Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,

 

as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.

 

As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!

 

Regards,

Smart Home Forum by FIBARO Team


Recommended Posts

Posted

Long!

 

Welcome to episode #9 of “programs nobody needs”. This episode is for software devs only. I think it’s the last one in this series.

 

As usual - story time.

We all know (from school) that the known universe is inhabited by many species, among others the developers and the users. The former create software and sometimes try to make a living from it. The latter use that software and - if the developer wishes - are forced to pay certain fees for using it... Some users believe their interests are so fundamentally opposed to the interests of developers that they will do a lot of dirty tricks - often even when it’s very inconvenient - just to avoid paying. They roll back the date, reinstall, rip the program apart, and so on. And basically everyone would like to try a QuickApp before buying it, ideally as a “full demo”.

 

In Fibaro, most of the developers’ work (sometimes truly titanic work) can be used for free. But not always. There are many scripts that are paid and can cost even a 100+ EUR. They also have protections - encryption offered by HC plus custom protections written by the authors. I looked at some of those protections (obviously not all) and usually found a gap - with a bit of creativity, you could bypass them. I want to be clear: I did not use this to cheat authors and run their software for free.

I started thinking about building a framework that would eliminate all typical bypasses. It would give the developer control over issued licences, the ability to remotely disable a QuickApp (☠️), provide user with time-limited demo mode (and after user decision - convert it remotely to full licence either disable), and it could even collect usage statistics.

 

And that’s how this was born:
The LiceMan (Licence Manager)

 

It comes as an add-on (a toolbox) for a QA, and with it you can manage the licence remotely. Two basic starting conditions:

  • you need a free or paid GitHub account
  • the app for the user must be encrypted

And with that, you get full control over how the user runs your QuickApp, without having any access to the customer’s hub.

 

How does it work and what does it allow?

Using a simple text file (JSON) stored on GitHub, the developer can:

  • Enable / disable a module with one field (mode)
    "full" - full licence
    "demo_timed" - time-limited full demo (active only until the end of the trial)
    "blocked" - immediate block
  • Decide whether a full licence is unlimited or time-limited
    full without expiresAt = unlimited
    full with expiresAt = active until that date, then depending on graceUntil, then stop
  • Control the “grace period” after a full licence expires (graceUntil)
    if expiresAt has passed but graceUntil has not - the module still works, only the reason changes to full_expired (meaning “works, but after the deadline”)
    after graceUntil - hard block (isActive=false, reason=full_expired)
  • Set the demo length (trialLengthDays)
  • additionally, cut the demo by a hard date (expiresAt)
    so you can give a 30-day trial, but still cut everything on a specific date
  • Decide whether full works offline and for how long (graceOfflineDays)
    very important for “GitHub server downtime” or loss of internet: a user who paid for a licence cannot be “punished” by having the QA turned off.
    graceOfflineDays > 0 enables “offline grace” for full: if there is no contact, the QA stays active for a defined number of days
    graceOfflineDays = 0 means no such protection (full does not get a special full_offline mode)
  • Add custom metadata to the licence

 

What the toolbox does in the background?

From inside the QA, the toolbox reads the licence file from GitHub once every “x” hours (programmable, sensibly: 12 or 24 h). At the same time, it also writes the application state back to the server, which gives these benefits:

  • A persistent, updated “snapshot” of the computed licence state for each QA separately - i.e. mode, isActive, isDemo, reason + reasonText
  • Memory of dates and timestamps that cannot “reset” after a QA restart, reinstall, even HC total reset: firstInstallAt, trialExpiresAt, lastUpdateAt, lastServerDate, serverDate
    This ensures all user QA's will continue working as before when reinstall is necessary - even on clean hub
  • Stable demo: thanks to firstInstallAt and trialExpiresAt, the demo does not restart after reinstall/restart
  • Protection against system clock tampering. The time source is external and checked for monotonicity
  • Offline-grace continuity only for full licences: it keeps graceOfflineDays so that in offline mode it can go into full_offline or block after too long without contact
  • A diagnostic channel for the developer: you can see “why it doesn’t work” (reason) and “when it last worked” (lastUpdateAt, lastServerDate)
  • It is written cyclically (saved to GitHub after each computation), so it works like a “heartbeat”
  • It supports collision-free updates on GitHub (not used yet - until the server version)
  • No ability to move the program to another hub - it won’t run, even if HC3 encryption would allow it
  • All dates are “human-readable”, not epoch
  • The state JSON is pre-formatted for easier reading

 

The QA logic won’t start until the initial licence read succeeds. For later communication errors (no internet, GitHub down) there are different mechanisms - depending on the licence state the toolbox reacts differently: soft for full users (graceDays), hard stop for demo mode.

 

Using it inside QA (developer side)

Using it is simple and a bit similar to DNSfD: licence initialization is a single line, you provide three functions with fixed names that handle: continuing the QA after the first licence read, stopping due to licence, and updating licence status.

 

In the licence update function you have access to all licence data, which you can display in the QA UI, for example:

  • licence state
  • first installation date
  • whether “grace” mode is active
  • number of “offline grace” days
  • demo days used so far
  • demo days left
  • reason
  • etc.

 

How a developer sets it up?

  • On GitHub you create a repository for a client, e.g. JohnSmith. The repository must be PRIVATE!
  • In the client repo you create a folder: licences/
  • In licences/ you create a folder for the client hub: licences/<HC3_SERIAL>/
  • Into that folder you put the licence file for the QA: licences/<HC3_SERIAL>/<moduleId>_licence.json
    Example JSON below.
  • You do not need to create the state file: the QA creates/updates licences/<HC3_SERIAL>/<moduleId>_state.json automatically.
  • Token: you create a PAT that has access to this repo and write permissions.
    You do it here: https://github.com/settings/personal-access-tokens/new
  • In the QA you paste the token in the right place
  • In the QA you call LiceMan.init(self, { moduleId = "...", hc3Serial = "HC3-..." }) - moduleId must match the file name and the entry under modules
  • You add hooks __LicenseStatus, __LicenseReady, __LicenseStop to control logic/UI

 

