| REVISION CONTROL RECORD | |||
|---|---|---|---|
| VER | DATE | DESCRIPTION OF CHANGE | AUTHOR |
| 1.0 | 12/14/2015 | - Changed product names to be generic (ENGAGE™ device) | R.Verde |
| - Highlighted sections that need removed before sending to partners | |||
| - Removed Version 0 Advertising Data | |||
| 1.01 | 1/21/2016 | - Updated RSI - Lock control (0x10) byte 0 to add cache extended unlock and cache re-lock commands | J. Everson |
| 1.02 | 1/25/2016 | - Updated Special Use Case TLVs to add 0xC0 for reporting a Lock configuration change to the Gateway | J. Everson |
| 1.03 | 4/18/2016 | - Updated Gateway General Service (Section 6) with MAPP Directed Linking detail | Ankit P. |
| 1.04 | 6/07/2016 | - Added Deadbolt / Privacy Secure to lock state for TLV lock status | J. Everson |
| 1.05 | 8/16/2016 | - Added Device Types for Schlage Sense and Denali | S. Venkateswaran |
| 1.06 | 8/17/2016 | - Renamed lock to device throughout document | J. Evenson |
| - Added clarifications for exit dogging state with lock states | |||
| - Added device exception column on a couple of tables | |||
| 1.07 | 10/13/2016 | - Update DPS Calibration Characteristic | S. Thaker |
| - Update IP_ADDRESS characteristic to report error in DPS command | |||
| 1.08 | 11/11/2016 | - Addition of data transfer resume feature | A. Setter |
| 1.09 | 01/25/2017 | - Addition of database BLE Resume Feature | S. Thaker |
| 1.10 | 03/01/2017 | - Addition of exit device states within 0x97 Tag | D. Pfunder |
| 1.11 | 03/21/2017 | - Adding CTE product | J. Everson |
| - CTE specific Advertising Data | |||
| - CTE device exclusions | |||
| - New TLV definitions for REN, REL, Reader Tamper and AUX | |||
| - New device state change definition for AUX relay | |||
| - Renamed VDE to RMRU to be consistent with other documentation | |||
| 1.12 | 07/18/2017 | - New TLV 0x83 for line voltage. Will map to battery voltage for RSI | J. Everson |
| 1.13 | 08/10/2017 | - Add Model Type for Connected Home Module in BLE advertisement | J. Goodrich |
| 1.14 | 9/19/2017 | - Update to Get Config Characteristic for 0x04 = Reserved and 0x05 = Get Audits without Delete (For Future use only) | T. Holt |
| 1.15 | 11/7/2017 | - Minor Updates to reference BLE Security Rev 3 and applicable App Note | T. Holt |
| 1.16 | 11/8/2017 | - Deprecated Get_Config Tag 0x03 for Get RTAC Subscription Service Configuration (410-IP) and re-assigned this to 0x04. Affects internal Gateway Communication only. | T. Holt |
| 1.17 | 4/2/2018 | - added section “6.4 MAPP Directed Site Survey” | Anirban Paul |
| 1.18 | 4/23/2018 | - moved IP characteristic tags for Site Survey feature to section 5.9 | Anirban Paul |
| 1.19 | 9/4/2018 | - minor updates | R. Verde |
| 1.20 | 9/7/2018 | - Added advertisement format clarifications, new Version value and Model Type for Gainsborough | J. Goodrich |
| 1.21 | 9/26/2018 | - Added second Gainsborough Model Type value and adjusted model names | J. Goodrich |
| 1.22 | 10/31/2018 | - Modified Section 4 for Version 2 Advertising information and updates. Also edited entire document for grammar and format. | T. Anfield |
| 1.23 | 01/07/2019 | - Fix examples for Version 2 Advertising updates. | T. Anfield |
| 1.24 | 04/22/2019 | - Reserved byte in Advertising Data | R. Verde |
| 1.25 | 04/25/2019 | - Removed Table of Contents in Markdown, renumbered tables and separated (Published Content) from internal only material. Created a second document: ENGAGE - BLE GATT - INTERNAL CONTENT ADDENDUM. | A. Clark |
| 1.26 | 05/01/2019 | - Replaced all references of "Sapphire" with "Allegion BLE Credential" to help with PACS documentation. Added a space for headers to help with parsing of markdown data. | M. Dexter |
Proprietary and Confidential, © 2019 Allegion™
| Abbreviations Used In This Document | |
|---|---|
| BLE | Bluetooth Low Energy |
| Db | Database |
| ENGAGE™ | Connectivity Platform Technology |
| ENGAGE™ Device | An ENGAGE™ NDE or ENGAGE™ Schlage Control Lock |
| Gateway | An ENGAGE™ Gateway that communicates BLE downstream to and ENGAGE™ device and upstream to a server using IP Ethernet (PoE option) or to an access control panel using RS-485 (RSI protocol) |
| JSON | Java Script Object Notation |
| NDE | Schlage ENGAGE™ Wireless Cylindrical Lock |
| LE | Schlage ENGAGE™ Wireless Mortise Lock |
| CTE | Schlage ENGAGE™ Reader Interface Controller |
| URI | Uniform Resource Identifier |
| URL | Uniform Resource Locator |
| GATT | Generic Attribute Profile |
| MAPP | An ENGAGE™ Mobile Application that runs on an IOS or Android Device |
| Indication | The same as a Notification except the value is confirmed with a response automatically by the BLE stack. |
| Notification | A BLE term used to describe a subscribed characteristic. The subscriber will always be notified when the value of the characteristic changes. |
| SF | NDE |
| SF-x00 | The SF-x00 is a NDE SF-200, 210, 400, 410, 415. |
| TBD | To Be Determined |
| RMRU | Von Duprin E-Dog Exit Device(with ENGAGE™) Base Device Type |
The purpose of this document is to describe how a MAPP, or a gateway can talk to an ENGAGE™ device via Bluetooth Low Energy (BLE). It is assumed that the reader is already familiar with BLE and GATT. This document only specifies the part of the GATT which is unique to ENGAGE™ devices.
The ENGAGE™ device is always the peripheral device. That means it is always the advertiser. The MAPP or gateway is always the initiator or central device. The device will continuously send out advertising messages on the advertising interval (1-5s) which are “undirected, connectable advertisements”.
There are only 4 services:
The Device Information service is a read-only service that includes the GATT version, ENGAGE™ Firmware version, and other non-essential information.
The Data Transfer service is used to transfer generic data, new firmware, JSON “files”, and the authentication handshake.
The General service is used to request configs, audits and to receive device status information.
The Real-Time service is only used by the Gateway to get device status and send device control messages. It is optimized for encrypting concise messages.
All JSON transfers are encrypted by AES-256-CBC. The key used depends on the authentication method. There are 2 types of authentication:
MAPP authentication – Uses the TempK for encrypting JSON
Gateway authentication – Uses the Gateway Key for encrypting JSON
Each method of authentication uses the data transfer service to authenticate. Only after authentication can most other characteristics be written. For detailed information on what tokens are exchanged during authentication, please reference the security documentation.
The Bluetooth Spec defines general advertising and scan response formats for BLE devices. Data fields in advertisements are defined by Bluetooth Specification Version 4.0 Volume 3 Part C Section 11. Allegion uses advertisements and scan response data to describe the device itself and its current operating state.
All versions of the advertising data (and not just the latest version) are described herein as any supporting mobile application may need to connect to all previous versions in the field.
Version 1 of Allegion Advertising Data for ENGAGE devices consists of exactly 30 bytes, shown in two parts below:
00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20
02 01 06 11 06 00 15 BB 8D E8 8C F5 99 82 47 01 E7 11 2C 05 52
|_|__|__|__|__|______________________________________________|
| | | | | |___Primary service – Allegion Data Transfer Service UUID
| | | | |___________________Advertising Data Type: Incomplete List of 128bit Service UUIDs
| | | |______________________Length of Incomplete 128bit Service UUIDs List
| | |_________________________Flags: Bit 0 LE General Discoverable Mode,
| | Bit 1 BR/EDR Not Supported.
| |___________________________Advertising Data Type: Flags
|______________________________Length of Advertising Flags Data Element
21|22|23|24|25|26|27|28|29
08 FF 3B 01 01 MM MM SS ZZ
|_|__|_____|__|_____|__|__|
| | | | | | |____ENGAGE Protocol Version:
| | | | | | 0x01= Original version
| | | | | | 0x02= Data Transfers have Sequence Numbers
| | | | | | 0x03= Refer to Schlage ENGAGE – BLE Security Rev 3 App Note
| | | | | | 0x04= Reserved
| | | | | |_______Device Status
| | | | | 0x01= FDR Mode – Lock needs to be captured
| | | | | 0x02= Captured Mode- Authentication required
| | | | | 0x03= Unconnectable – Lock in construction mode
| | | | | 0x04= Link Request to Gateway
| | | | | 0x05= Connection Request to Gateway
| | | | |____________Device Model ID (see Device Model ID Table below)
| | | |________________Allegion Advertising Data Format Version (0x01)
| | |_____________________Manufacturer ID (Allegion)
| |_________________________Advertising Data Type: Manufacturer Specific
|____________________________Length of Manufacturer Specific Data Element
0x0001 = NDE Lock
0x0002 = Schlage Control Lock
0x0003 = MT20W Reader
0x0004 = ADE Lock
0x0005 = Gateway
0x0006 = OEM Product
0x0007 = LE Lock
0x0008 = Schlage Sense
0x0009 = Denali
0x000A = RMRU exit device
0x000B = CTE Controller
0x000C = Connected Home Module
0x000D = Gainsborough GHI Trilock
0x000E = Gainsborough GHI Gateway
0x000F = BLE Wall Mount Reader
0x0010 = NDEB Lock
0x0011 = Schlage ControlB Lock
0x0012 = LEB Lock
Version 2 of Allegion Advertising Data is a variable length payload consisting of one or more Allegion protocol data elements to enunciate and describe device supported communication capabilities.
The generalized Version 2 Allegion Advertising payload has the following format:
00|01|02|03|04|05|06|07|08|09|10|11| … |30
02 01 06*NN*FF 3B 01 02 MM MM{XX YY … }*
|_|__|__|__|__|_____|__|_____|__________|
| | | | | | | | |________One or more* Allegion Protocol Blocks (see below)
| | | | | | | |________________Device Model ID (see Device Model ID Table in Version 1 above)
| | | | | | |____________________Allegion Advertising Data Format Version (0x02)
| | | | | |_________________________Manufacturer ID (Allegion)
| | | | |_____________________________Advertising Data Type: Manufacturer Specific
| | | |________________________________Length of Manufacturer Specific Data Element
| | |___________________________________Flags: Bit 0 LE General Discoverable Mode,
| | Bit 1 BR/EDR Not Supported.
| |______________________________________Advertising Data Type: Flags
|_________________________________________Length of Advertising Flags Data Element
NOTE: All length fields count the subsequent sub-elements’ bytes but do not include themselves, consistent with standard Bluetooth Core principles.
Each Allegion Protocol Block is comprised of at least 2 fields: Length and Type. All Allegion Protocol Blocks support additional data. Any number of Allegion Protocol Blocks may be included in an Allegion Advertising Data payload, each simply concatenated one after the other. Note that the order of blocks is not guaranteed. An interfacing application should iterate over the sub-elements, interrogating the Allegion Protocol Block Type of each to determine capabilities and methods of communication with the Allegion device. The Allegion Protocol Block length field should be used for such iteration and allows an interfacing application to skip over Allegion Protocol Blocks it does not recognize or support.
The possible Allegion Protocol Blocks are:
{XX YY …}
03 01 SS ZZ
|_|__|__|__|
| | | |____ENGAGE Protocol Version:
| | | 0x01= Original version
| | | 0x02= Data Transfers have Sequence Numbers
| | | 0x03= Refer to Schlage ENGAGE – BLE Security Rev 3 App Note
| | | 0x04= Reserved
| | |_______Device Status
| | 0x01= FDR Mode – Lock needs to be captured
| | 0x02= Captured Mode- Authentication required
| | 0x03= Unconnectable – Lock in construction mode
| | 0x04= Link Request to Gateway
| | 0x05= Connection Request to Gateway
| |_________Allegion Protocol Block Type: ENGAGE
|____________Length of ALLE ENGAGE Protocol Block
Example advertising data of an NDE device supporting ENGAGE only:
00|01|02|03|04|05|06|07|08|09|10|11|12|13
02 01 06 0A FF 3B 01 02 00 01 03 01 01 04
{XX YY …}
0C 02 SS ZZ TT TT UU UU UU UU UU UU VV
|__|__|__|__|_____|_________________|__|
| | | | | | |__NZRV for CAT* use (0 = time is set)
| | | | | |_____________48-bit unique identifier (UID)
| | | | |_________________________Status counter (see below)
| | | |_____________________________Residential Schlage Mode Protocol Version:
| | | 0x01= Original
| | |________________________________Device Status
| | 0x01= FDR/Unpaired State
| | 0x02= Paired
| |___________________________________Allegion Protocol Block Type: Residential Schlage Mode
|_____________________________________Length of ALLE Residential Schlage Mode Protocol Block
The 16-bit status counter is updated each time the status of the lock changes so that BLE central devices can tell whether they have the latest state information for the lock. Each device should record the value of the status counter each time that it connects to the lock. The device should initiate a new connection to read the lock status if the device sees a higher value status counter in the advertising data at a later time.
The 48-bit Unique Identifier is randomly-generated when Schlage mode is started and will also be used as the MAC address of the lock to make identifying a lock easier for both iOS (using advertising) and Android (using MAC address) mobile applications. Depending on implementation, the UID may or may not change when a lock is FDR’d or un-paired from a mobile app, but it will not change while paired.
This byte holds the status of the clock used in the CAT Secure Time Update process as described in the Secure Time Update section of the Schlage Mode BLE Interface Doc.
Example advertising data of a Denali device supporting just Residential Schlage Mode:
00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22
02 01 06 0A FF 3B 01 02 00 09 0C 02 01 01 00 01 FC 7E 12 A5 02 CD 00
{XX YY …}
03 03 SS ZZ
|_|__|__|__|
| | | |__BLE Credential Protocol Version:
| | | 0x01= Original version
| | |_____Device Status
| | 0x01= Not Ready/Unconfigured
| | 0x02= Ready/configured – REN Required
| | 0x03= Ready/Configured - Near Connections OK
| | 0x04= Ready/Configured - Any Connections OK
| |________Allegion Protocol Block Type: Allegion BLE Credential
|___________Length of ALLE BLE Credential Protocol Block
Example advertising data of a BLE Wall Mount Reader supporting BLE Credential only:
00|01|02|03|04|05|06|07|08|09|10|11|12|13
02 01 06 0A FF 3B 01 02 00 0F 03 03 04 01
Multiple Allegion Protocol Blocks can be supported and advertised by a device. The Length field for the Manufacturer Specific Data element will reflect the total bytes comprising all Allegion Protocol Blocks as well as the standard version 2 fields.
Example of a Residential Schlage Mode, ENGAGE, and Allegion BLE Credential supporting device:
00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30
02 01 06 1B FF 3B 01 02 00 02 0C 02 01 01 00 01 FC 7E 12 A5 02 CD 00 03 01 01 04 03 03 04 01
Manufacturer Data Format Version values 0xF0-0xFE are reserved. All bytes following the version field are considered custom and usable for any purpose. In general, the Device Model ID should be defined.
Scan response data from an ENGAGE device or any Version 2 Allegion Advertising device consists of a Local Name (a human-readable device handle for display) and Device Information data containing the device’s serial number. All Allegion scan response data uses standard Bluetooth Specification Version 4 Volume 3 Part C Section 11 data types to enumerate the subsequent data therein.
Example of Scan Response Data:
00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25
0D 09 53 63 68 6C 61 67 65 20 4C 6F 63 6B 0B 16 0A 18 A1 00 00 00 01 02 03 04
|_|__|___________________________________|__|__|_____|_______________________|
| | | | | | |__Serial Number (Last 8 bytes)
| | | | | |_____________Device Information
| | | | |_________________Service Data – 16bit UUID
| | | |____________________Length of Service Data Element
| | |____________________________________________Device’s Name (ex. “Schlage Lock”)
| |___________________________________________________________Data Type: Complete Local Name
|______________________________________________________________Length of Complete Local Name Data
The data transfer service is used for transferring encrypted JSON and non-JSON payloads including firmware files, door databases, configurations, authentication tokens, and WiFi handover commands.
| Item | UUID |
|---|---|
| Data Transfer Service UUID | 52052C11-E701-4782-99F5-8CE88DBB1500 |
| RxLength Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1501 |
| RxData Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1502 |
| RxCRC Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1503 |
| RxACK Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1504 |
| TxLength Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1505 |
| TxData Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1506 |
| TxCRC Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1507 |
| TxACK Characteristic | 52052C11-E701-4782-99F5-8CE88DBB1508 |
The data transfer service has 8 characteristics: 4 for sending, and 4 for receiving.
The data transfer service was optimized for BLE 4.0 radios. That is, radios that are not capable of increasing the MTU size greater than the default. It does this by using the write command (write without response), and allowing these 20-byte data messages to be sent as fast as possible.
There are two ways to send data with the data transfer service; with and without sequence numbers. Sequence numbers were added to support BLE stacks that may incorrectly send the data out of sequence (iPhone 5 and occasionally other iOS devices).
It is recommended that sequence numbers always be used although they are technically optional. The device’s sending of data transfers does not use sequence numbers. There have not been any reports of the device’s radio sending data packets out-of-order.
Due to RAM limitations on the ENGAGE™ device and because a single missed (20-byte) packet would require the entire JSON stream data transfer to be re-transmitted, the largest JSON stream data transfer is 2048 bytes. This is not to limit the maximum size of data being transferred. A fragmentation method for sending arbitrarily large data transfers can be used.
JSON is the primary means of communication to and from the device. For the contents of the JSON data, refer to the latest version of the ENGAGE - JSON Data Structures document. In general, JSON data can be sent over BLE or over WiFi. Since WiFi uses a client/server model, the device always makes a GET or POST HTTP request to a particular resource over WiFi.
For BLE, the GATT profile is set up so that the (authenticated) gateway or MAPP can send a JSON stream at any time to the device. In a similar way, the data transfer service will allow device to send a JSON stream at any time, however, the device waits for the connected device to request configuration or audits and those are the two main cases where the device sends data over the data transfer service.
Whenever the device gets a JSON stream, it will parse the JSON and process the contents. The JSON will always be encrypted with a known key and the device will first decrypt it. The device’s status of parsing the JSON and, if needed, database update status are sent to the connected device using the General Service and more specifically the IP Address characteristic.
The four (4) GATT characteristics used for data transfer are: Length, Data, CRC, ACK/NAK.
| Characteristic | BLE type | Description |
|---|---|---|
| Length/ Contents | Write with response/ Indication | The Length characteristic is first sent by the device sending the data transfer. When this is received, the receiver clears all buffers in preparation for receiving data. |
| This write request or indication contains not only the length of the packet of data but also bytes to indicate which key the encrypted data can be decrypted with. | ||
| Byte0-1 = Length | ||
| If Bytes0-1 == 0x0000, the packet is a fragmented large message. | ||
| (zero-byte length means the data transfer is only to send the Encryption Initialization Vector for a large data transfer that will be sent in multiple data transfers) | ||
| Byte2 = Receiver/Encryption. | ||
| Byte2 contains one of the following values to tell the receiver what to do with the data: | ||
| Byte2 => 0= No sequence byte. | ||
| Byte2 => 1= Reserved | ||
| Byte2 => 2= Encrypted Data | ||
| Byte2 => 4= Presence of sequence byte. The first byte of the 20 byte (or less) packet is the sequence number. Only 19 data bytes are sent each packet. This is useful for connecting with BLE stacks (iOS) that do not guarantee the order of the Write Command messages as they are sent out. The sequence number is 0-based. | ||
| If (Byte2 == Encrypted), the length parameter must be exactly 20 bytes long. | ||
| For encrypted data, the Byte3 contains: | ||
| Byte3 => 0=Reserved | ||
| Byte3 => 1=Capture Device/Gateway Step 1 | ||
| Byte3 => 2=Capture Device/Gateway Step 2 | ||
| Byte3 => 3=Authenticate - Establish Connection | ||
| Byte3 => 4= Authenticated Encrypted (TempK) - JSON | ||
| Byte3 => 5= Authenticated Encrypted (Site Key) - JSON | ||
| Byte3 => 6= Authenticated Encrypted (Zone Key) - JSON | ||
| Byte3 => 7= Authenticated Encrypted (Gateway Key) - JSON | ||
| Byte3 => 8= Application Firmware Download | ||
| Byte3 => 9= Authenticated Encrypted (TempK) – TLV Special Format -> Non-JSON. See Figure 12 - Switch To WiFi | ||
| Byte3 => 10=Authentication Challenge | ||
| Byte3 => 11=Gateway-Device Link Process Step 1 | ||
| Byte3 => 12=Gateway-Device Link Process Step 2 | ||
| Byte3 => 13=Authentication encrypted(Gateway Key) – JSON with resume capability | ||
| If Byte3 is between 2 and 5, the device will verify that the device is in the correct receive state that is specified. If it is not, the connection will be terminated and an audit record will be generated. | ||
| If the state is Authenticated Encrypted and the data appears to be garbage, the application may choose to generate an audit record as if the key is wrong. This could signal a hack attempt. | ||
| If Bytes0-1 == are nonzero, | ||
| Byte4-7: Packet # in sequence. LSByte sent first. | ||
| Bytes8-11: Total Packets. LSByte sent first. | ||
| If Bytes0-1 == 0x0000, and the Length field contains 20 bytes: | ||
| Byte4-19 = 128-bits CBC Random Initialization Vector used to make encrypted data appear random and uniformly distributed. | ||
| The CBC only needs one Initialization vector for the entire packet. i.e. The previous data transfer block’s end value is used for the next block’s cipher chain initialization value. This frees up 16 bytes to be used as fragmentation overhead. All fragmented messages must be the exact same length except for the last message. | ||
| Data | Write without response/Notification | The data is sent as fast as possible in 20-byte BLE packets. Using write without response (GATT client) or notifications (GATT server) is the only way to send multiple messages inside a single BLE connection interval. |
| If the sequence number is sent with the data, the sequence number shall be the first byte and the remaining bytes will be the data. The sequence number shall be 0 based. | ||
| CRC | Write with response/ Indication | When all data is sent, a 16-bit CRC calculated according to CRC Calculation is sent. |
| Indication/ Write with response | Every time the receiver gets a CRC value regardless of whether any length or data has been transferred, a one-byte ACK/NAK is sent. | |
| ACK = 0x01 | ||
| NAK_WRONG_CRC = 0x02 | ||
| NAK_NOT_ENOUGH_BYTES = 0x03 | ||
| NAK_LENGTH_TOO_LARGE = 0x04 | ||
| NAK_INVALID_TARGET = 0x05 | ||
| NAK_MESSAGE_SIZE_IS_DIFFERENT = 0x06 | ||
| BLE_NAK_ENCRYPTED_DATA_DOES_NOT_ALIGN_ON_BLOCK_SIZE_BOUNDARY = 0x07 | ||
| BLE_NAK_DB_MODULE_IS_STILL_USING_SCRATCHPAD_BUFFER = 0x08 | ||
| BLE_NAK_LARGE_DATA_TRANSFER_PACKET_OUTSIDE_OF_PACKET_BOUNDS = 0x09 | ||
| BLE_NAK_UNAUTHORIZED = 0x0A | ||
| BLE_NAK_TIMEOUT = 0x0B |
For all JSON data transfers, as shown in Table 1, first the Length byte is transmitted. Then, the Data bytes are all sent 20-bytes per-packet to the same characteristic (TxData or RxData) using BLE standard “write with no response” or, if the GATT server is sending JSON, BLE standard “notifications”.
If sequence numbers are specified in byte 2 (third byte) of the length characteristic, the 20-byte packets will have 19 bytes of data and the first byte will be a sequence number.
Once the Data sending is complete, the CRC is sent. When the receiver of the JSON gets the CRC it will always send an ACK or NAK depending on the CRC being correct. Since the CRC, Length, and ACK messages are all sent using a standard write (with response), the BLE stack will retransmit those messages if it isn’t ack’d at the BLE link layer.


