Flic hub intergration

So you have put the code onto the Flic Hub and it is running when you press a button ?

I have many automations running with the Flicd addon so I made some modifications to the Flic Hub code shared by others in order to keep that automations running with the same Flic Button but now paired to the Flic Hub. The new code also sends some state updates so the buttons are still showed on your dashboards.

const requestManager = require("http");
const buttonManager = require("buttons");

//--------------------------------------------------------------------------------//

const MIN_EVENTS_OFFSET = 600;
const SERVER_HOST = 'http://192.168.XXX.YYY:8123';
const SERVER_AUTH_TOKEN = 'Your Long-Lived Access Token';

//--------------------------------------------------------------------------------//

buttonManager.on("buttonReady", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonState(button, 'on');
});

buttonManager.on("buttonDisconnected", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonState(button, 'off');
});

buttonManager.on("buttonDeleted", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonState(button, 'off');
});

var lasClickTimestamp = 0;
buttonManager.on("buttonSingleOrDoubleClickOrHold", function(obj) {
	const timestamp = Date.now();
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonState(button, 'on');
	if(timestamp - lasClickTimestamp >= MIN_EVENTS_OFFSET) {
		lasClickTimestamp = timestamp;
		button.clickType = obj.isSingleClick ? "single" : obj.isDoubleClick ? "double" : "hold";
		sendButtonEvent(button);
	} else {
		console.log("Event was ignored");
	}
});

//--------------------------------------------------------------------------------//

function getButtonName(data) {
	return 'flic_' + data.bdaddr.replace(new RegExp(':', 'g'), '');
}

function sendButtonState(button, state) {
	var data = JSON.parse(JSON.stringify(button));
	notifyHomeAssistant({
		'method': "POST",
		'url': SERVER_HOST + "/api/states/binary_sensor." + getButtonName(data),
		'content': JSON.stringify({
			'state': state,
			'attributes': {
				'friendly_name': data.name == null ? getButtonName(data) : data.name
			}
		})
	});
}

function sendButtonEvent(event) {
	var data = JSON.parse(JSON.stringify(event));
	notifyHomeAssistant({
		'method': "POST",
		'url': SERVER_HOST + "/api/events/flic_click",
		'content': JSON.stringify({
			'button_name': getButtonName(data),
			'button_address': data.bdaddr,
			'click_type': data.clickType
		})
	});
}

function notifyHomeAssistant(options) {
	options.headers = {
		'Authorization': 'Bearer ' + SERVER_AUTH_TOKEN,
		'Content-Type': 'application/json'
	};
	requestManager.makeRequest(options, function (error, result) {
		if(error != null) {
			console.log(JSON.stringify(options));
			console.log(error);
		}
	});
}
7 Likes

Thank you. I finally got Flic working with HA thanks to your code.

Thank you blunan.
My flic hub and flic2 buttons are now working reliably (I used to have a lot of stability/connection issues with the flicd addon).
This is an excellent solution that is easy to use for novice users.

Thank you, this works perfectly and is also much faster response compared to using webhooks configured in the flic app.

Thank you Blunan for this!

Slight problem/question. I have one Flic directly connected to my RaspPi using flicd everything works correctly and it also shows a state change when viewing the states tab in Dev tools. I used the Flic SDK following your directions copying all 3 files, long live token, etc. I have another Flic this time connected to the Flic hub. The Flic connected to the hub does show up as a binary object but has a permanent “on” state. When I fire the Flic connected to the hub, Home Assistant recognizes the click type, single, double, hold, and any automation work. I debugged both Flics via Node Red and I see the Flic connected directly to the Pi sends a state change when clicked but the Flic connected to the hub does not, hence the permanent “on” state. Did I miss something in the Flic Hub SDK where it’s not sending the actual state change in Home Assistant? I know it’s not a big deal as the Flic connected to the Flic Hub still work as intended but it’ll be nice to have the state change show up accurately in Home Assistant.

