<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Developers]]></title><description><![CDATA[Discussion and help about the Flic SDKs ]]></description><link>https://community.flic.io/category/8</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 21:23:18 GMT</lastBuildDate><atom:link href="https://community.flic.io/category/8.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 09 Apr 2026 15:30:51 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Detect Flic Duo Buttons]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> Thank you</p>
]]></description><link>https://community.flic.io/topic/18622/detect-flic-duo-buttons</link><guid isPermaLink="true">https://community.flic.io/topic/18622/detect-flic-duo-buttons</guid><dc:creator><![CDATA[Beckintosh]]></dc:creator><pubDate>Thu, 09 Apr 2026 15:30:51 GMT</pubDate></item><item><title><![CDATA[Remote Configuration of Virtual Devices and Action Messages]]></title><description><![CDATA[<p dir="auto"><a href="https://community.hubitat.com/t/release-flic-hub-integration-for-flic-twist-flic-button/161287" rel="nofollow ugc">https://community.hubitat.com/t/release-flic-hub-integration-for-flic-twist-flic-button/161287</a></p>
]]></description><link>https://community.flic.io/topic/18613/remote-configuration-of-virtual-devices-and-action-messages</link><guid isPermaLink="true">https://community.flic.io/topic/18613/remote-configuration-of-virtual-devices-and-action-messages</guid><dc:creator><![CDATA[Ultim8]]></dc:creator><pubDate>Sun, 08 Feb 2026 01:19:34 GMT</pubDate></item><item><title><![CDATA[Unable to Get RSSI from Flic 2 Using fliclib-linux-hci on Raspberry Pi]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> Ya it be a great help write now i am using a python progame on pi to run 24/7 to recive signal for flic device i have provide the code below</p>
#!/usr/bin/env python3
import fliclib
from datetime import datetime

button_rssi = {}

def now_ts():
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]

# Advertisement RSSI (best-effort)
def on_advertisement_packet(scanner, bd_addr, name, rssi, is_private,
                           already_verified, already_connected_to_this_device,
                           already_connected_to_other_device):
    button_rssi[bd_addr] = rssi
    print(f"{now_ts()} ADV {bd_addr} RSSI={rssi} dBm")

def on_button_event(channel, click_type, was_queued, time_diff):
    click_name = str(click_type).split(".")[-1]
    rssi = button_rssi.get(channel.bd_addr, "N/A")
    print(f"{now_ts()} BUTTON {channel.bd_addr} {click_name} RSSI={rssi}")

def got_button(bd_addr):
    print(f"{now_ts()} Found verified button {bd_addr}")
    cc = fliclib.ButtonConnectionChannel(bd_addr)
    cc.on_button_single_or_double_click_or_hold = on_button_event
    client.add_connection_channel(cc)

# ---- MAIN ----
client = fliclib.FlicClient("localhost")
#scanner = fliclib.ButtonScanner(client)
scanner = fliclib.ButtonScanner()
scanner.on_advertisement_packet = on_advertisement_packet
client.add_scanner(scanner)
client.on_new_verified_button = got_button
client.handle_events()
dietpi@DietPi:~$ 

]]></description><link>https://community.flic.io/topic/18612/unable-to-get-rssi-from-flic-2-using-fliclib-linux-hci-on-raspberry-pi</link><guid isPermaLink="true">https://community.flic.io/topic/18612/unable-to-get-rssi-from-flic-2-using-fliclib-linux-hci-on-raspberry-pi</guid><dc:creator><![CDATA[Wand7698]]></dc:creator><pubDate>Fri, 06 Feb 2026 12:54:01 GMT</pubDate></item><item><title><![CDATA[Flic duo gesture and twist sensitivity]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5330">@rickard</a> If anyone else wants me a chatgpt (98% chatgpt) did this</p>
<p dir="auto">This basically uses a twist motion as a variable speed adjuster that keeps going after hitting value from flic (intended). For that reason the virtual volume/lights/blinds should not have a limiter, instead you configure the limiter here in main.js</p>
<p dir="auto">All you need to do is set up a virtual adjuster in the flic app and this will log the output. You can always then send this over mqtt or such</p>
// rateDetentController.js
//
// Key fixes in this version:
// 1) Soft recenter while neutral-latched (prevents UP/DOWN asymmetry)
// 2) Debounced "ease into fine mode" so jitter does NOT trigger fine mode
//
// No behavior changes elsewhere.

function clamp(x, min, max) {
  return x &lt; min ? min : (x &gt; max ? max : x);
}
function sign(x) {
  return x &gt; 0 ? 1 : (x &lt; 0 ? -1 : 0);
}