The CRC is calculated similar to XModem standard by first calculating a table of 256 bytes:
for (i = 0; i \< 256; i++)
{
z = (byte)((byte)i \^ ((byte)i \>\> 4));
table[i] = (ushort)(z \^ (z \<\< 5) \^ (z \<\< 12));
}
The bytes to be calculated are then all sent sequentially through the following equation using the CRC of the previous bytes with a seed value of 0:
crc = ((crc \<\< 8) \^ table[byt \^ (crc \>\> 8)]);
The General Service is used mainly for requesting data transfers (Get Config characteristic), receiving lock status (IP Address characteristic), and for reading credentials in enrollment mode (Read Credential characteristic).
Refer to the ENGAGE – BLE Security Rev 3 App Note document for the proper format and encryption of the General Service characteristics on device that support BLE Security Rev 3.
There are many characteristics in the General Service. The table below only shows characteristics that are hooked up to do something (if that feature exists on the device). The rest of the characteristics are not currently used, and were never taken out because of side effects of changing the GATT[1] characteristic handle IDs.
[1] Most BLE devices (iOS and Android) cache the GATT characteristic handles during the discovery process. If the GATT characteristic
handles change, for example, due to removal or addition of characteristics, the mobile device will not know and will send a read
or write request to the wrong handle ID. The user will not be able to connect properly until he cycles power on the BLE radio or
the cache expires.
| Item | UUID |
|---|---|
| NDE General Service UUID | 52052C11-E701-4782-99F2-8CE88DBB1500 |
| Time | 52052C11-E701-4782-99F2-8CE88DBB1502 |
| Read Credential | 52052C11-E701-4782-99F2-8CE88DBB1503 |
| Door Name | 52052C11-E701-4782-99F3-8CE88DBB1502 |
| Firmware Version | 52052C11-E701-4782-99F3-8CE88DBB1506 |
| Calibrate DPS | 52052C11-E701-4782-99F3-8CE88DBB1507 |
| Get Configs | 52052C11-E701-4782-99F7-8CE88DBB1502 |
| IP Address | 52052C11-E701-4782-99F8-8CE88DBB1502 |
In Table 2, a Write is from MAPP to a device, a Read/Indication is data transferred from a device to MAPP.
| Characteristic | Description | Bytes | Device Exclusions |
|---|---|---|---|
| Time | Write-Sets the time of the clock on the lock. Read-Reads the time | Format YYYYMMDDHH:MM | |
| Read Credential | Turns on “Event Notifications” for the next 1 Credential event. Disables the unlocking of the door (DB function) when the credential is read. The credential will be sent as an Indication. | Write: Byte0= 0x01=Turn on “Enrollment Mode”. This simply will initiate enrollment mode, which sends the next credential as an Indication. | RMRU, CTE |
| Indication/Read: Credential that was read, encrypted with the Site Key, justified to MSb as first credential bit, 0 padded to nearest Byte, with no value of actual credential bit length. The 16-byte serial number is also prepended and the entire value is encrypted with the TempK. | |||
| Door Name | Write -Writes the door name. Read -N/A | ||
| Firmware Version | Write -N/A Read -Gets the version information. | ||
| Calibrate DPS | Write -Write defined values to perform specific functions related to DPS. Read -Used with the Write of 0x04 to read results of the Compare. | Write: Byte0=> 0x01 = Run DPS Calibration. NOTE: WRITE THIS CHARACTERISTIC VALUE WHEN THE DOOR IS CLOSED. | LE, CTE |
| Write: Byte0=> 0x02 = Turn ON audits and alerts which use DPS (Audits: Force Door, Propped Door) | |||
| Write: Byte0=> 0x03 = Turn OFF audits and alerts which use DPS (Audits: Force Door, Propped Door) | |||
| Write: Byte0=> 0x04 = Read DPS Value and Compare against Calibrated Value. Read: Only use with above write of 0x04 to read result of Compare. | |||
| Byte 0=> 0x01 = Determined Open; | |||
| Byte 0=> 0x02 = Determined Close | |||
| Get Config | Write -Writing this value will request the configuration values to be sent via JSON through the Data Transfer Service. Read -Reading this value will return the last Database timestamp so the database can be generated using the difference of the timestamp and current entries. | Write: Byte0=> 0x01 = Get device configuration | |
| Write: Byte0=> 0x02 = Get Audits | |||
| Write: Byte0=> 0x03 = Deprecated | |||
| Write: Byte0=> 0x04 = Get RTAC Subscription Service Configuration (410-IP) | |||
| Write: Byte0=> 0x05 = Get Audits without Deletion | |||
| Read: Bytes0-7=> Database timestamp Byte 0 is LSB, byte 7 is MSB | |||
| Read: Bytes8-11=> Number of audits available Byte 8 is LSB, byte 11 is MSB | |||
| IP Address | Write -Requests the WiFi module to connect to the host (Server). Read -Reading this characteristic returns the most recent status or an error message from the WiFi module. Indication -The indication will only contain the first 20 bytes of the result. After receiving an indication this attribute should be read as a long characteristic or blob and up to 255 bytes will be read. | Write: Byte0=>Tag/Type/Command | |
| Write: Byte0=> 0x01=Do immediate database download from host. | |||
| Write: Byte0=> 0x02=Connection Test. Connect to AP and see if WiFi parameters are connection. | |||
| Write: Byte0=> 0x03=Do immediate firmware download from host. | |||
| Write: Byte0=> 0x04=Do immediate firmware flashing. | |||
| Write: Byte0=> 0x05=Initiate Built-In Test. Results will be located in Audit Records. | |||
| Read: A TLV formatted message as defined in General Service Event Messages. |