Hi there,
I’m new to HA and what I’d like to achieve is using the above Flic Hub SDK code to have the hub transmit button events to the HA instance.
Setting up the flic hub side is easy but what do I need on the HA side to listen for the events and start different actions for different buttons. But how? Do I need the flic-addon? (My understanding is that it’s only required when you want to pair flic buttons with the Pi directly?
Best
AF360

1 Like

Sorry, I too have the same question. Any guidance would be wonderful.

@JJ6767 Well I figured it out meanwhile, it’s really easy. So assuming you have properly setup the flic 2 Hub LR to send a request on a websocket go to home assistant → configuration → automations and add an empty automation:

As the trigger pick webhook and in the ID-field add what your previously have setup in the flic hub (so your automation is only triggered from your flic button(s).

Next you can filter the automation by defining conditions but that’s optional. Leave it empty if you just want to call an action when the flic button is clicked.

Finally you define the action.
As action type pick call service and as the service pick what floats your boat (the dropdown will show your option’s)

Hope this will get you on the right track, too. :grinning:

Have been spending many hours with the system in the last few days and learned a lot. I‘m loving it!

1 Like

That’s how I use the flic hub with hass too. You don’t have to worry about setting any of the headers or password keys in the flic app since webhooks don’t require login authentication. Instead, they rely on you picking a unique random Webhook ID that can’t be guessed as that’s the only way it’s secured. Then, in the flic app, you only need to configure the webhook post URL to be something like this:

http://192.168.x.x:8123/api/webhook/random_id_12345

flic app:


None of the other settings on that page are required.

The related automation trigger config in hass looks like this:

platform: webhook
webhook_id: random_id_12345

or:
trigger

You can have multiple buttons point to the same webhook for invoking the same automation. However, different automations require different unique webhooks. If you wanted to use the various button press types (short/double/long) you would need a new automation and trigger for each one when using this method.

Thank you so much everyone - giving it a go now !

Hi @wallE,

The state reported is linked with the connection state to the Hub. From Flic Hub SDK, a button can emit the following events:

buttonConnected
Emitted as soon as the button has made a physical connection to the hub (not yet fully verified).

buttonReady
Emitted when the connection has been verified. From now on button press events may be delivered.

buttonDisconnected
Emitted when the physical connection to the button has ended for any reason. This will happen either if the signal strength to the button is not good enough, if it lost synchronization with the button or if the button went into sleep mode.

When buttonReady event is emitted the state for that button is set to on, and when buttonDisconnected is emitted the state is set to off. Each button also has a ready property which is used to update the state every CONFIG.SYNC_TIME milliseconds.

I guess Flicd addon behaviour can be achieved by using buttonDown and buttonUp events. I can’t test it right now but I’ll leave the changes here.

main.js
const CONFIG = require("./config");
const requestManager = require("http");
const buttonManager = require("buttons");

// STATES
const STATE_ON = 'on';
const STATE_OFF = 'off';

// ACTIONS
const CLICK_HOLD = 'hold';
const CLICK_SINGLE = 'single';
const CLICK_DOUBLE = 'double';

//--------------------------------------------------------------------------------//

function syncButtons() {
	var buttons = buttonManager.getButtons();
	for (var i = 0; i < buttons.length; i++) {
		const button = buttons[i];
		sendButtonBattery(button);
	}
}

syncButtons()
setInterval(syncButtons, CONFIG.SYNC_TIME);

//--------------------------------------------------------------------------------//

buttonManager.on("buttonDown", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonBatteryAndState(button, STATE_ON);
});

buttonManager.on("buttonUp", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	sendButtonBatteryAndState(button, STATE_OFF);
});

var lasClickTimestamp = 0;
buttonManager.on("buttonSingleOrDoubleClickOrHold", function(obj) {
	const timestamp = Date.now();
	var button = buttonManager.getButton(obj.bdaddr);
	if(timestamp - lasClickTimestamp >= CONFIG.MIN_EVENTS_OFFSET) {
		lasClickTimestamp = timestamp;
		button.clickType = obj.isSingleClick ? CLICK_SINGLE : obj.isDoubleClick ? CLICK_DOUBLE : CLICK_HOLD;
		sendButtonEvent(button);
	} else {
		console.log("Event was ignored");
	}
});

//--------------------------------------------------------------------------------//

function getButtonName(data) {
	return 'flic_' + data.bdaddr.replace(new RegExp(':', 'g'), '');
}

function getBatteryIcon(battery_level) {
	if(battery_level >= 99) {
		return 'mdi:battery';
	} else if(battery_level < 99 && battery_level > CONFIG.WARNING_BATTERY_LEVEL) {
		return 'mdi:battery-' + (battery_level / 10) + "0";
	} else if(battery_level <= CONFIG.WARNING_BATTERY_LEVEL) {
		return 'mdi:battery-alert-variant-outline';
	}
}

