Bluetooth Application Layer development on Nexus Channel

Our first topic!
Here is a discussion that was already happening in emails about developing a Bluetooth Application Layer leveraging the existing Nexus Channel work by Angaza.

I’ll highlight a few distilled points from a recent email thread with Vaibhav that may be useful.

Nexus Channel Core is the application layer standard (a direct subset of OCF) that defines how devices expose resources to one another, and how that data is communicated between devices at the presentation layer (via CBOR, also specified by OCF). Application developers on any device (from Cortex-M0 based MCUs to full fledged laptops or smartphones) are able to implement standard ‘resource models’ for common functionality. An introduction of these ‘models’ can be found here: Nexus Channel Models, and the spec for writing a new resource model is here for developing a new resource model. That spec has certain conventions in place (entire resource representation in CBOR < 120 bytes) intended to ease use over the OpenPaygo Link wired connectivity between devices (and ensure that the largest number of devices implementing Nexus Channel Core could also read/interact with the same resource). Assuming the underlying link layer was OK transporting more data, you could of course increase the amount of data exposed by a single resource to a GET request.

Nexus Channel Core makes no assumption of cloud connectivity (does not expect or require a device to ‘talk to a central server’), and requires only a way to communicate data between devices in the field to function.

There is also an application security layer Angaza offers on top of “Nexus Channel Core”, when that security layer is used, the resulting solution is referred to as “Nexus Channel”. Basically, it defines a few new security-oriented resources (to manage cloud-driven, ‘secured links’ at the application layer between devices). It also allows sending custom commands from a server to a ‘controller capable’ device (typically via a token/keycode) which allows it to interact with other ‘accessory capable’ devices nearby to establish a secure link. Once the secure link is established, the devices can interact with one another ‘securely’ (messages are authenticated, replay attacks are prevented, etc). This is accomplished by introducing a security-layer between the incoming messages (GET/POST) and the eventual ‘resource’ they are heading to, and checking if the resource
is secured, and if so, ensuring the link is established with the requesting device, and the message is valid (authenticates using the link security key/info). This, combined with a PAYG Credit resource that only allows ‘POST’ requests from ‘linked/secured’ controller devices, enables certain PAYG use cases.

Just like Nexus Channel ‘security’ adds some context at the application layer (the notion of ‘controller’ and ‘accessory’ capable devices, and ‘secured links’ between them, as well as ‘securing’ GET or POST requests to certain resource types), other application level functionality can be layered on top of Nexus Channel Core. Nexus Channel Core focuses entirely on enabling devices to share application-level information in a common language (CoAP GET/POST to standard resource models definitions implemented by other devices, which return a CoAP response). The presentation layer is specified (CBOR) as well as partially a network layer (devices implementing Nexus Channel Core devices may have Nexus IDs, which can be represented as a permanent, universally valid IPV6 address - allowing devices to send commands to specific other Nexus IDs). There is a valid registered block of addresses in ARIN which can be used for applications that need to provide globally-unique and valid addresses to Nexus Channel Core devices (such as a server wanting to send a command to a ‘specific’ device running Nexus Channel Core - if it knows the Nexus ID of the target device). This also allows for use cases where a gateway might share the ‘connected’ Nexus Channel IPV6 addresses with an authorized server, to indicate what specific devices are conncted. Those IPV6 addresses could also be exposed by the gateway to allow a server to ‘communicate via HTTPS to an IPV6 address’ to the gateway, which then translates the messages down into Nexus Channel Core to send to the devices.

Its important to note that Nexus Channel Core is separate from the link and transport layers that connect devices (whether wirelessly or wired), and relies on some standard connectivity at that layer between the devices - in order to transmit application-layer messages between them. OpenPaygo Link is our current recommended wired link and transport layer, and we’d be interested in exploring how OpenPaygo Airlink could serve an equally important role as the standard link/transport layer for Bluetooth devices implementing Nexus Channel Core application layer resource interoperability.

Hey Josh
thanks for joining the community and posting the recap, really appreciated!

Would this be the fc00::/7 space? Or has Angaza specifically requested an addressing space for its iot devices on the global internet?

Further, is there value in maintaining a device registry specific to this interoperability initiative?

Would this be the fc00::/7 space?

While fc00::/7 is intended for private/local use the Nexus CIDR block is actually a public, globally addressable /48 block. You can check out the registration details for the “Nexus” IPV6 block via a whois:

 whois 2620:89:6000:0:0:0:0:0

You should see something like:

NetRange: 2620:89:6000:: - 2620:89:6000:FFFF:FFFF:FFFF:FFFF:FFFF
CIDR: 2620:89:6000::/48
NetName: NEXUS
NetHandle: NET6-2620-89-6000-1

If devices choose to implement Nexus Channel Core, they can have globally unique Nexus IDs which are also able to be made into globally unique, completely legal IPV6 addresses, allowing global addressing of devices without any NAT (of course, assuming the devices are internet connected, which many devices are not at this stage).

Nexus IDs are composed of 6-bytes (48 bits) split into two parts (described more below), and can be converted into a valid IPV6 address using EUI-64 expansion (same as MAC address expansion, described in RFC 2373).

The ‘who sent it’ is answered by each device having a “Nexus ID”, generally a permanent ID which is burned in at time of production (doesn’t matter how, but it does need to be globally unique). The Nexus ID is 48-bits, split into the following format:

  • Upper 2 bytes: uint16_t value representing " authority id"
  • Lower 4 bytes: uint32_t value representing 'device_id"