class RateDetentController {
  constructor(cfg) {
    this.cfg = cfg || {};

    this.tickMs = this.cfg.tickMs || 333;

    // Neutral hysteresis
    this.deadbandEnter = typeof this.cfg.deadbandEnter === "number" ? this.cfg.deadbandEnter : 5;
    this.deadbandExit  = typeof this.cfg.deadbandExit  === "number" ? this.cfg.deadbandExit  : 9;

    // Speed tiers
    this.tier1MaxOff = typeof this.cfg.tier1MaxOff === "number" ? this.cfg.tier1MaxOff : 25;
    this.tier2MaxOff = typeof this.cfg.tier2MaxOff === "number" ? this.cfg.tier2MaxOff : 50;
    this.tierHys     = typeof this.cfg.tierHys === "number"     ? this.cfg.tierHys     : 3;

    // Output clamp
    this.minOutPct = typeof this.cfg.minOutPct === "number" ? this.cfg.minOutPct : 0;
    this.maxOutPct = typeof this.cfg.maxOutPct === "number" ? this.cfg.maxOutPct : 100;

    // --- NEW: soft recenter tuning ---
    this.neutralRecenterAlpha =
      typeof this.cfg.neutralRecenterAlpha === "number"
        ? this.cfg.neutralRecenterAlpha
        : 0.08; // 8% per update while resting

    // --- NEW: debounce for easing into fine mode ---
    this.easeConfirmMs =
      typeof this.cfg.easeConfirmMs === "number"
        ? this.cfg.easeConfirmMs
        : 200;

    // State
    this.centerInPct = null;
    this.actualOutPct = typeof this.cfg.initialOutPct === "number" ? this.cfg.initialOutPct : null;

    this.fineMode = false;

    this.lastDir = 0;
    this.lastSpeed = 0;

    this.currentDir = 0;
    this.currentSpeed = 0;

    this.neutralLatched = false;
    this.speedLatched = 0;

    // For debouncing easing
    this._easeCandidateSince = null;
    this._easeCandidateDir = 0;

    this._lastIntentKey = null;

    this._timer = setInterval(() =&gt; this._tick(), this.tickMs);
  }

  _desiredSpeed(absOff) {
    if (absOff &lt;= this.tier1MaxOff) return 1;
    if (absOff &lt;= this.tier2MaxOff) return 2;
    return 3;
  }

  _updateLatchedSpeed(desired, absOff) {
    if (this.speedLatched === 0) {
      this.speedLatched = desired;
      return;
    }

    if (this.speedLatched === 1) {
      if (desired &gt;= 2 &amp;&amp; absOff &gt;= (this.tier1MaxOff + this.tierHys)) this.speedLatched = 2;
      if (desired === 3 &amp;&amp; absOff &gt;= (this.tier2MaxOff + this.tierHys)) this.speedLatched = 3;
      return;
    }

    if (this.speedLatched === 2) {
      if (absOff &lt;= (this.tier1MaxOff - this.tierHys)) { this.speedLatched = 1; return; }
      if (desired === 3 &amp;&amp; absOff &gt;= (this.tier2MaxOff + this.tierHys)) { this.speedLatched = 3; return; }
      return;
    }

    if (this.speedLatched === 3) {
      if (absOff &lt;= (this.tier2MaxOff - this.tierHys)) this.speedLatched = 2;
    }
  }

  _baseIntent(rawInPct) {
    if (this.centerInPct === null) {
      this.centerInPct = rawInPct;
      this.neutralLatched = true;
      this.speedLatched = 0;
      return { dir: 0, speed: 0, desiredSpeed: 0, reason: "center set" };
    }

    const off = rawInPct - this.centerInPct;
    const absOff = Math.abs(off);

    // --- Sticky neutral with SOFT RECENTER ---
    if (this.neutralLatched) {
      if (absOff &lt;= this.deadbandExit) {
        // soft recenter while resting
        this.centerInPct =
          this.centerInPct +
          this.neutralRecenterAlpha * (rawInPct - this.centerInPct);

        this.speedLatched = 0;
        return { dir: 0, speed: 0, desiredSpeed: 0, reason: "deadband (latched)" };
      }
      this.neutralLatched = false;
    } else {
      if (absOff &lt;= this.deadbandEnter) {
        this.neutralLatched = true;
        this.speedLatched = 0;
        return { dir: 0, speed: 0, desiredSpeed: 0, reason: "deadband (enter)" };
      }
    }

    const dir = sign(off);
    const desiredSpeed = this._desiredSpeed(absOff);
    this._updateLatchedSpeed(desiredSpeed, absOff);

    const speed = (this.speedLatched === 0) ? 1 : this.speedLatched;
    return { dir, speed, desiredSpeed, reason: "detent" };
  }

