Skip to main content

bluetooth.setscanfilter(rules)

Specifies rules used to filter out unwanted advertisements during scans

Availability

Device (from impOS™ 38)

Parameters

Name Type Description
rules Array of tables A set of filter rules

Returns

Nothing

Description

This method applies a set of rules which can be used to ensure only required advertisements are passed to your application via the callback function registered with bluetooth.startscan().

Rules can be applied or changed on the fly. To remove or change a single rule, you will need to re-supply the remaining filters you wish to keep. To remove all filters, pass in an array containing a single, empty table, ie. [{}]. Including an empty table in the array sets a filter that matches all adverts. Passing just an empty array will block all messages.

Each filter table may contain any of the following keys, all of which are optional. If a filter has more than one key (eg. minrssi and type) then all keys must match for that filter to match.

Key Type Bounds Matches On Description
address String or blob 12 bytes See below IP Address
addresstype Integer 0 or 1 advert.addresstype == filter.addresstype Public or private
minrssi Integer -127—20 advert.rssi >= ilter.minrssi RSSI in dBm
type* Integer 0—4 advert.type == filter.type Advert type
data String or blob 0—31 bytes filter.data in advert.data**
collect Float or Integer > 0 Does not affect matching (see ‘Advertisement De-duplication’ below) Timer duration in seconds
collectmax Float or Integer > 0 Does not affect matching (see ‘Advertisement De-duplication’ below) Maximum number of collected items per timer

* This allows separate advertisement data processing for scan responses.
**The filter data string can appear anywhere within the advert data string. For example, the filter.data value “abc” matches “abc”, “123abc” and “1abc23”, but not “1ab2c3”.

address is a 12-byte hex string, with the addition that the underscore character defines a mask for ‘don’t care’ nibbles in the address. For example, “0123__67____” will match all addresses starting 0x0123 and with 0x67 in the third byte.

data is not interpreted by impOS in any way: it does not have to contain whole or syntactically valid advertising data.

Advertisement De-duplication

A filter with the collect and collectmax keys collects matching advertisements over a period of time and dispatches them to Squirrel when a timer fires. The timer is started on the first receipt of a matching advertisements. The value attached to the collect key is the timer duration in seconds. For each filter using this facility, impOS will maintain the timer and an array of matching unique advertisements. This array is no more than collectmax items in size. Each element in this array is expected to consume approximately 64 bytes of RAM.

The array will not be passed to Squirrel until the timer fires. If the array is full when a new advertisement is being added, a random eviction will be performed. This is done by choosing a random number in the range 0 to collectmax + 1 and removing that item, or dropping the new item if collectmax + 1 is chosen. This policy is fair and in high-traffic situations (stochastically) ensures Squirrel will eventually observe all matching advertisements.

To use the facility, both collect and collectmax keys must be provided.

This facility has the benefit of decreasing the number of Squirrel calls and duplicated data passed to squirrel, at the cost of adding latency to the receipt of those advertisements. Each batch of advertisement is passed to Squirrel with ordering intact: earlier unique advertisements which match a filter will appear before later advertisements.

Advertisement uniqueness is determined by equality of type, address, addresstype and data (RSSI is ignored; the latest seen RSSI and timestamp will be passed to Squirrel in each batch).

Example Code

The following filter accept advertisements from devices with either public addresses starting 123b, or a whole public address a1a2a3a4a5a6. Advertisements from other devices are ignored:

bt.setscanfilter([
  { address = "123b________", addresstype = 0 },
  { address = "a1a2a3a4a5a6", addresstype = 0 },
]);

The following filter accepts: - Advertisements from Quintic Corp devices (by matching their manufacturer ID), that have advert data containing a manufacturer-specific advert data packet. - Advertisements from any iBeacons with UUID "INSERT_UUID_HERE". - Advertisements from any iBeacons with UUID "A_DIFFERENT_UUID".

bt.setscanfilter([
  { address = "087cbe______", addresstype = 0,
    type = 3, data = "\x1b\xff\x05\x28\xbe\xacPRODUCT_NAME" },
  { type = 3, data = "\x1a\xff\x4c\x00\x02\x15INSERT_UUID_HERE" },
  { type = 3, data = "\x1a\xff\x4c\x00\x02\x15A_DIFFERENT_UUID" },
]);

Because the filter is included when the advertisements are passed to the callback registered with startscan(), this allows your Squirrel code to quickly and easily dispatch on different advert types:

bt.startscan(function (adverts) {
  foreach (advert in adverts) {
    if (advert.rule == 0) {
      handleAltBeacon(advert);
    } else if (advert.rule == 1) {
      handleiBeaconA(advert);
    } else if (advert.rule == 2) {
      handleiBeaconB(advert);
    }
  }
});

The following filter ensures Squirrel is not interrupted more often than every second, with up to 64 unique advertisements (randomly selected from those received):

bt.setscanfilter([
  { collect = 1, collectmax = 64 },
]);

The following filter accepts and immediately processes all adverts from the device with public address a1a2a3a4a5a6. All other adverts are batched up and dispatched to Squirrel every quarter of a second. This example shows balancing low-latency for certain devices, while limiting squirrel load caused by others.

bt.setscanfilter([
  { address = "a1a2a3a4a5a6", addresstype = 0 },
  { collect = 0.25, collectmax = 64 },
]);

The following filter de-duplicates occupancy sensor event adverts from a specific device (by address), adding 100ms additional latency. All other adverts are processed as normal.

bt.setscanfilter([
  { address = "087cbe112233", addresstype = 0,
    type = 3, data = "\x1b\xff\x05\x28\xbe\xacPRODUCT_NAME",
    collect = 0.1, collectmax = 1 },
  {},
]);