The general concept is that an ‘authority ID’ maps back to some party which is guaranteeing there are ‘no collisions’ within that ID space, so there won’t be any two devices with the same authority ID and device ID globally (generally speaking, although see authority ID 0xFE80 below for a special exception which is not intended for universally unique use).

The ‘authority IDs’ that are defined so far are:

  • 0xFFFF = reserved for development/testing (anyone can use or make IDs in this space in a pre-production/testing context)

  • 0x0000-0x00FF = reserved for core ‘GOGLA related’ use cases currently, including a ‘globally unique’ PAYG ID scheme. Authority IDs in this range are authorized to translate their Nexus ID into a globally valid IPV6 address within the Nexus CIDR block.

  • 0xFE80 = reserved for dynamically assigned Nexus IDs (e.g. nexus IDs that aren’t globally unique, e.g. if your link layer has a scheme where it dynamically assigns identities to devices that have no factory assigned ID or outside world mapping to those device IDs, you can use this authority ID). Selected to be semantically

  • 0xFFxx = Currently reserved as a special ‘broadcast designator’, that is only used as a destination address when a Nexus Channel Core device is broadcasting. May be ignored (in most cases, it will just translate to whatever ‘broadcast’ address/scheme is used by the link layer). The bottom byte is variable ‘xx’ so that in the future, its possible to add some scope context to the multicast if required (right now, the reference implementation uses 0xFF02, assuming something similar to a ‘link local’ broadcast, so we chose to stay semantically similar to the IPV6 spec, even though a bare Nexus ID isn’t an IPV6 address…). But again, we’d expect most link layer implementations to just see ‘authority ID begins with 0xFF, ok, this is a broadcast’ and ignore the rest. (the API also includes a ‘broadcast flag’ so the dest address can just be completely ignored in that case, as well).

Further, is there value in maintaining a device registry specific to this interoperability initiative?

I suspect so! For the specific universal PAYG ID use case, we’re working with GOGLA to make the existing work around universal PAYG IDs more widely available. Its certainly possible there is value in another, non-PAYG related device registry also leveraging the Nexus ID scheme.

However, do you mean a device registry related to permanent Nexus IDs (/IPV6 addresses), or device as a model that collects a certain ‘set’ of ‘resource types’ (e.g. a ‘fridge’ is a device that implements the ‘temperature’ and ‘capacity’ resources, or something like that)?

This diagram from the documentation submitted to ARIN for the Nexus IPV6 block may be helpful as well - it explains how even though the devices on a local network might not speak ‘IPV6’, a gateway can still be “IPV6 aware” and translate the “Nexus ID” of devices on the local network (on a constrained link/transport layer) to “IPV6” for addressing by the outside world, by placing those 48-bit Nexus IDs into valid IPV6 addresses in the Nexus CIDR block.

(Of course, since the ARIN block wasn’t granted at this point, the diagram shows a nonsense “2001:db8:1234” space, the actual Nexus granted block is 2620:89:6000).

Thanks for this great set of information. What types of use cases are foreseen/in use for PAYG/IoT devices that require them to be on the global internet?

Hi Vaibhav,

Essentially, the representation of the Nexus ID in IPV6 its just a convenience to allow the devices to have an IPV6 if there are other use cases (perhaps unrelated to PAYG at all) on the device that a developer might want to have a unique address to identify a device by. Because there is already space purchased and allocated for the purpose, its possible to choose to just use the Nexus ID directly as an IPV6 address (rather than needing to purchase or otherwise obtain a separate block for the same end result).

In the drawing above, it should also show how the Nexus ID can be used as a link-local unique IPV6 as well (allowing use of the ID as a direct way to address devices for systems that are already connected in a way that supports IPV6 addressing, e.g. something like RFC 7668 IPV6 over BLE)

I don’t foresee any immediate uses of a globally unique IPV6 address for PAYG use cases (as most of what we’re seeing so far are devices either directly connected to a specific backend, or via a gateway to the same effect, and ‘accessing’ the device is typically through some interface on that backend/server).

Hi @jjmilburn @benjamin.david , we have a first-pass Bluetooth device resource model up at AirLink Devices

Your thoughts would be appreciated! Several questions:

  1. Does it look like we’ve understood the current interoperability work sufficiently?
  2. Do the Bluetooth characteristics/Resource properties make sense the way they’re shown?

Note that we decided to not use IPV6 but instead have a numeric device registry specific to each manufacturer since all Bluetooth sellers have to register anyway.

Thanks for sharing this, Vaibhav! I’ll try to make a few comments based on the interaction between Nexus Channel and AIrlink, and maybe ask a few questions along the way. In general, it looks like (correct me if I’m off here) that Airlink is built around sort of ‘bundled’ resources, that is, a number of distinct, conceptually separate resource types (client info, PAYG credit, device status, etc) are exposed together as ‘one’ Bluetooth service. That makes sense, if I’m reading the first part correctly here! I think it would be great to capture any new info/actions that can be shared between devices (client info related, or OpenPaygo Token Entry, for example) as distinct resource types, and add them to the resource type registry:

Then, they’d potentially be able to be used in multimode (a gateway supporting both Airlink devices and OpenPaygo Link devices simultaneously, for instance) or non-Airlink integrations (OpenPaygo Link only) as well. That might also simplify the Airlink spec a bit, by allowing you to specify what resource types (and what attributes of those resource types) are exposed on each service, rather than writing back out individual attributes in the spec.

I’m going to go a bit deeper on a few aspects of the spec here:

Advertising Packet