  _applyFineMode(base) {
    const { dir, speed, desiredSpeed } = base;
    const now = Date.now();

    const directionChanged =
      (this.lastDir !== 0 &amp;&amp; dir !== 0 &amp;&amp; dir !== this.lastDir);

    const hitNeutralFromIntent =
      (this.lastSpeed &gt; 0 &amp;&amp; speed === 0);

    // --- Debounced easing detection ---
    let easedConfirmed = false;

    const easingCandidate =
      (this.lastSpeed &gt;= 2 &amp;&amp;
       desiredSpeed &gt; 0 &amp;&amp;
       desiredSpeed &lt; this.lastSpeed &amp;&amp;
       dir === this.lastDir);

    if (easingCandidate) {
      if (this._easeCandidateSince === null) {
        this._easeCandidateSince = now;
        this._easeCandidateDir = dir;
      } else if (
        this._easeCandidateDir === dir &amp;&amp;
        (now - this._easeCandidateSince) &gt;= this.easeConfirmMs
      ) {
        easedConfirmed = true;
      }
    } else {
      this._easeCandidateSince = null;
      this._easeCandidateDir = 0;
    }

    if (!this.fineMode &amp;&amp; (directionChanged || hitNeutralFromIntent || easedConfirmed)) {
      this.fineMode = true;
      this._easeCandidateSince = null;

      if (speed === 0) return { dir: 0, speed: 0, note: "enter fine (neutral)" };
      if (directionChanged) return { dir, speed: 1, note: "enter fine (turn)" };
      if (easedConfirmed) return { dir, speed: 1, note: "enter fine (ease)" };
      return { dir, speed: 1, note: "enter fine" };
    }

    if (this.fineMode) {
      if (speed === 0) return { dir: 0, speed: 0, note: "fine mode" };
      return { dir, speed: 1, note: "fine mode" };
    }

    return { dir, speed, note: null };
  }

  updateRaw(rawInPct) {
    if (typeof rawInPct !== "number") return null;

    if (this.actualOutPct === null) this.actualOutPct = this.minOutPct;
    if (this.centerInPct === null) this.centerInPct = rawInPct;

    const base = this._baseIntent(rawInPct);
    const applied = this._applyFineMode(base);

    this.currentDir = applied.dir;
    this.currentSpeed = applied.speed;

    const note = applied.note || base.reason || null;

    const key =
      this.currentDir + "|" +
      this.currentSpeed + "|" +
      (this.fineMode ? "F" : "-") + "|" +
      (this.neutralLatched ? "N" : "-") + "|" +
      (note || "");

    const intentChanged = (key !== this._lastIntentKey);
    this._lastIntentKey = key;

    this.lastDir = this.currentDir;
    this.lastSpeed = this.currentSpeed;

    return {
      intentChanged,
      rawInPct,
      dir: this.currentDir,
      speed: this.currentSpeed,
      fineMode: this.fineMode,
      note
    };
  }

  _tick() {
    if (this.actualOutPct === null) return;
    if (this.currentDir === 0 || this.currentSpeed === 0) return;

    this.actualOutPct = clamp(
      this.actualOutPct + (this.currentDir * this.currentSpeed),
      this.minOutPct,
      this.maxOutPct
    );
  }

  getActualOutPct() {
    return (this.actualOutPct === null) ? null : Math.round(this.actualOutPct);
  }

  stop() {
    if (this._timer) {
      clearInterval(this._timer);
      this._timer = null;
    }
    return this.getActualOutPct();
  }
}

module.exports = RateDetentController;


<p dir="auto">That can be tested with a main.js like this</p>
var buttons = require("buttons");
var flicapp = require("flicapp");
var RateDetentController = require("./rateDetentController");

var ROTATE_ARM_MS = 700;
var CLICK_SUPPRESS_AFTER_ROTATE_MS = 800;

var speakerVirtualDeviceId = null;
var lightVirtualDeviceId = null;
var blindVirtualDeviceId = null;

var stateByKey = {};
var rotateSessionByBdaddr = {};
var suppressClicksUntilByBdaddr = {};

var ctrlByKey = {};
var lastFinalOutByDevKey = {};

function keyOf(obj) { return obj.bdaddr + ":" + obj.buttonNumber; }
function sizeLabel(buttonNumber) { return buttonNumber === 0 ? "BIG" : "small"; }
function clamp01(x) { return x &lt; 0 ? 0 : (x &gt; 1 ? 1 : x); }
function toPct01(x01) { return typeof x01 === "number" ? Math.round(clamp01(x01) * 100) : null; }
function pctTo01(pct) { return clamp01(pct / 100); }
function isInRotateMode(bdaddr) { return !!rotateSessionByBdaddr[bdaddr]; }
function dirText(d) { return d &gt; 0 ? "UP" : (d &lt; 0 ? "DOWN" : "NEUTRAL"); }

function clearArmTimer(st) {
  if (st &amp;&amp; st.armTimer) { clearTimeout(st.armTimer); st.armTimer = null; }
}
function startRotateMode(st) {
  if (!st || st.rotateArmed) return;
  st.rotateArmed = true;
  rotateSessionByBdaddr[st.bdaddr] = { key: st.key, sizeLabel: st.sizeLabel, startedPrinted: false };
}

function inToOut(inPct, minOut, maxOut) {
  var range = maxOut - minOut;
  if (range &lt;= 0) return minOut;
  return minOut + (inPct / 100) * range;
}
function outToIn(outPct, minOut, maxOut) {
  var range = maxOut - minOut;
  if (range &lt;= 0) return 0;
  var v = ((outPct - minOut) / range) * 100;
  if (v &lt; 0) v = 0;
  if (v &gt; 100) v = 100;
  return Math.round(v);
}
function syncVirtualFromOut(type, id, outPct, minOut, maxOut) {
  var inPct = outToIn(outPct, minOut, maxOut);
  var v01 = pctTo01(inPct);

  if (type === "Speaker") flicapp.virtualDeviceUpdateState("Speaker", id, { volume: v01 });
  else if (type === "Light") flicapp.virtualDeviceUpdateState("Light", id, { brightness: v01 });
  else if (type === "Blind") flicapp.virtualDeviceUpdateState("Blind", id, { position: v01 });
}