In most cases, the data being transferred is less than the buffer size. (e.g. Less than 1K of data per transfer). In most cases, this is fully-formed JSON. However, as an example, if firmware were to be downloaded over BLE, the data to transfer is much larger than the buffer size. This must be stored in external flash memory to process it.

If the connection is interrupted during a large download transfer, the transfer may be restarted so that the previously sent blocks do not have to be re-transmitted. This resume feature requires that the receiving device store the plaintext data of all blocks that successfully pass CRC and have been ACK’ed in non-volatile memory. The sender needs only to keep track of which blocks have successfully been ACK’ed by the receiving device.
Once a new connection has been re-established, the resume begins the same way as all large data transfers (shown in Figure 6). Before skipping to the block number that is next to be transmitted, the sender must first send only the length characteristic indicating block number 1 and wait for the transport layer ACK (write response). Immediately after, the entire new block with length characteristic indicating the resuming block number. The rest of the large data transfer continues as normal. Figure 6 shows the large data transfer resume process.

The WiFi hand-off is done using the Data Transfer service, with a non-JSON payload encrypted with the TempK. Because it is encrypted, the length will always be a multiple of 16 bytes, but it can be padded at the end with anything.
Because it is a non-JSON data transfer, and because the data to specify a WiFi transfer must contain SSID and password for the device’s AP mode, Tag-Length-Value format (TLV) is used.
The Tags are:
| Tag | Data |
|---|---|
| 0x01 | SSID (ASCII) for the lock to broadcast. |
| 0x02 | SSID Password (ASCII) to authenticate to the SSID. |
| 0x03 | IP Address (connection 2) (ASCII) |
| 0x04 | MAPP random login ID (ASCII) |
| 0x05 | MAPP random login password (ASCII) |
| 0x06 | FWDL URL (ASCII max 50 bytes) |
| 0x07 | DL Type (0=DB, 1=FW, 2=Audit) |
| 0x08 | Turn Wifi Off (no data). |
| 0x09 | AP Channel Number (1 to 13) |
| 0x0A | Port Number |
There are many cases when the device needs to send a status or error message to the MAPP. This can be while firmware is being downloaded to show download status percentage, or after an error connecting to the database host has been detected.
This message is in TLV format and may contain more than one tag.
It would be possible to send these with the data transfer service but sending with the IP Address characteristic allows faster transfer for shorter data. That is the only reason these are sent with the IP Address characteristic. Also, these values are unencrypted. There is no secret information as the data is intended to be displayed directly to the user.
After the indication, the IP Address characteristic must be read, to read the entire data.
NOTE This information is not encrypted because these are status and troubleshooting informational messages that do not contain secret data. Similar information can be seen on the LEDs on the Device. It makes troubleshooting easier for Integrators if these messages are not encrypted.
The Tags are:
| Tag | Data |
|---|---|
| 0x01 | Padding. This byte and all other bytes after it are padding to get the data length on an encryption block-size boundary (16-bytes). This should not be confused with an actual Tag, which always has a length parameter immediately following it. |
| 0x02 | Wifi Firmware Download Percentage (3 byte ASCII 000-100) |
| 0x03 | Wifi Status/Error message (ASCII text. This tag is deprecated.) |
| 0x04 | Wifi is done downloading from MAPP’s web server. It is ok to shut off web server now. |
| 0x05 | No More Audits Available (over BLE) |
| 0x06 | Error Retrieving Configuration – 2-byte error code (byte0=LSB, byte1=MSB) |
| Error code is one of: | |
| 0x0002 Internal Error- Frame Continue | |
| 0x0003 Internal Error- Invalid Event | |
| 0x0004 Internal Error- Invalid Report | |
| 0x0005 Frame Error- Invalid JSON | |
| 0x0007 Internal Error-Invalid Buffer Size Provided | |
| 0x0008 Internal Error-Invalid Tag Value | |
| 0x000A Buffer Error-Buffer is being used. Please try again later. | |
| 0x07 | Error Retrieving Audits – 2-byte error code (byte0=LSB, byte1=MSB) |
| Error code is one of: | |
| 0x0002 Internal Error- Frame Continue | |
| 0x0003 Internal Error- Invalid Event | |
| 0x0004 Internal Error- Invalid Report | |
| 0x0005 Frame Error- Invalid JSON | |
| 0x0006 Internal Error- Bad Audit Data | |
| 0x0007 Internal Error-Invalid Buffer Size Provided | |
| 0x0008 Internal Error-Invalid Tag Value | |
| 0x0009 Internal Error-Invalid Overall Audit Size | |
| 0x000A Buffer Error- Buffer is being used. Please try again later. | |
| 0x08 | IBIT (Initiated, Built-In Test) is completed. Check Audits for results. |
| 0x09 | Wifi Database Download Percentage (3 byte ASCII 000-100) |
| 0x0A | Wifi Audit Upload Percentage (3 byte ASCII 000-100) |
| 0x0B | JSON Parsing Percentage (3 byte ASCII 000-100) |
| 0x0C | DB Update Percentage (3 byte ASCII 000-100) . This is the last step in the WiFi DB Download. When this value is 100%, it is safe to send any configuration data to the lock. Sending configuration or DB data when the WiFi is in progress of any other status message has the potential to cause errors. |
| 0x0D | Firmware WiFi Status. Length of 2 bytes. First byte is Command Type. Second byte is error code. Command types and error codes are defined in WiFi Audit Trail Document |
| 0x0E | WiFi Error. Byte 0 is Command Type, Bytes 1-2 is error code. HTTP 404 error will be 0x01 0x94. Command types and error codes are defined in WiFi Audit Trail Document |
| 0x0F | BLE Characteristic Value Error – 1-byte error code |
| Error code is one of: | |
| 0x01 DPS Characteristic Error | |
| 0x10* | Site Survey Status, two bytes |
| Byte 1: | |
| 0x00 = Idle | |
| 0x01 = inProgress | |
| Byte 2: | |
| 0x00 = No error | |
| 0x01 = Site Survey is in progress | |
| 0x02 = No site survey result found | |
| 0x03 = No edge device is connected | |
| 0xFF = Generic error | |
| 0x11* | Site Survey Progress, 3 bytes ASCII (000 - 100) |
*Gateway only

