New Flic Twist features for the Hub SDK
-
We are today announcing a Beta release of some new features in the Hub SDK that can be used together with Flic Twist.
In order to seamlessly continue to work with the rest of your smart home devices that you might have assigned to other triggers on the Flic Twist, we introduce the concept of Virtual Devices. A Virtual Device is handled by the Flic Hub firmware just like any other supported real device, but its functionality is implemented by the user in the Hub SDK, typically by writing some kind of bridge software that sends commands and receives update events over the LAN to/from the real device. If for example the brightness of a (real) light is changed by some external means, it is possible to tell the Flic Hub firmware from javascript about the new brightness level, which the hub then forwards to the Flic Twist, so that the LED status can update accordingly. That way when you twist it, it will start from the correct position.
We are also adding a "message" action that can be used to send arbitrary strings to your scripts whenever the action is triggered. The intended use case is to be able to trigger custom code also for Push/Double Push in the Selector feature or perform some action when a specific point is reached in Advanced Dimming or Scene Blender.
The virtual devices can be created in the Flic App and be set to be controlled by a Flic Twist as follows:
Using this piece of code, updates are received in your javascript code after configuring a virtual device to be triggered in the Flic App for a specific Flic Twist:
const flicapp = require("flicapp"); flicapp.on("virtualDeviceUpdate", (metaData, values) => { // The values object can contain hue, saturation, brightness, colorTemperature, volume, position (for blinds) console.log(`Twist ${metaData.buttonId} updated virtual device ${metaData.virtualDeviceId} of type ${metaData.dimmableType} with these values: ${JSON.stringify(values)}`); });
When a device is modified externally, we use this function to inform the system of the change:
flicapp.virtualDeviceUpdateState(dimmableType, virtualDeviceId, values);
The
dimmableType
can be either "Light", "Speaker" or "Blind". Thevalues
is an object containing at least one of the fields mentioned above that is appropriate for the correspondingdimmableType
. For example:flicapp.virtualDeviceUpdateState("Light", "my_ceiling_light", {hue: 0.6, saturation: 0.7, brightness: 0.8});
The values themselves are always floating point numbers between 0 and 1.
Configure an action message to be triggered by assigning the following action in the Flic app:
The action messages are easy to receive, just register a listener as follows:
flicapp.on("actionMessage", message => console.log(`Got a message: ${message}`));
We'd love to hear your feedback!
-
@mosthated Sorry forgot to mention that only the iOS app shows this provider right now. It will come later to Android.
-
How do I enable these features? I do not see anything related to virtual devices in the flic app, and it looks like the most recent update available is 3.12.3 from 02/11/2025. I don't see any options or settings, either in the play store, or in the app to enable any sort of beta access.
My hub itself is showing v4.4.0. I don't see anything 'Studio' related showing up in providers, or in any settings.
-
Here's a quick and dirty script I created to test volume control. Might be errors (even dragons) here, use at own risk. Maybe it's useful for someone sometime…I don't know.
const buttonManager = require("buttons"); const flicapp = require('flicapp'); const net = require("net"); const http = require("http"); const client = 'INSERT IP ADRESS HERE' const port = 4710; let client = new net.Socket(); var muteCommand = Buffer.from('set /devices/0/outputs/20/Mute/value/true \0', 'utf-8'); var volumeCommand = Buffer.from('set /devices/0/outputs/20/CRMonitorLevelTapered/value/ '); flicapp.on("actionMessage", function(message) { if(message == 'mute') { sendToSocket(muteCommand); } // handle more (else) cases here }); function sendToSocket(msg) { client.connect(port, client, function() => { client.write(msg); }) }; flicapp.on("virtualDeviceUpdate", function(metaData, values) { let virtualID = metaData.virtualDeviceId; if(values.volume && values.volume != "") { sendToSocket(volumeCommand + values.volume + ' \0'); } // console.log(metaData.virtualDeviceId); // console.log(values.volume); });
-
Nice. I already got it up and running with a couple of custom volume controls. I use it in my home studio (remote controlling input/output volume on Universal Audio gear, controlling playback and recording when tracking vocals and drums etc), and one for my home surround system as well.
Although…
Can you PLEASE update the existing Spotify Connect "provider"/service to also include the volume (up, down, mute) endpoints as well as the existing ones?
It would require next to no time and effort for you to configure, but it would probably make a world of difference for a lot of the "average" end users of your products.
Think about it…the access token/authentication mechanisms are already there, the Spotify volume endpoints have been up and ready to serve since long before the dinosaurs, and it wouldn't require anything out of the ordinary to add it to your already working Spotify service provider.
Don't get me wrong. The Hub SDK is really great now with the latest updates. I enjoy and love that level of flexibility and all the customization goodies, but it's clearly not for everyone - as the learning curve can be somewhat steep and in my opinion it's a total overkill if you have no prior programming skills or interest, but still want to make use of your Flic hub, Twist, Flic 2 button, Duo or whatever. Yay or nay? Oh and btw, great work. I don't just say that
(And please fix the Flic 2 Universal MIDI functionality, as it's useless at this point).
🤍
Andreas
-
@sgemmen Thanks! Fixed.
-
@Emil Been playing with this a bit and so far it's pretty great! Thank the team for landing this!
I noticed one thing..
I believe:
flicapp.virtualDeviceUpdateValue("Light", "my_ceiling_light", {hue: 0.6, saturation: 0.7, brightness: 0.8});
should be virtualDeviceUpdateState:
flicapp.virtualDeviceUpdateState("Light", "Virtual_light", {hue: 0.6, saturation: 0.7, brightness: 0.2});
That seems to work for me. UpdateValue results in a "TypeError: not a function".
-
Emil
-
@Emil Exciting update! Looking forward to giving it a go. Will report back. Thank you!