The constraint on size for this packet does make the ‘custom format’ pretty important - I understand the preference here to not publish the keys for resource properties in the packet each time (e.g. you’re able to parse the value of ‘adf’ by position only, no need to send the key ‘adf’ as well). The note about the gateway expanding this out into a ‘proper’ resource (with key names for each property value) makes sense in that context, to me at least. Related to this, I’m not sure that an ‘rtr’ is necessary in the advertising packet – this isn’t exposing a valid resource (or collection of resources), as there are only values, no property keys here (however, the ‘decompressed’ representation of the resource that the gateway creates might have an rtr?).

Without making ‘adf’ (or an equivalent version field) mandatory in the packet, it may become difficult to coordinate parser versions for the advertising packet over time. Specifically, if the ‘adf’ isn’t mandatory, it might be difficult to figure out what ‘version’ of the advertising packet that different devices using different iterations of Airlink are sending. Suggest making the ‘adf’ field mandatory, and maintaining an ‘official’ Airlink list of packet contents for each ‘adf’ version that you end up defining (e…g ‘adf=1 exposes these properties from resource type A, these properties from resource type B, etc).

Consider making this advertising packet a fully-compliant CBOR array, so that the data can be parsed with standard CBOR parsers. Consider restructuring the packet so that the version/format identifier (‘adf’) come first, so that a parser can always interpret the first two bytes as ‘adf’ version, and pass the remaining packet data to an ‘adf’ version-specific parser as needed. Related to this, you could consider using the integer representation of timestamps (based on the Linux epoch in UTC), which doesn’t introduce any MySQL dependence, and take up less space than the MySQL representation.

For example, here is an annotated version of the advertising packet that can be read by a CBOR parser directly, that has all of the information currently specified in the “PUE Advertisement”, and is 23 bytes long:

Diagnostic format:

[54321, 4210818301, 21, 55, 129, 1629830325, 65340, 15]

Raw Bytes/CBOR encoded (23 bytes):


88 # array(8)
19 D431 # unsigned(54321) - first element = adf
1A FAFBFCFD # unsigned(4210818301) - 'did' (4-byte/uint32 device ID
15 # unsigned(21) - 'err' device error
18 37 # unsigned(55) - 'ds' device status
18 81 # unsigned(129) - 'fv' firmware version
1A 61253CB5 # unsigned(1629830325) - 'pts' in seconds since the epoch
19 FF3C # unsigned(65340) - 're' (cr) PAYG credit remaining
0F # unsigned(15) - 'un' PAYG credit units

I understand the need to keep advertising packets as short as practical to keep power consumption lower - so the cost of having to write a custom parser for that is arguably worth it if it keeps from needing to use extended advertising packets. The above is just an attempt to see what it would take to use a ‘standard’ CBOR array of values, so the parser only needs to know how to read CBOR (and how to interpret the adf), but the spec might already be there and I’m misreading it.

Related Question: Can devices that are not using PAYG enforcement use AirLink, or is it required that AirLink devices have some form of PAYG enforcement? I’m trying to understand whether it would be permissible to have an AirLink device in an installation which has no PAYG metering, but simply reports its own usage data (but maybe there are other PAYG devices connected to the same gateway). Depending on what your vision is and how tightly you want to scope the protocol, you might want to consider making some of the PAYG attributes optional on this advertising resource.

Another way to ask that question is - in addition to the current ‘adf’ format (which makes the PAYG-related attributes ‘mandatory’), do you think its feasible to consider future development/expansion of a new ‘non-metered’ advertising packet ‘adf’ (which would tell the parser to not look for PAYG attributes in the advertising packet) that a non-metered, non-PAYG device could use to participate in the same AirLink network? Even for PAYG devices, do you feel that sending this info in every advertisement is necessary, compared to simply querying the non-gateway devices when needed to check their PAYG credit (assuming that the gateway can determine whether they support PAYG credit or not by looking at nx/res).

Services and resource models

Looking over the existing Bluetooth services (PUE Use Service, Device Config Service, Device Discovery Services), it looks like these are essentially composed of multiple Nexus Channel ‘resources’ put together in a single resource (as the AirLink spec mentions, the OCF bridging guidelines also suggest this).

To separate concerns, how do you feel about filing those individual resources for addition to the Nexus Channel resource registry (giving them “Resource Type” IDs/rtrs) as well as filing for new ‘combined’ Airlink specific resource types (that are special resources made up of 2 or more ‘individual’ resources?). I know that OCF also has Composite Resource Types (Section 5.7), but I don’t want to suggest adding more overhead than necessary to the AirLink system - and the ‘composite’ approach would likely lead to an additional round-trip of data (e.g. one round trip to “GET” the composite resource, then another round-trip to “GET” the subresource), whereas defining AirLink specific ‘combined’ resources that take on all of the attributes of separate ‘individual’ resources can reduce the roundtrips.

I am not proposing making different characteristics or services than what the spec currently defines, I’m just seeing how you feel about trying to capture some of the separate groups of properties here as individual Nexus Channel resource types, to improve reusability and allow other developers to compose the pieces they might want/need for other use cases in the future.

Specifically, I’d suggest considering the following as resource types that might be added to the Nexus Channel Core Resource Registry, and assigning individual new RTRs to each of these device resources. Note that only GET and POST are ‘supported’ by Nexus Channel (based on the fact that existing OCF resources appear to avoid PUT for idempotent updates), but that really only matters for the Nexus Channel resource model definitions here, I think.