function sendButtonBatteryAndState(button, state) {
	sendButtonState(button, state);
	sendButtonBattery(button);
}

function sendButtonState(button, state) {
	var data = JSON.parse(JSON.stringify(button));
	notifyHomeAssistant({
		'method': "POST",
		'url': CONFIG.SERVER_HOST + "/api/states/binary_sensor." + getButtonName(data),
		'content': JSON.stringify({
			'state': state,
			'attributes': {
				'batteryStatus': data.batteryStatus,
				'friendly_name': data.name == null ? getButtonName(data) : data.name
			}
		})
	});
}

function sendButtonBattery(button) {
	var data = JSON.parse(JSON.stringify(button));
	notifyHomeAssistant({
		'method': "POST",
		'url': CONFIG.SERVER_HOST + "/api/states/sensor." + getButtonName(data) + "_battery",
		'content': JSON.stringify({
			'state': data.batteryStatus,
			'attributes': {
				'device_class': 'battery',
				'unit_of_measurement': '%',
				'icon': getBatteryIcon(data.batteryStatus),
				'friendly_name': (data.name == null ? getButtonName(data) : data.name) + " Battery"
			}
		})
	});
}

function sendButtonEvent(event) {
	var data = JSON.parse(JSON.stringify(event));
	notifyHomeAssistant({
		'method': "POST",
		'url': CONFIG.SERVER_HOST + "/api/events/flic_click",
		'content': JSON.stringify({
			'button_name': getButtonName(data),
			'button_address': data.bdaddr,
			'click_type': data.clickType
		})
	});
}

function notifyHomeAssistant(options) {
	options.headers = {
		'Authorization': 'Bearer ' + CONFIG.SERVER_AUTH_TOKEN,
		'Content-Type': 'application/json'
	};
	requestManager.makeRequest(options, function (error, result) {
		if(error != null)  {
			console.log(JSON.stringify(options));
			console.log(JSON.stringify(error));
		} else if(result.statusCode >= 300) {
			console.log(JSON.stringify(options));
			console.log(JSON.stringify(result));
		}
	});
}
1 Like

Hi @blunan,

Thank you for taking the time to reply back and provide a thorough explanation of how it works. I tested the code and it worked! The states show properly now, I can finally stop pulling my hair out!

I’m getting a better understanding of how all of this functions together.

Thank you!

In order to understand what’s going on here. Can you correct my recap if needed?

So the Flicd addon as described above is the solution to get your flicks working when you pair them directly to the home assistant using the bluetooth connection.

The solution that kind Sir Blunan has proposed makes it possible to use a flic that has a connection to the flic hub. Meaning, you can add flics to the hub as much as you want and then you can find them in your Home Assistant?

In that way your range is increased, since the hub has a really good range compared to for instance the raspberry Pi. AND you no longer need to use webhooks/internet requests to use the flics correctly?

@balens Yes, your assumption is correct.
When using the bridge either with custom code configured (or setting up Webhook-Calls for each button) you don’t need the flic-Addon.

All you need to do is listening for the incoming calls from the flic-Hub and do the Automationssystem accordingly

I got it working!!! I don’t know what I did but it worked!!! Thank you @blunan

As I always want more, is there a way to turn your flic buttons into devices too?

Not via the flic-Hub integration. If you want flic button as devices you need to go for the flicd-solution and pair the buttons to your Pi directly (no hub).
But why would you want them as devices in HA?

Hi @blunan, thanks for taking the time to share your Flic Hub integration. Unfortunately I’ve stumbled over an early hurdle and could use some advice…

I’ve copied the required files into the Flic IDE and amended the config.js file - but once I run the module, I receive a “connect timed out” error.

  • SERVER_HOST = my HA IP
  • SERVER_AUTH_TOKEN = a new long life token
  • My HA configuration.yaml file includes default_config: line (which as I understand it enables the REST API)

Any ideas as to why I’m unable to connect to HA? Thanks in advance!

This shouldn’t be just your HA IP.

It needs to include the protocol and port number to look like this:
const SERVER_HOST = 'http://192.168.XXX.YYY:8123';

1 Like

(post deleted by author)