// ---- buttons ----
buttons.on("buttonDown", function (obj) {
  if (!obj) return;

  var k = keyOf(obj);
  stateByKey[k] = {
    key: k,
    bdaddr: obj.bdaddr,
    buttonNumber: obj.buttonNumber,
    sizeLabel: sizeLabel(obj.buttonNumber),
    rotateArmed: false,
    armTimer: setTimeout(function () { startRotateMode(stateByKey[k]); }, ROTATE_ARM_MS)
  };
});

buttons.on("buttonUp", function (obj) {
  if (!obj) return;

  var k = keyOf(obj);
  var st = stateByKey[k];

  clearArmTimer(st);

  if (isInRotateMode(obj.bdaddr)) {
    delete rotateSessionByBdaddr[obj.bdaddr];
    suppressClicksUntilByBdaddr[obj.bdaddr] = Date.now() + CLICK_SUPPRESS_AFTER_ROTATE_MS;

    var keys = Object.keys(ctrlByKey);
    for (var i = 0; i &lt; keys.length; i++) {
      var entry = ctrlByKey[keys[i&rsqb;&rsqb;;
      if (!entry || entry.bdaddr !== obj.bdaddr) continue;

      var finalOut = entry.ctrl.stop();
      if (finalOut !== null) {
        console.log(entry.label + " - rotate end - " + entry.prettyName + " - final out " + finalOut + "%");
        lastFinalOutByDevKey[entry.devKey] = finalOut;
        syncVirtualFromOut(entry.type, entry.id, finalOut, entry.minOut, entry.maxOut);
      }

      delete ctrlByKey[keys[i&rsqb;&rsqb;;
    }
  }

  if (st &amp;&amp; !st.rotateArmed) {
    if (obj.gesture === "up" || obj.gesture === "down" || obj.gesture === "left" || obj.gesture === "right") {
      console.log(st.sizeLabel + " - " + obj.gesture.toUpperCase());
    }
  }

  delete stateByKey[k];
});

buttons.on("buttonSingleOrDoubleClick", function (obj) {
  if (!obj) return;
  if (isInRotateMode(obj.bdaddr)) return;

  var suppressUntil = suppressClicksUntilByBdaddr[obj.bdaddr] || 0;
  if (Date.now() &lt; suppressUntil) return;

  var lbl = sizeLabel(obj.buttonNumber);
  console.log(lbl + (obj.isDoubleClick === true ? " - DOUBLECLICK" : " - CLICK"));
});

// ---- rotate ----
flicapp.on("virtualDeviceUpdate", function (metaData, values) {
  if (!metaData || !metaData.dimmableType || !metaData.virtualDeviceId) return;

  var bdaddr = metaData.buttonId;
  if (!bdaddr) return;

  var session = rotateSessionByBdaddr[bdaddr];
  if (!session) return;

  var type = metaData.dimmableType;
  var id = metaData.virtualDeviceId;

  if (type === "Speaker" &amp;&amp; speakerVirtualDeviceId === null) speakerVirtualDeviceId = id;
  if (type === "Light" &amp;&amp; lightVirtualDeviceId === null) lightVirtualDeviceId = id;
  if (type === "Blind" &amp;&amp; blindVirtualDeviceId === null) blindVirtualDeviceId = id;

  if (type === "Speaker" &amp;&amp; id !== speakerVirtualDeviceId) return;
  if (type === "Light" &amp;&amp; id !== lightVirtualDeviceId) return;
  if (type === "Blind" &amp;&amp; id !== blindVirtualDeviceId) return;

  var inPct = null;
  var prettyName = null;

  if (type === "Speaker") { inPct = values &amp;&amp; typeof values.volume === "number" ? toPct01(values.volume) : null; prettyName = "tv speaker"; }
  else if (type === "Light") { inPct = values &amp;&amp; typeof values.brightness === "number" ? toPct01(values.brightness) : null; prettyName = "living room lights"; }
  else if (type === "Blind") { inPct = values &amp;&amp; typeof values.position === "number" ? toPct01(values.position) : null; prettyName = "test"; }

  if (inPct === null) return;

  var devKey = bdaddr + "|" + type + "|" + id;
  var entry = ctrlByKey[devKey];

  var minOut = 0, maxOut = 100;
  if (type === "Speaker") { minOut = 0; maxOut = 80; }
  else if (type === "Light") { minOut = 5; maxOut = 100; }
  else if (type === "Blind") { minOut = 0; maxOut = 100; }

  if (!entry) {
    var storedOut = lastFinalOutByDevKey[devKey];
    var startOut = (typeof storedOut === "number") ? storedOut : Math.round(inToOut(inPct, minOut, maxOut));

    syncVirtualFromOut(type, id, startOut, minOut, maxOut);

    var label = session.sizeLabel;

    var ctrl = new RateDetentController({
      initialOutPct: startOut,
      tickMs: 333,

      // STICKY NEUTRAL (tweak here)
      deadbandEnter: 5,
      deadbandExit: 9,

      // SENSITIVITY
      tier1MaxOff: 25,
      tier2MaxOff: 40,
      extremeBandPct: 10,

      minOutPct: minOut,
      maxOutPct: maxOut
    });

    entry = {
      bdaddr: bdaddr,
      devKey: devKey,
      type: type,
      id: id,
      prettyName: prettyName,
      label: label,
      ctrl: ctrl,
      minOut: minOut,
      maxOut: maxOut,
      lastOut: null
    };

    ctrlByKey[devKey] = entry;

    if (!session.startedPrinted) {
      session.startedPrinted = true;
      console.log(label + " - rotate mode - start " + prettyName + " - out " + startOut + "% (in " + outToIn(startOut, minOut, maxOut) + "%)");
    }
  }

  var u = entry.ctrl.updateRaw(inPct);
  if (!u) return;

  var outNow = entry.ctrl.getActualOutPct();

  // intent change line
  if (u.intentChanged) {
    console.log(
      entry.label + " - " + entry.prettyName +
      " - out " + (outNow === null ? "?" : outNow) + "% - " +
      dirText(u.dir) + " " + u.speed +
      " - in " + inPct + "%" +
      (u.note ? " - " + u.note : "")
    );
  }

  // tick/output line (only if output changed)
  if (outNow !== null &amp;&amp; outNow !== entry.lastOut) {
    entry.lastOut = outNow;
    console.log(entry.label + " - " + entry.prettyName + " - out " + outNow + "% - " + dirText(u.dir) + " " + u.speed);
  }
});

console.log("Ready. Short press: click/double + gesture. Hold &gt;= 700ms: rotate-only until release.");


]]></description><link>https://community.flic.io/topic/18611/flic-duo-gesture-and-twist-sensitivity</link><guid isPermaLink="true">https://community.flic.io/topic/18611/flic-duo-gesture-and-twist-sensitivity</guid><dc:creator><![CDATA[rickard]]></dc:creator><pubDate>Wed, 28 Jan 2026 15:43:15 GMT</pubDate></item><item><title><![CDATA[Flic Duo Button Identification JS]]></title><description><![CDATA[<p dir="auto">I just spent too long trying to figure this out since the documentation is not up to date and the chatGPT bot is just wrong.</p>
<p dir="auto">Anyways I thought I would share how I am handling my first Flic Duo device to trigger different Home Assistant automations using the different buttons and webhooks . Hopefully this might save other people some time and effort.</p>
<pre><code>main.js

var buttonManager = require("buttons");
var http = require("http");

buttonManager.on("buttonSingleOrDoubleClickOrHold", function(obj) {
	var button = buttonManager.getButton(obj.bdaddr);
	var clickType = obj.isSingleClick ? "click" : obj.isDoubleClick ? "double_click" : "hold";
	var payload = JSON.stringify({
		button_name: button.name,
		click_type: clickType,
	});

	var targetUrl = null;

	if (button.name === "lock") {
		targetUrl = "http://XXX.XXX.XX.XX:8123/api/webhook/flic-lock";
	} else if (button.name === "auto1") {
		targetUrl = "http://XXX.XXX.XX.XX:8123/api/webhook/flic-leavingHome";
	} else if (button.name === "duo1") {
			if (obj.buttonNumber === 0) {
				targetUrl = "http://XXX.XXX.XX.XX:8123/api/webhook/flic-duo1-big";
			} else if (obj.buttonNumber === 1) {
				targetUrl = "http://XXX.XXX.XX.XX:8123/api/webhook/flic-duo1-small";
			}
	}

	if (targetUrl) {
		http.makeRequest({
			url: targetUrl,
			method: "POST",
			headers: {"Content-Type": "application/json"},
			content: payload,
		}, function(err, res) {
			console.log("");
			console.log("Sent to: " + targetUrl);
			console.log("Name: " + button.name);
			console.log("ID (bdaddr): " + button.bdaddr);
			console.log("Serial: " + button.serialNumber);
			console.log("Click Type: " + clickType);
			console.log("uuid: " + button.uuid);
			console.log("key: " + button.key);
			//console.log("Button #: " + obj.buttonNumber);
			console.log("Status: " + res.statusCode);
		});
	}
});

console.log("Script started");
</code></pre>
<p dir="auto"><strong>obj.buttonNumber</strong> returns <strong>0 for the upper bigger button</strong> and <strong>1 for the smaller lower button</strong></p>
<p dir="auto">You can also perform different automations depending on click type using an if statement where you change the keyword click using something like (YAML):</p>
<pre><code>conditions:
  - condition: template
    value_template: "{{ trigger.json.click_type == 'click' }}"
</code></pre>
<p dir="auto">The HA automation webhook trigger YAML looks something like:</p>
<pre><code>triggers:
  - allowed_methods:
      - POST
      - PUT
    local_only: true
    webhook_id: flic-leavingHome
    trigger: webhook
</code></pre>
<p dir="auto">This might not be the best way to go about this but I would be interested to hear suggestions for improvements. Now do add the rest of the new buttons and model the dimensions as a 3D STL file. It would be nice if flic also provided this as well.</p>
]]></description><link>https://community.flic.io/topic/18601/flic-duo-button-identification-js</link><guid isPermaLink="true">https://community.flic.io/topic/18601/flic-duo-button-identification-js</guid><dc:creator><![CDATA[flicIngConfused]]></dc:creator><pubDate>Sat, 20 Dec 2025 03:38:26 GMT</pubDate></item><item><title><![CDATA[Flic Hub Studio Virtual Device does not appear as a device option in twist configuration]]></title><description><![CDATA[<p dir="auto">I have the new app installed and have successfully setup flic twists to control the volumes in 3 different Biamp Cambridge Zones.  Thank you for the feature!</p>
]]></description><link>https://community.flic.io/topic/18586/flic-hub-studio-virtual-device-does-not-appear-as-a-device-option-in-twist-configuration</link><guid isPermaLink="true">https://community.flic.io/topic/18586/flic-hub-studio-virtual-device-does-not-appear-as-a-device-option-in-twist-configuration</guid><dc:creator><![CDATA[mikdav]]></dc:creator><pubDate>Sun, 19 Oct 2025 21:40:54 GMT</pubDate></item><item><title><![CDATA[Flic as a security device]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5337">@gordon-0</a> As the "Internet Request" action in the app is designed, it unfortunately does not contain any type of cryptographic signature that you can verify to make sure the request (when received) itself actually originated from the press of the button. The only thing you can do is to provide credentials or something in the headers of the Internet Request, but those you have to design and implement yourself.</p>
]]></description><link>https://community.flic.io/topic/18580/flic-as-a-security-device</link><guid isPermaLink="true">https://community.flic.io/topic/18580/flic-as-a-security-device</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Mon, 29 Sep 2025 10:42:54 GMT</pubDate></item><item><title><![CDATA[&quot;Alternative keymap&quot; enter key with iOS 18]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/94">@oskar</a></p>
<p dir="auto">Thanks for the update. I appreciate it.</p>
<p dir="auto">I've also logged an issue with the WebKit project in case they can shed any light: <a href="https://bugs.webkit.org/show_bug.cgi?id=290779" rel="nofollow ugc">https://bugs.webkit.org/show_bug.cgi?id=290779</a></p>
]]></description><link>https://community.flic.io/topic/18548/alternative-keymap-enter-key-with-ios-18</link><guid isPermaLink="true">https://community.flic.io/topic/18548/alternative-keymap-enter-key-with-ios-18</guid><dc:creator><![CDATA[josh.k]]></dc:creator><pubDate>Mon, 24 Mar 2025 20:54:16 GMT</pubDate></item><item><title><![CDATA[Location permission denied]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> That fixes the issue. Thanks!</p>
]]></description><link>https://community.flic.io/topic/18546/location-permission-denied</link><guid isPermaLink="true">https://community.flic.io/topic/18546/location-permission-denied</guid><dc:creator><![CDATA[bmatest0910]]></dc:creator><pubDate>Wed, 19 Mar 2025 13:53:39 GMT</pubDate></item><item><title><![CDATA[Crypto for secured requests]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/94">@oskar</a> That's great thank you! I just managed to separate the logic to different files so it's shaping up well. Thanks for the help</p>
]]></description><link>https://community.flic.io/topic/18541/crypto-for-secured-requests</link><guid isPermaLink="true">https://community.flic.io/topic/18541/crypto-for-secured-requests</guid><dc:creator><![CDATA[beachb_sl]]></dc:creator><pubDate>Wed, 12 Mar 2025 23:41:12 GMT</pubDate></item><item><title><![CDATA[Flic Twist and Home Assistant for Twist Events]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5018">@sgemmen</a> Thanks for this, finally got around to setting it up. It wasn't working at first but realised I needed to add the two helpers (boolean and number) for the targets of the service.</p>
<p dir="auto">Now I need to work on using it to adjust all the lights in a room while keeping the relative brightness of them the same.</p>
<p dir="auto">EDIT: Found this add-on which seems to work - <a href="https://community.home-assistant.io/t/relative-brightness-light-group/695450" rel="nofollow ugc">https://community.home-assistant.io/t/relative-brightness-light-group/695450</a> - brightness changes are a bit jerky (not sure if this related to flic, the add-on, or something else) but it does the job for now.</p>
]]></description><link>https://community.flic.io/topic/18510/flic-twist-and-home-assistant-for-twist-events</link><guid isPermaLink="true">https://community.flic.io/topic/18510/flic-twist-and-home-assistant-for-twist-events</guid><dc:creator><![CDATA[Matthew Griffin]]></dc:creator><pubDate>Tue, 24 Dec 2024 19:29:18 GMT</pubDate></item><item><title><![CDATA[Flic Twist in SDK]]></title><description><![CDATA[<p dir="auto">any news on when the Flic Twist is going to be supported in the sDK - trying to get some value from the number of Twist buttons I've purchased... if native support for Home Assistant is not going to happen then please let us build our own custom sdk apps ourselves.</p>
<p dir="auto">the community sdk mqtt app is excellent and works great with Home Assistance albeit only with 'click', 'double-click' and 'hold' actions.. would dearly love to get twist actions supported..</p>
<p dir="auto">Thank you in advance..</p>
]]></description><link>https://community.flic.io/topic/18497/flic-twist-in-sdk</link><guid isPermaLink="true">https://community.flic.io/topic/18497/flic-twist-in-sdk</guid><dc:creator><![CDATA[martin 1]]></dc:creator><pubDate>Sat, 30 Nov 2024 19:34:39 GMT</pubDate></item><item><title><![CDATA[TlsFailure - Latenode Webhook]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5197">@dhtbrowne</a> I just tried. Seems to work fine now.</p>
]]></description><link>https://community.flic.io/topic/18481/tlsfailure-latenode-webhook</link><guid isPermaLink="true">https://community.flic.io/topic/18481/tlsfailure-latenode-webhook</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Thu, 10 Oct 2024 20:56:25 GMT</pubDate></item><item><title><![CDATA[Simple OSC Module Works...once]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> It works now! Thanks so much for your help!</p>
]]></description><link>https://community.flic.io/topic/18474/simple-osc-module-works-once</link><guid isPermaLink="true">https://community.flic.io/topic/18474/simple-osc-module-works-once</guid><dc:creator><![CDATA[ryan_joyner]]></dc:creator><pubDate>Mon, 09 Sep 2024 20:11:05 GMT</pubDate></item><item><title><![CDATA[Can&#x27;t seem to get the confirmation E-Mail for my device manager account]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/94">@oskar</a> Can now use the device Manager with my account, thank you for the support.</p>
]]></description><link>https://community.flic.io/topic/18450/can-t-seem-to-get-the-confirmation-e-mail-for-my-device-manager-account</link><guid isPermaLink="true">https://community.flic.io/topic/18450/can-t-seem-to-get-the-confirmation-e-mail-for-my-device-manager-account</guid><dc:creator><![CDATA[_Roy]]></dc:creator><pubDate>Tue, 21 May 2024 10:00:15 GMT</pubDate></item><item><title><![CDATA[IDE Commands]]></title><description><![CDATA[<p dir="auto">We have a business solution that might have the functionality you are looking for: <a href="https://flic.io/business/device-manager" rel="nofollow ugc">https://flic.io/business/device-manager</a>.</p>
]]></description><link>https://community.flic.io/topic/18435/ide-commands</link><guid isPermaLink="true">https://community.flic.io/topic/18435/ide-commands</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Wed, 03 Apr 2024 13:31:02 GMT</pubDate></item><item><title><![CDATA[Button Request Payload]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5125">@Y2K</a></p>
<p dir="auto">41842fed-e3fc-4ef3-853e-7be9b5e9650e-image.png</p>
<p dir="auto">729f7266-3441-4d10-a672-d5b0e3c8577f-image.png</p>
<p dir="auto">34165d4f-cc2e-4a43-9f0c-a00312388077-image.png</p>
]]></description><link>https://community.flic.io/topic/18434/button-request-payload</link><guid isPermaLink="true">https://community.flic.io/topic/18434/button-request-payload</guid><dc:creator><![CDATA[Y2K]]></dc:creator><pubDate>Mon, 01 Apr 2024 19:02:29 GMT</pubDate></item><item><title><![CDATA[Example code for IR signal?]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5092">@jakekapsandy</a> here is an example:</p>
var ir = require('ir');