Separate Resource Types currently in Use by Airlink (as far as I can tell)

  1. New resource type - “Client Provisioning”

  2. [Required for POST, required on GET] Customer name (‘cn’)

  3. [Required for POST, required on GET] Customer phone (‘cp’)

  4. Sidenote: Does this need to exist on the device as a resource? It seems like something a backend would manage, not something that is ever pushed down to the device (e.g. at registration, a backend associates device A with client B). You might be able to eliminate this entirely unless the non-gateway device itself needs to store this info to make some decisions (rather than a backend simply storing an association between that client and the device).

  5. New resource type - “Device Provisioning”

  6. [Required] 6-Byte Device ID

  7. [Required] Provisioning Status (‘pst’)

  8. [Optional] IoT Backend Type (int enum, e.g. ThingsBoard, etc)

  9. [Optional] IoT Backend Auth Token (‘sat’)

  10. New resource type -“OpenPaygo Token Entry”

  11. [Required] Token String

  12. [Required] Last token received - note, you might consider using ‘seconds since last token entered’, to avoid needing to keep track of / sync actual clock time across devices.

  13. (required) ‘lcr’ last added PAYG credit (this is not applicable to general PAYG use cases, as credit is not always added, it might be subtracted or directly ‘set’ to a value - but this might be a good property of this new ‘OpenPaygo Token Entry’ resource if its something you need)

  14. New resource type - “Device Health/Status” , to capture the error data mentioned in the spec.

  15. Device error (err)

  16. Device erd

  17. PAYG Credit Resource

  18. Consider using the existing draft PAYG resource type model, but further constrain it in AirLink to only certain units and ranges (e.g. AirLink will not report PAYG credit units > 65535, e.g.). Existing resource model draft has PAYG units and PAYG credit remaining as ‘required’ fields.

  19. If the existing draft resource model won’t work, consider extending it with AirLink specific optional properties, or creating a new resource model if the paradigm is too different

  20. Some fields in the Airlink spec are specific to OpenPaygo Token or token PAYG credit management in general, and would be better added to the new ‘OpenPaygo Token Entry” resource, rather than the general PAYG resource (e.g. starting code, last entered token, last entered token value, etc)

  21. Power Used/Consumed - Consider reusing or revising the energy consumption resource type to accommodate the relevant info provided by PUE timeseries resource

  22. Power Generated - Consider reusing or revising the energy generation resource type to accommodate the relevant info provided by PUE timeseries resource

  23. Productive Use Info - Consider a resource that provides this info, but also consider - would it be possible to separate this into something more specific, e.g. a ‘pump’ resource that indicates flow? If not, it might make sense for the productive use metric to include units/productive use machine type.

  24. Battery - Consider using the existing battery resource type fields besides ‘vb’ and ‘cp’. For example, if ‘ft’ (fault) is insufficient to meet the use case you see for ‘bh’ (battery health), suggest extending/improving the existing battery resource to have a new optional ‘bh’ field. Similar for ‘pmax’,‘pmin’, and ‘tchg’ (consider extending the existing battery model with these properties).

  25. Consider using ‘ss’ (‘seconds since’) instead of ‘ts’ (absolute/UTC timestamp): This might depend on the Airlink device capabilities, but as specified, the assumption appears to be that Airlink devices all have a fairly accurate notion of the global wall-clock time. More constrained devices won’t always have an accurate wall clock, but can generally keep track of elapsed real time (seconds) in smaller increments (minutes/hours at a time). By specifying sample times in ‘seconds since sampled’ rather than timestamps, you would reduce the transmitted size (from 6 bytes down to just 1 byte, for samples taken in the last few minutes), and also support more constrained devices. Of course, the gateway device could still easily convert the ‘seconds since sampled’ into a wall-clock sample time (assuming there is fairly small, e.g. under a few seconds latency, between gateway requesting data from a non-gateway device, and the non-gateway device responding).
    Related question - is the notion here that ‘ts’ represents the timestamp of all information in the PUE resource, so the measurements must all be taken at the exact same time?

  26. Location - consider introducing a new Nexus Channel resource type in the registry that has lat/long/accuracy, with room for that ‘array’ (for historical values?) mentioned in the Airlink spec.

  27. Historical time series data - There is an existing resource type draft (‘samplelog’) that provides one way to expose a series of sampled data as a Nexus Channel resource. However, its just a draft - I’d suggest we try to use it here, or update the resource type to meet your exact needs.

If the above understanding of ‘separate’ resource types is correct (check me on that), then is it correct to say that the PUE resources are composed as follows?

PUE Timeseries Resource Type, contained subtypes

  • (existing) Battery
  • (new) Location
  • (existing) Power Generation
  • (existing) Power Consumption
  • (new) Productive Use
  • (new) Device Health/Status

PUE PAYG Resource Type, contained subtypes

  • (new) OpenPaygo Token Resource

  • (new) Device Provisioning Resource

  • (Existing) PAYG credit resource

PUE Provisioning Resource Type, contained subtypes

  • (new) Client Provisioning
  • (new) Device Provisioning
  • (new) OpenPaygo Token resource

Security and PAYG Credit Management - Sidenote

The approach to transmit credit via tokens to each individual device is possible (e.g. OpenPaygo Token Entry resource type), but there is another approach that lets you push updates (PAYG or otherwise) to the devices without needing to send tokens, while still remaining secure against replay and MITM attacks. This is the functionality provided by Nexus Channel Links. Basically, these provide application layer security between devices by using a secure key negotiation mechanism (secure as in no keys or cryptographically sensitive data are transmitted between the devices), after which two devices have a derived shared secret ‘link’ key (unique to the link between those two specific devices). That key is used to secure request/response messages (by providing a monotonically increasing nonce, and generating/appending a MAC generated using that nonce, the message payload, and the CoAP type code). The secure link is established between two devices when a ‘controller’ device receives a specific ‘origin command’ (a token keyed specifically to that controller, with information that also lets it authenticate to the specific targeted ‘accessory’ to link to). The controller then initiates the link handshake process, and the target connected accessory to link either accepts/validates it, or does not. One the link is established, both devices use the newly derived (but never exposed on the wire) secret key to secure CoAP messages sent between them.