NOTE: Data shown is unencrypted for clarity; actual data transfer is encrypted with TempK.
This XML is copied from the actual XML configuration file that generates the code on the Bluegiga module.
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<service uuid="1800">
<description>Generic Access Profile</description>
<characteristic uuid="2a00" id="DeviceName">
<properties read="true" />
<value length="32" variable_length="true" />
</characteristic>
</service>
<!-- 180A: org.bluetooth.service.device_information -->
<service uuid="180A" id="device_information">
<description>Device Information</description>
<!-- 2A26: org.bluetooth.characteristic.firmware_revision_string -->
<characteristic uuid="2A26" id="c_firmware_revision_string">
<description>Firmware Revision String</description>
<properties read="true" const="true" />
<value>1.0.8</value>
</characteristic>
</service>
<service uuid="52052C11-E701-4782-99F5-8CE88DBB1500" type="primary" advertise="true">
<description>DataTransfer</description> <!-- description is not exposed by the GATT Database -->
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1501" id="RxLength">
<description>RxLength</description>
<properties write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1502" id="RxData">
<description>RxData</description><!-- Notification is not confirmed. Indication is confirmed with a response. -->
<properties write_no_response="true" write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1503" id="RxCRC">
<description>RxCRC</description>
<properties write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1504" id="RxACKNAK">
<description>RxACKNAK</description>
<properties indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1505" id="TxLength">
<description>TxLength</description>
<properties indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1506" id="TxData">
<description>TxData</description><!-- Notification is not confirmed. Indication is confirmed with a response. -->
<properties notify="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1507" id="TxCRC">
<description>TxCRC</description>
<properties indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F5-8CE88DBB1508" id="TxACKNAK">
<description>TxACKNAK</description>
<properties write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
</service>
<service uuid="52052C11-E701-4782-99F2-8CE88DBB1500" type="primary" advertise="true">
<description>General</description> <!-- description is not exposed by the GATT Database -->
<characteristic uuid="52052C11-E701-4782-99F2-8CE88DBB1501" id="IdentifyDoor">
<description>IdentifyDoor</description>
<properties write_no_response="true" write="true" read="true" indicate="true" >
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F2-8CE88DBB1502" id="Time">
<description>Time</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic\>
<!-- This attribute can be used for turning events on. Credential events, forced door events, switch status events, etc.
This will probably be a bitmask of some sort. -->
<characteristic uuid="52052C11-E701-4782-99F2-8CE88DBB1503" id="ReadCredential">
<description>ReadCredential</description>
<properties write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<!-- Notice the attribute is indicate only. That means the iPhone can't read or write it. It can only receive indications
when there is a new event. -->
<characteristic uuid="52052C11-E701-4782-99F2-8CE88DBB1506" id="DoorInfo">
<description>EventInfo</description>
<properties indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F2-8CE88DBB1505" id="LockDoor">
<description>LockDoor</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<!-- Door name is contained in the GAP service 0x1800 attribute 0x2A00. This attribute is used for setting the door name -->
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1502" id="DoorName">
<description>DoorName</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" />
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1503" id="ListBondedDevices">
<description>ListBondedDevices</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1504" id="BondDevice">
<description>BondDevice</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1505" id="UnbondDevice">
<description>UnbondDevice</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1506" id="FirmwareVersion">
<description>FirmwareVersion</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<!-- Only write this attribute when the door is closed. This initiates a DPS calibration and will indicate a successul or
failure response. -->
<characteristic uuid="52052C11-E701-4782-99F3-8CE88DBB1507" id="CalibrateDPS">
<description>CalibrateDPS</description>
<properties write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" />
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F6-8CE88DBB1501" id="BatteryLevel">
<description>BatteryLevel</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F6-8CE88DBB1502" id="ConnectivityStatus">
<description>ConnectivityStatus</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F6-8CE88DBB1503" id="ErrorNotification">
<description>ErrorNotification</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<!-- Writing to this attribute will be considered a request for a JSON file with audits to be generated and sent via the
data transfer service.-->
<characteristic uuid="52052C11-E701-4782-99F7-8CE88DBB1501" id="GetAudits">
<description>GetAudits</description>
<properties write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<!-- Writing to this attribute will be considered a request for a JSON file with configuration information to be generated
and sent via the data transfer service.-->
<characteristic uuid="52052C11-E701-4782-99F7-8CE88DBB1502" id="GetConfig">
<description>GetConfig</description>
<properties write="true" read="true"/>
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F8-8CE88DBB1501" id="CaptureLock">
<description>CaptureLock</description>
<properties write_no_response="true" write="true" read="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99F8-8CE88DBB1502" id="IPAddress">
<description>IPAddress</description>
<properties read="true" write="true" indicate="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
</service>
<service uuid="52052C11-E701-4782-99E0-8CE88DBB1500" type="primary" advertise="true">
<description>Gateway Real-Time Service</description> <!-- description is not exposed by the GATT Database -->
<characteristic uuid="52052C11-E701-4782-99E0-8CE88DBB1501" id="Lock Control">
<description>Lock Control</description>
<properties indicate="true" write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
<characteristic uuid="52052C11-E701-4782-99E0-8CE88DBB1502" id="Lock Status">
<description>Lock Status</description>
<properties read="true" indicate="true" write="true" />
<value variable_length="true" length="20" type="user" /> <!-- If value is user characteristic value is not stored in RAM.
Application has to handle storing attribute value and handle length checking. -->
</characteristic>
</service>
</configuration>
From Version 4.0 Volume 3 Part C Section 11 and background.
The data fields that can be in the advertisement or scan response data are:
The Advertising and Scan Response message may each contain up to 31 bytes. The Scan Response is only used to transmit local name (Device name), which can be up to 29 bytes.
These fields are all in TLV format. The flags field takes up 3 bytes of the Advertising message. The primary service UUID is 16 bytes (52052C11-E701-4782-99F5-8CE88DBB1500), which will take up 18 bytes of the advertisement. That leaves 10 bytes of the advertisement and for manufacturer specific data. Since overhead (Tag, Length + Manufacturer ID) take up 4 bytes, there are 6 bytes left for actual data in the advertisement.
According to the Bluetooth assigned numbers website, link, Allegion’s company identifier is 0x013B.
It is a good idea to give the TX Power Level in the advertisement or scan response data. This allows more generalized distance information. It is probably not needed because the TX power is fixed and can be inferred (looked up) from the model type if different Allegion products have different BLE transceivers and different power levels.