var arr = [48256, 7029, 3405, 418, 445, 418, 445, 418, 445, 421, 445, 421, 448, 418, 445, 421, 445, 416, 445, 421, 445, 418, 445, 418, 445, 418, 445, 424, 1293, 418, 1296, 416, 448, 418, 445, 426, 445, 424, 1296, 421, 445, 416, 445, 421, 445, 424, 445, 418, 445, 421, 445, 418, 1293, 424, 445, 421, 1293, 416, 1293, 418, 1293, 424, 1293, 421, 1293, 418, 1293, 421, 34946, 7053, 1709, 421];

ir.play(new Uint32Array(arr), function(error) {
	console.log(error);
});

]]></description><link>https://community.flic.io/topic/18433/example-code-for-ir-signal</link><guid isPermaLink="true">https://community.flic.io/topic/18433/example-code-for-ir-signal</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Fri, 29 Mar 2024 18:27:26 GMT</pubDate></item><item><title><![CDATA[flic with AWS]]></title><description><![CDATA[<p dir="auto">I am sucessfully using the  SDK to send HTTP Post to an AWS Lambda URL, which is great.  However, I can't seem to make this work with AWS Signature Version 4, which would allow me to secure my endpoint.  Is that possible with the current version of the SDK?  Thanks for any help!</p>
]]></description><link>https://community.flic.io/topic/18431/flic-with-aws</link><guid isPermaLink="true">https://community.flic.io/topic/18431/flic-with-aws</guid><dc:creator><![CDATA[hlbischoff]]></dc:creator><pubDate>Fri, 22 Mar 2024 13:28:44 GMT</pubDate></item><item><title><![CDATA[Internet Request replacement tokens available?]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> Thanks!  That's super helpful.</p>
]]></description><link>https://community.flic.io/topic/18427/internet-request-replacement-tokens-available</link><guid isPermaLink="true">https://community.flic.io/topic/18427/internet-request-replacement-tokens-available</guid><dc:creator><![CDATA[ai-please-ai]]></dc:creator><pubDate>Sun, 10 Mar 2024 02:55:04 GMT</pubDate></item><item><title><![CDATA[Flic2 buttons disconnect and reconnect]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/2741">@info-6</a> Sorry, I am not sure if I exactly understand your question. Due to radio circumstances, it's normal for the button to occassionally drop the connection. Also if you enable Passive mode, the button will disconnect automatically after some time of inactivity. If the button is currently not connected, it will attempt to connect when you press it.</p>
]]></description><link>https://community.flic.io/topic/18420/flic2-buttons-disconnect-and-reconnect</link><guid isPermaLink="true">https://community.flic.io/topic/18420/flic2-buttons-disconnect-and-reconnect</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Fri, 16 Feb 2024 10:41:10 GMT</pubDate></item><item><title><![CDATA[Code does not work after stop button]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5039">@eddieAnd_1</a> you can close the browser window and the program will continue to run. It's just the text editor and control panel.</p>
]]></description><link>https://community.flic.io/topic/18414/code-does-not-work-after-stop-button</link><guid isPermaLink="true">https://community.flic.io/topic/18414/code-does-not-work-after-stop-button</guid><dc:creator><![CDATA[Emil]]></dc:creator><pubDate>Wed, 31 Jan 2024 09:11:21 GMT</pubDate></item><item><title><![CDATA[Flic API support for Twist]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/5035">@subscriptions</a> <a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/57">@Emil</a> Thanks for your response. Just caught the email about full matter launching soon, good to hear the SDK twist is coming up.</p>
<p dir="auto">Are there a lot of people using the matter integration? I've struggled to figure out anything I that I would use it for with the twist accept for investing time into creating a virtual matter device so I could use the twist events for my own uses...</p>
<p dir="auto">These are the things I have in my house. Are there any interesting use cases I'm missing?</p>
<p dir="auto">Smartthings<br />
Philips hue<br />
Sonos<br />
nanoleaf<br />
Google hubs (voice assistant)</p>
<p dir="auto">With sonos/hue integration already working with the twist with matter (which is great...) not sure what else I could do with it.</p>
<p dir="auto">Might be cool to see a list of matter integrations/demos with the twist functionality specifically? (more than a list of other companies that support matter)</p>
<p dir="auto">Thank you!</p>
]]></description><link>https://community.flic.io/topic/18397/flic-api-support-for-twist</link><guid isPermaLink="true">https://community.flic.io/topic/18397/flic-api-support-for-twist</guid><dc:creator><![CDATA[sgemmen]]></dc:creator><pubDate>Wed, 03 Jan 2024 08:21:01 GMT</pubDate></item><item><title><![CDATA[Your swagger.json seems broken]]></title><description><![CDATA[<p dir="auto">Hello,</p>
<p dir="auto">I'm currently implementing the Flic Device manager Api into our <a href="http://ASP.Net" rel="nofollow ugc">ASP.Net</a> Core application.</p>
<p dir="auto">Normally i just add the swagger.json to the project and let visual studio do the work for me but somehow this does not work for your swagger.json</p>
<p dir="auto">After the code is generated al functions do not return data only http status codes.</p>
<p dir="auto">So after comparing your swagger file to an other working swagger file it looks like the schema is missing in the 200 OK responses.</p>
<p dir="auto">I hope that someday it gets fixed so we don't need to code it ourselves</p>
]]></description><link>https://community.flic.io/topic/18395/your-swagger-json-seems-broken</link><guid isPermaLink="true">https://community.flic.io/topic/18395/your-swagger-json-seems-broken</guid><dc:creator><![CDATA[Dooie]]></dc:creator><pubDate>Thu, 28 Dec 2023 11:43:56 GMT</pubDate></item><item><title><![CDATA[Windows 11 will support fliclib-windows?]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="https://community.flic.io/uid/3346">@email</a> any update on this?</p>
]]></description><link>https://community.flic.io/topic/18392/windows-11-will-support-fliclib-windows</link><guid isPermaLink="true">https://community.flic.io/topic/18392/windows-11-will-support-fliclib-windows</guid><dc:creator><![CDATA[manoj.s]]></dc:creator><pubDate>Fri, 22 Dec 2023 15:25:59 GMT</pubDate></item></channel></rss>