It doesn’t require any special manufacturer authorization/steps/process to set up the link compared to generating a PAYG keycode - the same 16-byte symmetric keys provisioned inside for token acceptance (OpenPaygo Token, Nexus Keycode, etc) can be used to enable accepting/validating origin commands to establish a link.

This security is independent of any lower-level transport security (or Bluetooth pairing), and ensures that two ‘linked’ devices can securely communicate regardless of their connectivity mode (OpenPaygo Link, AirLink, CAN, etc).

You can see this in action with two dev boards here: Nexus Channel Link Security Hardware Demo - YouTube , although the code shown there hasn’t been pushed to the public repository yet (we’re looking to coordinate it with another release).

That video (and the reference code) demonstrate using Nexus Channel links to send secured request messages from a controller device to accessory devices, and handle secured responses sent back - specifically, the accessory devices are configured to only accept secured POST requests to their PAYG credit resource (ignoring unsecured ones).

So, you might want to consider reusing that functionality, and only keeping the OpenPaygo Token entry on the gateway device if you need it for a backup to deliver credit if the gateway internet access is out - or just skipping PAYG credit token support entirely if you can rely on pushing credit updates for each device from the backend to the gateway. As long as the gateway has secure links established to each other Airlink device (which is done via interaction between the ‘link handshake’ resource of the gateway/controller and each downstream ‘accessory’ device), you can rely on MITM and replay-resistant control of PAYG credit to each downstream device with no token entry needed.

hmm, the numbering seems to be off on the resource types and their attributes…

Hi Josh, this is a great set of comments and suggestions and I made sure to first digest them within our team before posting here. I’ve already incorporated quite a few of the suggestions, so let’s keep this discussion going:

  1. "In general, it looks like (correct me if I’m off here) that Airlink is built around sort of ‘bundled’ resources, that is, a number of distinct, conceptually separate resource types (client info, PAYG credit, device status, etc) are exposed together as ‘one’ Bluetooth service. "
    This is true - in general for Bluetooth we’re considering ourselves link-poor i.e. we don’t reliably know if a connection will occur. We’re also considering inventory management cases e.g. where one gateway connects to many devices to update them, and hub cases where a central wireless GSM hub connects to and updates several device’s payg status. So we’re minimizing the number of characteristics and services and choosing to bundle similar items, as all 3 cases are different from wired connections (which are reliable and one-to-not-many).
    So although we reuse the terms from other resources e.g. battery voltage vb etc, we’ve bundled those with other use items, based on when we think the update will take place e.g. during provisioning, during timeseries updates, during payment etc. Splitting up the resource models would mean several Bluetooth interactions and we wanted to avoid the O(nxm) interactions if possible. Composite resource types seem onerous for a gateway to process so we’ll leave that out for now.
    So a new manufacturer with a modified PAYG resource would extend the base resource instead of defining their own smaller resource while reusing ours. Do you think this causes unnecessary resource proliferation?

  2. adf and advertising - this makes sense, we’ve put this to the top and also collapsed the entire packet into one regular CBOR array - we found that changing the timestamps to unix and removing rtr etc saved us a couple octets which we could then use for the additional CBOR headers.
    Also made the payg bits ‘optional’ - in that we have default values. We realized that none of the advt packet is really optional because it goes as one fixed width item. So optional items just need predefined defaults.
    Hope the new version looks cleaner.

  3. Services and resource models - We’re proposing that we use the nx/res discovery resource and extend each line to include the characteristic UUID as well as Bluetooth Service UUID where that resource is bundled. Do you think that’s a sufficient implementation? To reduce data size on the nx/res below the practical 100 byte BLE limit, we’re also thinking of using a base UUID and varying only a smaller section for each characteristic/service

  4. Client provisioning - this came as a request from our clients, some of our prototypes had a display and they want their name to be shown on it to discourage theft or to identify their devicess from a sea of others (e.g. our fishing lights are often lumped on a beach by several clients). of course this introduces additional server-device syncs. What do you think?

  5. your comment on payg product type being included is spot on, we’d need a registry for those too though.

  6. Combination of resource types and subtypes - This might be ok but it might make it harder to devices to comply if a subtype changes, any thoughts on that? Could we do this, but base them loosely and not lock them to the sub-types? Do you have any strong ideas one way or another?

  7. On security and credit management - we’re prototyping with a ‘thingsboard.io’ server, which registers each device with an auth token during provisioning. Both device and server have the auth token, and a gateway needs to know the auth token to register for the device. So there’s some potential for MITM there, and your additional device-pair links would help. But again those links work well for preset device pairs, whereas we’re thinking of more ad-hoc pairings. So authentication is always between server and end device (OpenPAYGO token), with gateway only transmitting data and being able to see use data. So the only protected resource in our case is PAYG credits (and provisioning via server auth token). This makes the one-gateway-to-hundreds-of-devices cases more tractable.

Do you see a specific advantage in an app-layer authenticated link for all data transfer? Do you see it working well for one-gateway-to-very-many-devices cases? Anything remiss there from my understanding?

I’ll post another doc update once I hear your thoughts on these.

1 Like