This way the developer has all licences organized by clients, their hubs (if they have more than one), and finally by specific QuickApps. Everything is controlled through GitHub content.

 

Current status

As a standalone toolbox, LiceMan works and is tested as thoroughly as my patience allowed. The code is about 1350 lines. The toolbox version can handle many apps in a single client repository (many licence & status files). 

 

I’m now thinking about a server version. There would be one LiceMan server per hub, and unlimited client apps, each with a minimal toolbox for sending “check licence” requests. The main  problem is that single LiceMan server could carry many different GitHub tokens - one hub may have many apps from different developers, and one licence server. How to solve that?

The token is entered once into a QA variable - in plain text. After restart (mandatory after variable update), each “plain text” token is encrypted only once and written back into the variable. From that point on, LiceManS recognizes encryption, decrypts it also once and uses it for communication. Encryption is protected against hand manipulation of variable.

 

In practice, the user sends the LiceMan server QA to the vendor (with current licences in QA variables), the vendor adds their token as “plain text”, starts it once, and sends it back to the user, who will no longer see the token. Encryption has its limits because it had to be written in pure Lua, but I'm sure it’s strong enough. It costs me much of time... I won’t say which algorithm it is, but it has a pretty funny name. This is already done, it works great.

 

The rest of the work is frozen for now - lack of time for fun.

 

Usage test:

Please login or register to see this code.

 

Result:

Please login or register to see this attachment.

 

Licence file:

Please login or register to see this image.

/monthly_2026_01/image.png.7434a3af4a662920f1e8c28ac283fca8.png" />

 

Licence status file:

Please login or register to see this attachment.

  • Like 3
  • 4 weeks later...
Posted

Hi @Łukasz997,

 

Thank you for this interesting solution. I just wonder what happens if internet connection is lost or not available at the moment when QA needs to check license status?

  • Topic Author
  • Posted
    W dniu 2.01.2026 o 16:04, Łukasz997 napisał:

    Decide whether full works offline and for how long (graceOfflineDays)
    very important for “GitHub server downtime” or loss of internet: a user who paid for a licence cannot be “punished” by having the QA turned off.
    graceOfflineDays > 0 enables “offline grace” for full: if there is no contact, the QA stays active for a defined number of days
    graceOfflineDays = 0 means no such protection (full does not get a special full_offline mode)

     

    LiceMan handes such situation: in licence file you can set parameter "graceOfflineDays" to number of days. When no internet or github is down this parameter controls if licence can stay active and for how many days.

     

    During QuickApp startup, a proper connection is required (otherwise qa will not start). At that time, this parameter is read and stored. It is updated on each license check (so the license provider can change it freely). Therefore, it will also work - using the last stored value - if the connection to GitHub is lost for any reason.
    This ensures the integrity of the solution.

     

    In other words, if graceOfflineDays = 14, the user can continue to use the full license for another 14 days w/o github contact. After that, the QuickApp will be stopped and restarting it will not help as long as the license file cannot be read. This applies only to licenses of type "full".

    • Like 1
    • 2 months later...
    Posted

    Hi,

     

    I have made licensing model that do not need internet with activation key and 30 day trial period. Moreover, quick apps can be activated on its own or can be activated by the main Yubii UHAS quick app if installed and activated.

     

    So, only one activation key will be needed for Yubii UHAS installation with no restrictions on how many Yubii UHAS compatible quick apps are installed, or user can choose to only install needed quick app(s) to work as standalone and get activation key(s). Note that if same quick app needs to be installed several times e.g. to control certain lights, then only one activation key is needed.

     

    BTW the activation key is not stored anywhere in the quick app code, but it is generated on the quick app start up and the code that do that is encoded and written by me not following or using any available solutions on the internet. I'm willing to send one such quick app to anyone if interested to crack it for a nice reward. :-) 

     

    @Łukasz997 solution is still better than mine since it can support subscriptions.

    • Like 1
  • Topic Author
  • Posted

    Yes, a paid model probably can’t be implemented without some external service.

    Although I still feel this is not really a Fibaro scenario, even though “the whole world” basically runs on subscriptions now - with food included…

    On the other side - a licence API seems to me an answer for real need in Fibaro world. That's why I tried, succesfully.

    Also, my goal was to control app usage without any access to the user’s hub - I assumed resistance to a user–developer conflict scenario.

     

    How does resistance to the so-called “eternal demo” look on your side - through the only realistic scenario: reinstalling QA when needed? I know that QA data repository survives restart, but not reinstall. Manipulating the clock can probably be put in the fairy-tale scenario category.

    Posted
    3 hours ago, Łukasz997 said:

    How does resistance to the so-called “eternal demo” look on your side - through the only realistic scenario: reinstalling QA when needed? I know that QA data repository survives restart, but not reinstall. Manipulating the clock can probably be put in the fairy-tale scenario category.

     

    Hi @Łukasz997,

     

    there is no reasonable and easy way to manipulate gateway clock to extend demo period. Note that gateway is rebooted every time when time is changed in the settings. Easiest way is to delete and reinstall quick app, but I wonder who is ready to do that regularly every 30 days even for one quick app, not to mention more than one.

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Reply to this topic...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    ×
    ×
    • Create New...