The protocol is designed to be simple to implement and use, while still being powerful enough to handle more complicated situations. It is a binary client - server protocol over a TCP socket. The client sends commands and the server sends events. Each command or event is called a packet and every packet is prefixed with a 16-bit little endian encoded length integer when sent over the socket.
- The length header does not include its own length.
- The first byte in each packet consists of an opcode that is unique for that kind of packet.
- All integers are encoded in little endian byte order.
- Booleans (bool) are encoded as a single byte - 0 means false and 1 means true.
- Enums are encoded as a single byte. The corresponding integer byte value is 0 for the first possible value, then 1, then 2 and so on for the other values.
- There are no alignment or padding between items in a packet.
- The items are serialized in the same order as noted in this document.
A bluetooth address (bdaddr_t) is encoded in little endan, 6 bytes in total. When such an address is written as a string, it is normally written in big endian, where each byte is encoded in hex and colon as separator for each byte. For example, the address 08:09:0a:0b:0c:0d
is encoded as the bytes 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08
.
NoError - There were space in the bluetooth controller's white list to accept a physical pending connection for this button
MaxPendingConnectionsReached - There were no space left in the bluetooth controller to allow a new pending connection
Disconnected - Not currently an established connection, but will connect as soon as the button is pressed and it is in range as long as the connection channel hasn't been removed (and unless maximum number of concurrent connections has been reached or the bluetooth controller has been detached).
Connected - The physical bluetooth connection has just been established and the server and the button are currently verifying each other. As soon as this is done, it will switch to the ready status.
Ready - The verification is done and button events may now arrive.
Unspecified - Unknown reason
ConnectionEstablishmentFailed - The bluetooth controller established a connection, but the Flic button didn't answer in time.
TimedOut - The connection to the Flic button was lost due to either being out of range or some radio communication problems.
BondingKeysMismatch - The server and the Flic button for some reason don't agree on the previously established bonding keys.
RemovedByThisClient - The connection channel was removed by this client.
ForceDisconnectedByThisClient - The connection channel was removed due to a force disconnect by this client.
ForceDisconnectedByOtherClient - Another client force disconnected the button used in this connection channel.
The following reasons might only happen if the Flic button is previously not verified, i.e. these are errors that might happen during the bonding process.
ButtonIsPrivate - The button is not in public mode. Hold it down for 7 seconds while not trying to establish a connection, then try to reconnect by creating a new connection channel.
VerifyTimeout - After the connection was established, the bonding procedure didn't complete in time.
InternetBackendError - The internet request to the Flic backend failed.
InvalidData - According to the Flic backend, this Flic button supplied invalid identity data.
ButtonDown - The button was pressed.
ButtonUp - The button was released.
ButtonClick - The button was clicked, and was held for at most 1 seconds between press and release.
ButtonSingleClick - The button was clicked once.
ButtonDoubleClick - The button was clicked twice. The time between the first and second press must be at most 0.5 seconds.
ButtonHold - The button was held for at least 1 second.
The server can be configured to either use the burnt-in public address stored inside the bluetooth controller, or to use a custom random static address. This custom address is a good idea if you want to be able to use your database with bonding information with a different bluetooth controller.
PublicBdAddrType
RandomBdAddrType
This specifies the accepted latency mode for the corresponding connection channel. The physical bluetooth connection will use the lowest mode set by any connection channel. The battery usage for the Flic button is normally about the same for all modes if the connection is stable. However lower modes will have higher battery usage if the connection is unstable. Lower modes also consumes more power for the client, which is normally not a problem since most computers run on wall power or have large batteries.
Normal - Up to 100 ms latency.
Low - Up to 17.5 ms latency.
High - Up to 275 ms latency.
The server software detects when the bluetooth controller is removed or is made unavailable. It will then repeatedly retry to re-established a connection to the same bluetooth controller.
Detached - The server software has lost the HCI socket to the bluetooth controller and is trying to reconnect.
Resetting - The server software has just got connected to the HCI socket and initiated a reset of the bluetooth controller.
Attached - The bluetooth controller has done initialization and is up and running.
This command is used to retrieve current state about the server. After this command is sent, an EvtGetInfoResponse is sent back.
uint8_t opcode: 0
Creates a scanner with the given scan_id. For each advertisement packet received from a Flic button by the server, an EvtAdvertisementPacket will be sent with the given scan_id until it is removed using CmdRemoveScanner. If there is already an active scanner with this scan_id, this does nothing.
uint8_t opcode: 1
uint32_t scan_id: A unique identifier that is sent together with advertisement packets. This identifier is also used to remove the scanner.
Removes the scanner with the given scan_id. Once this is received by the server, it will no longer send out EvtAdvertisementPackets with this scan_id.
uint8_t opcode: 2
uint32_t scan_id: The same identifier that was used in CmdCreateScanner.
Creates a connection channel for a Flic button with the given bluetooth address. You assign a unique conn_id for this connection channel that will later be used in commands and events to refer to this connection channel. After this command is received by the server, an EvtCreateConnectionChannelResponse is sent. If there already exists a connection channel with this conn_id, this does nothing.
uint8_t opcode: 3
uint32_t conn_id: A unique identifier.
bdaddr_t bd_addr: The address of the Flic to connect to.
enum LatencyMode latency_mode: Latency you are willing to accept for this connection channel.
uint16_t auto_disconnect_time: Time in seconds after the Flic button may disconnect after the latest press or release. The button will reconnect automatically when it is later pressed again and deliver its enqueued events. Valid values are 0 - 511. 512 is used to disable this feature, i.e. the button will remain connected. If there are multiple connection channels for this button, the maximum value will be used.
Removes a connection channel previously created with CmdCreateConnectionChannel. After this is received by the server, this connection channel is removed and no further events will be sent for this channel. If there are no other connection channels active to this Flic button among any client, the physical bluetooth connection is disconnected.
uint8_t opcode: 4
uint32_t conn_id: Connection channel identifier.
Removes all connection channels among all clients for the specified Flic button bluetooth address.
uint8_t opcode: 5
bdaddr_t bd_addr: The address of the Flic to disconnect.
Changes the accepted latency for this connection channel and the auto disconnect time. The latency mode will be applied immediately but the auto disconnect time will be applied the next time tme Flic is getting connected.
uint8_t opcode: 6
uint32_t conn_id: Connection channel identifier.
enum LatencyMode latency_mode: The accepted latency mode.
int16_t auto_disconnect_time: See under CmdCreateConnectionChannel.
If you for various reasons would like to ping the server, send this command. An EvtPingResponse will be sent back in return with the same ping_id.
uint8_t: opcode: 7
uint32_t: ping_id: An identifier that will be sent back in return.
For each scanner the client has created, this packet will be sent for each bluetooth advertisement packet arriving that comes from a Flic button. Usually the Flic button sends out many advertisement packets, with higher frequency if it was lately pressed.
uint8_t opcode: 0
uint32_t scan_id: The scan id corresponding to the scanner which this advertisement packet belongs to.
bdaddr_t bd_addr: The bluetooth address of this Flic button. Use it to establish a connection chnanel.
uint8_t name_length: The length in bytes of the name following.
_char[16] name: The first name_length bytes of this array contain the UTF-8 encoding of the advertised name. The other bytes will be zeros.
int8_t rssi: Signal strength in dBm, between -126 and 20, where -127 is weakest and 20 is strongest. -127 means not available.
bool is_private: The Flic button is currently in private mode and won't accept connections from unbonded clients. Hold it down for 7 seconds while not attempting to connect to it to make it public. First then you may connect.
bool already_verified: If the server has the bonding key for this Flic button, this value is true. That means you should be able to connect to it.
This event will always be sent when a CmdCreateConnectionChannel is received, containing the status of the request.
uint8_t opcode: 1
uint32_t conn_id: Connection channel identifier.
enum CreateConnectionChannelError error: Whether the request succeeded or not.
enum ConnectionStatus connection_status: The current connection status to this button. This might be a non-disconnected status if there are already other active connection channels to this button.
This event is sent when the connection status is changed.
uint8_t opcode: 2
uint32_t conn_id: Connection channel identifier.
enum ConnectionStatus connection_status: New connection status.
enum DisconnectReason disconnect_reason: If the connection status is Disconnected, this contains the reason. Otherwise this parameter is considered invalid.
This event is sent when a connection channel is removed. After this event is sent from the server, it will no longer send events corresponding to this connection channel. From this point, the conn_id can now be reused when creating new connection channels. Note: If you got an EvtCreateConnectionChannelResponse with an error different than NoError, the connection channel have never been considered created, and this event will thus never be sent afterwards.
uint8_t opcode: 3
uint32_t conn_id: Connection channel identifier.
enum RemovedReason removed_reason: Reason for this connection channel being removed.
There are four types of button events. For each type of event, there is a different set of possible ClickTypes. Normally one application would handle one type of events and discard the others, depending on how many different triggers you would like the Flic button to be used for.
The following event types are defined:
- ButtonUpOrDown: Possible ClickTypes are ButtonUp and ButtonDown. Used to simply know when the button was pressed or released.
- ButtonClickOrHold: Possible ClickTypes are ButtonClick and ButtonHold. Used if you want to distinguish between click and hold.
- ButtonSingleOrDoubleClick: Possible ClickTypes are ButtonSingleClick and ButtonDoubleClick. Used if you want to distinguish between a single click and a double click.
- ButtonSingleOrDoubleClickOrHold: Possible ClickTypes are ButtonSingleClick, ButtonDoubleClick and ButtonHold. Used if you want to distinguish between a single click, a double click and a hold.
uint8_t opcode: 4, 5, 6 or 7 for the different types of event, in the same order as above.
enum ClickType click_type: The click type. For each opcode, there are different possible values.
bool was_queued: If this button event happened during the button was disconnected or not.
uint32_t time_diff: If this button event happened during the button was disconnected, this will be the number of seconds since that event happened (otherwise it will most likely be 0). Depending on your application, you might want to discard too old events.
This is sent to all clients when a button has been successfully verified that was not verified before (for the current bluetooth controller bluetooth address). Note: The EvtConnectionStatusChanged with connection_status = Ready will be sent just before this event.
uint8_t opcode: 8
bdaddr_t bd_addr: The bluetooth address for the verified Flic button.
This is sent as a response to a CmdGetInfo.
uint8_t opcode: 9
enum BluetoothControllerState bluetooth_controller_state: Current state of the HCI connection to the bluetooth controller.
bdaddr_t my_bd_addr: Current bluetooth address / identity of this device.
enum BdAddrType my_bd_addr_type: Current bluetooth address type of this device.
uint8_t max_pending_connections: The max number of Flic buttons that can be monitored at the same time, regardless of having an established connection or not.
int16_t max_concurrently_connected_buttons: The max number of Flic buttons that can have an established bluetooth connection at the same time. If this amount is reached, no other pending connection will succeed until another one has disconnected. This value will be -1 until the value becomes known. It becomes known first when the maximum number of connections is currently established and there is an attempt to establish yet another connection. Not all bluetooth controllers handle this correctly; some simply hides the fact that the maximum is reached and further connections won't succeed successfully, until a previously established connection is disconnected. Note: For some bluetooth controllers we have tested we have already hardcoded the correct value and this parameter will thus not be -1 but the correct one.
uint8_t current_pending_connections: Current number of Flic buttons that are monitored by the server, among all clients.
bool currently_no_space_for_new_connection: The maximum number of concurrently connected buttons has been reached.
uint16_t nb_verified_buttons: Number of verified buttons for this my_bd_addr/my_bd_addr_type pair.
bdaddr_t[nb_verified_buttons] bd_addr_of_verified_buttons: An array of all the verified buttons.
Sent whenever the server wants to connect another button but there is no more space.
uint8_t opcode: 10
uint8_t max_concurrently_connected_buttons: Same as in EvtGetInfoResponse.
Sent when the maximum number of concurrent connections was reached but a button has now disconnected, making room for one new connection.
uint8_t opcode: 11
uint8_t max_concurrently_connected_buttons: Same as in EvtGetInfoResponse.
See enum BluetoothControllerStateChange. If the bluetooth controller is detached, the scanners and connection channels set up by the user will maintain their state (but obviously no advertisement packet / connection state change / button events will be received). When the state is changed to Attached, internally all pending connections and scanners will be recreated as they were before the bluetooth controller was detached. Note: before sending the Detached state to the client, the server will first send EvtConnectionStatusChanged for each connected button with connection_status = Disconnected. Note: If the bluetooth controller sends a hardware error event, the state will transition directly from Attached to Resetting and if it was able to reset, back to Attached.
uint8_t opcode: 12
enum BluetoothControllerState state: The new state.
Sent in response to a CmdPing
uint8_t: opcode: 13
uint32_t: ping_id: Same ping id as sent in the CmdPing.