Updated numbering formatting for section: “Separate Resource Types currently in Use by Airlink (as far as I can tell)”

  1. New resource type - “Client Provisioning”

    • [Required for POST, required on GET] Customer name (‘cn’)
    • [Required for POST, required on GET] Customer phone (‘cp’)
    • Sidenote: Does this need to exist on the device as a resource? It seems like something a backend would manage, not something that is ever pushed down to the device (e.g. at registration, a backend associates device A with client B). You might be able to eliminate this entirely unless the non-gateway device itself needs to store this info to make some decisions (rather than a backend simply storing an association between that client and the device). Edit - based on your comments, it sounds like you do want this stored on the devices so the name can be displayed in the field. Understood!
  2. New resource type - “Device Provisioning”

    • [Required] 6-Byte Device ID
    • [Required] Provisioning Status (‘pst’)
    • [Optional] IoT Backend Type (int enum, e.g. ThingsBoard, etc)
    • [Optional] IoT Backend Auth Token (‘sat’)
  3. New resource type -“OpenPaygo Token Entry”

    • [Required] Token String
    • [Required] Last token received - note, you might consider using ‘seconds since last token entered’, to avoid needing to keep track of / sync actual clock time across devices.
    • (required) ‘lcr’ last added PAYG credit (this is not applicable to general PAYG use cases, as credit is not always added, it might be subtracted or directly ‘set’ to a value - but this might be a good property of this new ‘OpenPaygo Token Entry’ resource if its something you need)
  4. New resource type - “Device Health/Status” , to capture the error data mentioned in the spec.

    • Device error (err)
    • Device erd
  5. PAYG Credit Resource

    • Consider using the existing draft PAYG resource type model , but further constrain it in AirLink to only certain units and ranges (e.g. AirLink will not report PAYG credit units > 65535, e.g.). Existing resource model draft has PAYG units and PAYG credit remaining as ‘required’ fields.
    • If the existing draft resource model won’t work, consider extending it with AirLink specific optional properties, or creating a new resource model if the paradigm is too different
    • Some fields in the Airlink spec are specific to OpenPaygo Token or token PAYG credit management in general, and would be better added to the new ‘OpenPaygo Token Entry” resource, rather than the general PAYG resource (e.g. starting code, last entered token, last entered token value, etc)
  6. Power Used/Consumed - Consider reusing or revising the [energy consumption resource type] (Nexus Channel Redoc Wrapper) to accommodate the relevant info provided by PUE timeseries resource

  7. Power Generated - Consider reusing or revising the energy generation resource type to accommodate the relevant info provided by PUE timeseries resource

  8. Productive Use Info - Consider a resource that provides this info, but also consider - would it be possible to separate this into something more specific, e.g. a ‘pump’ resource that indicates flow? If not, it might make sense for the productive use metric to include units/productive use machine type.

  9. Battery - Consider using the existing battery resource type fields besides ‘vb’ and ‘cp’. For example, if ‘ft’ (fault) is insufficient to meet the use case you see for ‘bh’ (battery health), suggest extending/improving the existing battery resource to have a new optional ‘bh’ field. Similar for ‘pmax’,‘pmin’, and ‘tchg’ (consider extending the existing battery model with these properties).

    • Consider using ‘ss’ (‘seconds since’) instead of ‘ts’ (absolute/UTC timestamp): This might depend on the Airlink device capabilities, but as specified, the assumption appears to be that Airlink devices all have a fairly accurate notion of the global wall-clock time. More constrained devices won’t always have an accurate wall clock, but can generally keep track of elapsed real time (seconds) in smaller increments (minutes/hours at a time). By specifying sample times in ‘seconds since sampled’ rather than timestamps, you would reduce the transmitted size (from 6 bytes down to just 1 byte, for samples taken in the last few minutes), and also support more constrained devices. Of course, the gateway device could still easily convert the ‘seconds since sampled’ into a wall-clock sample time (assuming there is fairly small, e.g. under a few seconds latency, between gateway requesting data from a non-gateway device, and the non-gateway device responding).
      Related question - is the notion here that ‘ts’ represents the timestamp of all information in the PUE resource, so the measurements must all be taken at the exact same time?
  10. Location - consider introducing a new Nexus Channel resource type in the registry that has lat/long/accuracy, with room for that ‘array’ (for historical values?) mentioned in the Airlink spec.

  11. Historical time series data - There is an existing resource type draft (‘samplelog’) that provides one way to expose a series of sampled data as a Nexus Channel resource. However, its just a draft - I’d suggest we try to use it here, or update the resource type to meet your exact needs.

The above are my current best attempt to pull out the atomic ‘resource types’ that we’d be adding to the Nexus Channel Resource Type Registry - with the understanding that Airlink “Resources” simply pick and choose certain properties of each resource as needed. I think this is potentially easy to accomplish (?) by just specifying the following for each Airlink resource property:

  • What ‘core/atomic’ resource type model is this property mapped to?
  • What version of that resource type model was this based on (e.g. 0.7.1?)

Now, that info wouldn’t be part of the transmitted resource model, but you could include an ‘adf’ style field in each of your resources, allowing you to update/change them as needed for future expansion.

Regarding:

  1. Combination of resource types and subtypes - This might be ok but it might make it harder to devices to comply if a subtype changes, any thoughts on that? Could we do this, but base them loosely and not lock them to the sub-types? Do you have any strong ideas one way or another?

With the above, I’m not sure that there is any risk of falling out of compliance with the published subtypes, because (in the Airlink spec, not necessarily transmitted on the wire) you can pin to specific published versions of any resource type (which are all version controlled in Git anyhow).

Additionally, the Nexus Channel Resource Type Registry currently attempts to use semantic versioning. You’ll note that all of the resources there are pre-1.0. So, giving a solid ‘backwards compatible’ resource type model for subtypes used by Airlink would probably be a good enough reason to version-up to 1.0 (we’ll at that point have both in-progress wired implementations and future Airlink implementations able to match up to the same resource type models). Once we hit version 1.0 on a resource model, breaking changes (changing property key names, required values, etc) cannot be published without bumping the major version (e.g. 1.0->2.0).

Edit - I do want to respond to the other points - those are great! I want to talk a bit more with our team over here, but should have something back this week…

Thanks Josh. I had another question relating to the app-layer link- would the only needed enabler at the BLE level be a fully encrypted CBOR property called ‘command’ that accepts a longer token and that a nexus channel compatible device can use to interface with an app-layer link?

This way we could have the simpler BLE link as well as the BLE+App-layer link coexist. If there’s an app-layer link, it also makes it less important that the BLE characteristics/services map to resource models since those would be composed/transmitted within the encrypted app link. Am I understanding this correctly?

Hi Vaibhav,

These are great points. I will respond with the same numbering you used for organization:

  1. The goal of combining various properties from various resource types into a single Airlink resource (or resources) to reduce BLE transactions makes sense, I think we are aligned there. For lack of a better term, I’ll refer to those as ‘combined’ resources for now. My only comment is that it probably makes sense to define in the spec which resources and which properties from those resources are being used in each Airlink ‘combined’ resource so that its easy to refer back to the Nexus Channel Resource Type Registry and identify the same information being sent/received, rather than creating ad-hoc properties that aren’t tied to any registered resource.

I’m not sure that I understand the point about a new manufacturer with a modified PAYG resource - can you elaborate? We’d anticipate that the PAYG Credit Resource Type could be used, and a new manufacturer who had a need for new optional properties (beyond credit remaining and units of credit) could implement those as needed, without any proliferation of resources. For example, maybe a manufacturer needs to track a property ‘seconds since PAYG credit was last updated’, so they push a revision to the PAYG credit resource type model that adds a new optional ‘ss’ property (increasing the revision of the PAYG credit resource type), and they use that revision. If you chose to use that new property in Airlink, I’d anticipate an Airlink spec update that indicated the new property, and noted that the PAYG credit resource type version number being used was the newly updated version. Am I following your reasoning, or am I missing it?

  1. Regarding ADF, that makes sense. Thanks!

  2. Yes, for discovery on Airlink, providing the UUID makes a lot of sense (as you’re not handling CoAP messages, but using BLE services directly, per the bridging spec) if you know and can enforce the base UUID so that the discovery resource ‘nx/res’ can unambiguously determine what Airlink resource maps to what UUID. I’m not sure if its possible to ‘vary’ the last few bits of a characteristic UUID without registering it, though – my understanding is that BLE UUIDs must be completely regenerated for each new UUID unless registering, but I suspect you’ll have more knowledge on this point. Also, would the ‘nx/res’ resource basically be defined by a fixed/hardcoded UUID that all Airlink devices know? (that seems to make sense, I’m just checking my understanding).

Related to this point, does it make sense to include a version property in the Airlink resources, so that if you do version up a resource/service, someone can determine that? Or, will the advertised ‘adf’ be an ‘overall’ version that increases whenever the advertising packet changes or any Airlink resource version/format is updated?

  1. No objection from me - I was just curious as to whether it needed to live on the devices or not, and it sounds like it does. So, my suggestion to register this ‘client information’ as a new Nexus Channel resource type still stands. Is it just client name and phone number for now? I can help put a draft PR up (https://github.com/angaza/nexus-channel-models/pulls) or help you do it if you like! We can then get it assigned an RTR (even though its only being used in Airlink for now, just for future use - and it also lets you indicate in the Airlink spec that the client-related attributes are coming from the client information resource type, rtr=XYZ, etc)

  2. I think I may have confused myself here :). Can you help me understand what I proposed in this regard as you understand it?

  3. I think I mentioned this in the previous response, but since the resource types intentionally only have a very minimal number of ‘required’ fields, I think you are fairly safe from changes here. Additionally, once resource types are at 1.0, there cannot be breaking changes without changing the major version number (unlikely to happen without significant industry pressure, I’d think, plus, the Airlink spec can simply say ‘this Airlink resource is compatible with PAYG credit resource type version 1.X.X’, etc).

  4. That makes sense, and it was helpful to think about the hundreds-of-devices-to-one gateway you mentioned. Do you imagine many gateways connecting to one non-gateway device over its lifetime, or is it primarily one gateway to hundreds of non-gateway devices?
    The reason I ask is that there is nothing preventing the server/backend from dynamically creating ‘ad-hoc’ Nexus Channel links between a gateway (or multiple gateways) and non-gateway devices. Basically, it would just need to send an “Origin Command*” to the gateway device, which then validates it, and begins to initiate a link with the accessory devices nearby (e.g. advertising or otherwise), causing the appropriate device to validate the link and confirm it - allowing secured data to then move between the devices via the app-layer security. But nothing about that link makes it inherently long-lived, or prevents a non-gateway device from being linked to many gateways.

Note: The app-layer security operates on a resource/method pair, that is, the application code registers a resource/method as ‘secured’ or ‘unsecured’ with the app security, which then intercepts any incoming request/response messages and validates them before passing them on to the resource method handler. This is done so that its possible to, for example, secure the POST requests made to a PAYG credit resource, but leave the GET method unsecured, so no link is required to simply inquire how much credit is remaining (if desired). Similarly, you could leave the usage data collection requests as unsecured, allowing easy passage of data from non-gateway to gateway devices on the way to the server (depending on the sensitivity of the data).

One advantage of having app-layer security there is that you can easily add more ‘secured’ configuration updates or commands in the future without needing to generate special tokens for each device. E.g. once a gateway has a secured link to a non-gateway device, you can simply define a resource on the non-gateway device that has a secured method (in the Airlink case, I imagine it would be the PUT operation on a specific BLE service that hosts sensitive info that should only be changed by an authorized party). Then, data that is PUT to that resource is run through the app security handler which validates it before passing it on to the handler.

Before recommending for or against that approach, though, I’d want to understand more about the Airlink use cases and the number of round-trips via BLE that are currently required, how likely it is that a gateway will ever need to securely communicate to the same non-gateway device again in the future (are most gateway → non gateway interactions one-time only?), etc.

8.: that linked example carries an origin command in Nexus Keycode, but there is nothing preventing an origin command from being without Nexus Keycode involved at all.

App Layer Nexus Channel “Passthrough” on BLE

Regarding the app-layer link at the BLE level - yes, its possible to enable this by exposing a property that accepts opaque, binary messages up to 120 bytes. These are actually not only CBOR, but CoAP messages with either a CBOR or COSE payload (secured messages use a COSE payload, which the app security layer verifies and extracts).

So, yes, regardless of security or not, it would be possible to pass Nexus Channel messages over BLE by enabling a property that accepts up to 120 byte messages. Then, those can be passed to a CoAP parser, which then determines the content format (CBOR or COSE) based on the content-format element of the CoAP header. If it is CBOR, the payload is ‘unsecured’, and is passed directly to the relevant resource endpoint/method handler (if that resource method handler is registered as also unsecured). If the resource is secured, the CoAP parser will extract the payload and pass it to the app-security layer, which will verify/validate it, and extract and send on the payload to the appropriate resource method handler if needed.

It would also be necessary for the BLE layer to capture the Nexus ID of the sending device (so that the app security layer can look up links, which it does by looking for links by Nexus ID). Those are typically assigned in the factory, and are not the same as Bluetooth hardware IDs/MACs.

-this makes sense, I’ll rework the models to reflect and document

I think we’ll adopt your suggestion of versioning every resource, because that covers custom extensions per manufacturer without resource proliferation. An ‘adf’ for every property.

Yes exactly! On the other UUIDs, we’re wondering if they don’t need to be uniquely pre-registered per rtr, to reduce any data storage required by gateways. Each device would just report the internal combination of rtr and UUID within nx/res, that way the gateway can use the rtr value to access the same bluetooth service and not require a UUID registry.

I’ve split it out already in the uploaded airlink documentation as a ‘customer provisioning’ resource. I’m thinking it might also need a human-readable device serial number or payment reference added. Here’s the set proposed:

You had mentioned that the payg resource should include a product type e.g. water pump etc. That made sense.

So if I understand correctly, also relating to point #1, the overall suggestion would be to explicitly make the lumped bluetooth service a combination of the credit/generation/consumption etc nexus channel resources, and this would be ok as long as we move the spec of the component resources to 1.0. Coupled with the suggestion of versioning each airlink resource, yes I think this makes sense that we could have ‘Airlink 0.5 is compatible with A,B,C,D Nexus channel resources 1.0’ or such.
I think we should include this in nx/res itself, so that each resource’s version is known in case the gateway has some compatibility logic. Thoughts?

This is a potential use case for us to provide a gateway device as part of a package but also a cellphone which can cover situations when the gateway is not in cell-range. So each device could routinely be updated by two gateways. Other potential use cases are if we allow a local authority figure in a community to act as a backup in case someone’s phone is broken, to help update their credits. This is important in productive use cases since they don’t want to miss even a day of productivity and many of the customers are living hand to mouth.

I probably don’t understand enough about encryption to get how this works intuitively, and clearly you have given this some thought. Is there any documentation or example code available that you could point me to?

I could see where having example code for this kind of interaction would make this easier to adopt for someone designing a new device. Do you believe that this interaction is fairly optimal across different use cases and would become the de-facto standard? Or do you think manufacturers might develop their own application layer handshake (e.g. re-using the passthrough property in their own ways)?

We were thinking of using a uint_32 device ID per advertisement packet, would the Nexus IDs then be application layer IDs that are separate from the device ID?

1 Like

wanted to comment on this too - this makes sense. Although the device is not expected to know it’s own location but a gateway is expected to know the device’s location. Since a gateway may report on many devices (especially for the stolen device detection use case), in our calculus it made sense to include location along with an advertisement packet property posted to the server by a gateway. Interoperable gateways from other manufacturers as well as other client’s gateways from the same manufacturer would need to report this one combined property as part of enabling crowd-sourced stolen asset detection. All other properties e.g. PAYG commands could be optional to minimize data burden.

Even so, I don’t think it’s possible to mandate that an AirLink gateway always report any airlink device advertisement that it comes across, that would be too much to expect I think.

@jjmilburn I’m having some trouble understanding what the individual properties stand for in the documentation - Nexus Channel Redoc Wrapper

Specifically-
In PAYG Credit:
di = ?
In energy generation:
ft = only true/false? Can this be made into a full status so that we can use it for details?
eg, egs, egp = ?
Also, what are the units i.e. mA, mV or A, V etc?
In energy consumption:
ft = only true/false? Can this be made into a full status so that we can use it for details?
eo, eos, eop = ? in which units?
In battery:
ft = only true/false? Can this be made into a full status so that we can use it for details?
ca, ds, cg, lb = ? in which units?

Possibly this information is elsewhere?

Also, do you think we could extend the battery resource with optional properties for the 1.0 version that give the manufacturer some design feedback i.e.
LastChargeCycle BatPctMin “pmin”
LastChargeCycle BatPctMax “pmax”
LastChargeCycle ChgTime “tchg”
Bat Health “bh”
?