Skip to content

Releases: CX1-ApS/bricklogger

Bricklogger 0.3.1

Choose a tag to compare

@github-actions github-actions released this 24 Oct 09:35

Bricklogger 0.3.1

0.3.0 was tagged but never released: its release run found the fault fixed
below. These are its changes, with that fix.

A one-stop init

  • bricklogger init sets a machine up in one go and can be run again: the
    directories, the plugins, the sources and destinations, the database, the
    remaining files and the services, in that order. A file that exists is
    asked about, replace or skip, skip by default; a replaced file is copied
    first to <file>.<time>.bak, and the env file is only ever added to. On a
    machine where the daemon runs, it ends by asking whether to restart it.
  • Its plugin step shows the catalogue, installs the chosen plugins and any
    other package typed in, and goes on with the types installed when an
    install fails.
  • It prepares TimescaleDB: on localhost, on Debian and Ubuntu, it offers to
    install PostgreSQL 18 with TimescaleDB from Timescale's repository, run
    timescaledb-tune (copying postgresql.conf first) and enable the
    service, through sudo in the terminal; it creates the database, the role
    and the extension, as postgres locally or with an admin login asked for
    on another host and never kept. The role's password is generated and
    written to the env file. Nothing is ever deleted, and where it cannot act
    it prints the remaining commands and goes on. init --db runs the step
    alone.
  • init --non-interactive writes the missing files and never replaces;
    --plugin PACKAGE installs plugins, and with BRICKLOGGER_DB_PASSWORD set
    (and optionally BRICKLOGGER_DB_HOST, _PORT, _NAME, _USER) it writes
    a working tsdb destination instead of the example.

The catalogue

  • Bricklogger ships a catalogue of approved plugins, kept in
    github.com/CX1-ApS/bricklogger-marketplace, where a plugin is proposed with
    a pull request. It is shown by bricklogger plugins catalogue,
    GET /v1/plugins/catalogue, the Plugins screen's new Catalogue part with an
    Install per entry, and the MCP server's bricklogger://catalogue and
    list_catalogue. The MCP server still installs nothing.
  • Every installed plugin has an origin, built-in, catalogue or custom,
    shown by bricklogger plugins, the Plugins screen and GET /v1/plugins.
    Custom plugins are installed exactly as before.
  • catalogue joins the words no type may be named.

The compose file brings its database

  • docker-compose.yml now has a db service, timescale/timescaledb-ha:pg18
    with a volume of its own, and every service, the web interface and the MCP
    server included, starts with docker compose up -d; there are no profiles.
    All four run on the host's network, and the database listens on
    127.0.0.1 alone and asks for a password there.
  • .env beside the compose file must set POSTGRES_PASSWORD (the database's
    admin) and BRICKLOGGER_DB_PASSWORD (the role Bricklogger logs in as). At
    its first start the database creates the role, its database and the
    extension, and the daemon container writes a working TimescaleDB
    destination and installs the packages in BRICKLOGGER_PLUGINS, once each.
  • The TimescaleDB destination updates the extension at start when the server
    offers a newer one than the database has, and logs a warning with the
    command where its role may not.

Configuration writes and reload run as jobs

  • PUT /v1/config/{file} and POST /v1/daemon/reload answer 202 with a
    config or reload job instead of answering when they are done. Their
    steps are validating, writing, and stopping <instance> and
    starting <instance>; a configuration that does not hold fails the job
    with the 422 problem and its errors. They queue with model uploads and
    activations, one job at a time.
  • GET /v1/jobs lists the jobs, newest first, with ?state=. The Model,
    Configuration and Daemon screens show a queued or running job again when
    they open, and every web button that waits says so, with the seconds
    counting.
  • The CLI follows the job and shows its steps; the MCP write tools wait for
    it and answer as before. A stop finishes the configuration jobs it has
    accepted.

Speed and reliability

  • Validation parses each SPARQL query once: a 9.3k-triple model validated in
    8.7 s instead of 37.5 s.
  • A re-plan reads the points' locations with one query per kind of anchor: on
    a model of 6,000 entities, about a second instead of minutes, which every
    activation and reload waited for.
  • A source's status reports never wait for the daemon, so a source reporting
    during an activation or a reload no longer blocks it and gets abandoned
    with stop_timeout. That warning is withdrawn once the abandoned thread
    ends.

Fixes

  • What an activation inferred could differ between two starts of the daemon:
    Brick's SHACL rules were applied once, in an order that varied, so a rule
    that needs another's result sometimes ran too early. An entity typed
    brick:AHU, say, got the tags of brick:Air_Handling_Unit only in some runs.
    The rules are now applied until a pass adds nothing. Validation is
    unchanged; an activation takes about 40 % longer. 0.2 has the same fault.

Breaking changes

  • An API client that writes the configuration or reloads must follow the job
    it gets with 202, through GET /v1/jobs/{id}, as for a model upload. The
    CLI, the web interface and the MCP server do this already.

For plugin authors

  • The SDK contract is unchanged. A plugin is released again for 0.3 with
    bricklogger>=0.3,<0.4 — or >=0.2.5,<0.4 when it should go on working
    with 0.2 — since one bound to <0.3 holds update core at 0.2 and is left
    out when a container's image moves to 0.3.

Upgrading

  • bricklogger update all, once every installed plugin has a release that
    allows 0.3; update status names any plugin that holds it back.
  • In a container, compare your compose file with the new one: name
    ghcr.io/cx1-aps/bricklogger:0.3.1, and either take the db service and set
    both passwords in .env, or leave it out when the logger writes to a
    database of its own. The web interface and the MCP server now start without
    --profile.

Bricklogger 0.2.5

Choose a tag to compare

@github-actions github-actions released this 21 Oct 13:31

Bricklogger 0.2.5

Instance health

  • Every source and destination now has a health: ok, degraded or failed. It
    is read off the warnings: every warning code has a severity, and an
    instance's health is the worst severity among the warnings standing on the
    instance, its devices and its points. Its reason is that warning's message,
    with the time it began and how many others stand. A source can thereby be
    running and degraded at once, such as a cloud that refuses its token.
  • The daemon judges much of this itself: a failed instance, a device the
    source reports unreachable (the new warning device_unreachable), a device
    that skips poll rounds, and a stale point.
  • A point is stale (the new warning stale) when its newest observation, a
    value or a null, is older than three times its rule's interval. A source
    instance can set its own limit with stale_after in sources.yaml, a key that
    belongs to the daemon, and a plugin can declare a default for sources whose
    data arrives in bursts.
  • Overall health is degraded while any instance is not ok. /health answers 503
    only while an instance is failed, which includes a spool that drops data, so
    a container is not marked unhealthy over one silent controller.
  • Health is shown on the instance lines of bricklogger status, in
    sources status and destinations status, in a new table of instances on
    the web interface's overview and on its instance screens, in the daily
    summary mail, and through the MCP server. The warning list gains each
    code's severity.

Reliability

  • A source or destination that kept failing for about 17 hours stopped being
    restarted: the restart delay overflowed after 1,024 attempts, the
    supervising thread died, and status went on saying running. The delay now
    stays capped at a minute, and the BACnet/IP source's search backoff likewise.
  • The supervisor catches anything that escapes its loop, and a watchdog
    restarts an instance whose thread has ended without a failure being seen,
    marking it failed with instance_failed.
  • The backoff starts over once an instance has run for a minute without
    failing; the restart count in status keeps the total. Source status gives
    the next retry.
  • Validation and inference of an uploaded model run in a child process, so
    the API keeps answering and collection keeps going while a large model is
    worked on.
  • The BACnet/IP source refreshes a device's last success with every round
    that gets an answer.

For plugin authors

  • The SDK gains, as an addition: WarningCode with its Severity, declared in
    warning_codes on SourceDeclaration and DestinationDeclaration, and
    stale_after on SourceDeclaration. A code raised without being declared
    counts as degraded. Plugins bound to bricklogger>=0.2,<0.3 keep working
    unchanged; a plugin that uses the addition requires bricklogger>=0.2.5,<0.3.

Bricklogger 0.2.4

Choose a tag to compare

@github-actions github-actions released this 08 Oct 17:32

Bricklogger 0.2.4

The model beside the data

  • A destination can now store the Brick model beside the data, so that
    someone with access to the database alone can use the model to find the
    data: select points with SPARQL, then read their time series with SQL. It
    stores every version that has been active, with its activation times, and
    every point it holds data for carries Brick's ref:TimeseriesReference, with
    the destination's own key as ref:hasTimeseriesId and no ref:storedAt.
  • TimescaleDB does this. The new tables models and model_activations hold the
    versions as Turtle, with points.point_id as the id. The schema moves to
    version 2 when the destination first starts; existing tables and data are
    left as they are.
  • Bricklogger keeps the same references in its working graph, one named
    graph per destination, urn:bricklogger:timeseries:, reachable on
    the SPARQL endpoint. The rules, the plan, the model explorer and the
    sources do not see them. bricklogger model export --timeseries [--destination NAME] and ?timeseries= on GET /v1/models/{version} add
    them to an export of the active version.
  • Status, the CLI and the web interface show per destination whether it
    stores the model and which version it last wrote.

Status

  • The daemon, the web interface and the MCP server answer GET /health/live
    with their own process ID and start time, and bricklogger status shows
    both on all three lines, however each process was started.

For plugin authors

  • The SDK gains, as an addition: stores_model on DestinationDeclaration
    (False by default), Destination.timeseries_ids() and
    Destination.write_model(), and ModelDocument. Plugins bound to
    bricklogger>=0.2,<0.3 keep working unchanged; a plugin that uses the
    addition requires bricklogger>=0.2.4,<0.3.
  • From this release, an addition to the SDK contract that plugins do not need
    raises the patch version; a change that breaks plugins still raises the
    minor version.

Upgrading

  • bricklogger update core, or uv tool upgrade bricklogger; in a
    container, ghcr.io/cx1-aps/bricklogger:0.2.4.

Bricklogger 0.2.3

Choose a tag to compare

@github-actions github-actions released this 07 Oct 11:45

Bricklogger 0.2.3

Installing

  • Bricklogger is installed per login with uv: uv tool install bricklogger,
    then bricklogger init. uv brings a Python that fits, and everything stays
    in that login's home directory. The install script is gone, and so is
    installing as root.
  • bricklogger services install [--web] [--mcp] runs the daemon, and the
    web interface and the MCP server when asked, as systemd --user services
    that start at boot; init offers it as its last step.
    services uninstall and services status complete the group.
  • Plugins are kept in uv's record of the tool environment, so
    bricklogger update and uv tool upgrade bricklogger keep them. Do not run
    uv tool install bricklogger again over an installation with plugins: it
    uninstalls every plugin not named with --with.

Moving from an installation made with the install script

  • Remove it with the script it came from, keeping the configuration and the
    data:
    curl -fsSL https://github.com/CX1-ApS/bricklogger/releases/download/v0.2.2/install.sh | sudo sh -s -- --uninstall
    (without sudo for an installation in a home directory). Then
    uv tool install bricklogger, add the plugins again with
    bricklogger plugins add, copy the configuration and the data from
    /etc/bricklogger and /var/lib/bricklogger to ~/.config/bricklogger and
    ~/.local/share/bricklogger if they lay there — with the env file, and
    with data_dir in daemon.yaml changed to the new place — and run
    bricklogger services install.

Changed

  • /etc/bricklogger is no longer looked for; the configuration is in
    ~/.config/bricklogger unless --config-dir or BRICKLOGGER_CONFIG_DIR says
    otherwise. The container is unchanged.
  • The unit templates are user units: no User= line and no network target.
    bricklogger update rewrites only the units that are set up.

Bricklogger 0.2.2

Choose a tag to compare

@github-actions github-actions released this 06 Oct 13:21

Bricklogger 0.2.2

Upgrading

  • bricklogger update upgrades Bricklogger and its plugins from PyPI:
    update status shows what there is, update core upgrades Bricklogger as
    far as the installed plugins allow, update <type> one plugin, and
    update all everything together. The new version checks the configuration
    before anything is restarted, the previous versions are put back when it
    does not hold, the systemd units are brought up to date, and the units that
    run are restarted. Run the install script once to get 0.2.2; from there on
    sudo bricklogger update all takes over.
  • The daemon looks for newer releases once a day and names them in status
    and the daily summary mail. updates: {check: false} in daemon.yaml
    turns the look off on a network with no way out.
  • The web interface's Plugins screen shows the newest releases, with an
    Update per plugin and a Check now.

Fixed

  • A configured type whose plugin is not installed no longer stops the
    daemon. Its instances are failed, with a warning that names
    bricklogger plugins add, and everything else runs — which is what 0.2.0
    promised for an ibos instance after the upgrade. A change written through
    the CLI, the web interface, the API or the MCP server still refuses a type
    that is not installed, so a misspelling is caught where it is typed.
  • Running the install script over an installation tells what to restart,
    instead of repeating the guidance for a first install.

Changed

  • all, core and status cannot name a plugin type.
  • The systemd units are written from templates in the package, by the
    install script and by update alike.

0.2.1 was tagged but never published: its release stopped at a type check
of the tests. 0.2.2 carries everything listed here.

Bricklogger 0.2.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 07:37

The first public release of Bricklogger.

Install with

curl -fsSL https://github.com/CX1-ApS/bricklogger/releases/latest/download/install.sh | sudo sh

or run the image ghcr.io/cx1-aps/bricklogger:0.2.0. The documentation is at
https://cx1-aps.github.io/bricklogger/.

Upgrading from 0.1 with an iBOS source

The iBOS source is no longer built in: it is a plugin of its own,
bricklogger-ibos. While sources.yaml names type: ibos and the plugin is not
installed, the daemon does not start: it reports the unknown source type
'ibos'. Add the plugin right after the upgrade and start the daemon again:

bricklogger plugins add bricklogger-ibos
sudo systemctl restart bricklogger

The configuration, the type name, the vocabulary and the collected history are
unchanged, and collection resumes from the latest observation of every point;
the stretch the daemon was down is fetched from the cloud.

Changes

  • Bricklogger is published on PyPI, and the install script is a release
    asset; the image is built for released versions only, without an edge
    tag.
  • The plugin SDK grows: bricklogger.sdk.bacnet (BACnet's object types and
    the map from its engineering units to QUDT), expand and UnknownPrefix
    for prefixed names, and DURATION_HELP, parse_duration and
    format_duration. A plugin built for 0.1 pins bricklogger<0.2 and is
    released again for 0.2.
  • The model explorer keeps systems, collections and zones out of the tree:
    they stand in a band of their own under class headings, and a grouping opens
    to what it gathers. bricklogger model tree --root <grouping> does the same.

Fixes

  • A destination whose write fails — after the database restarted, say — is
    stopped and started again before the write is retried, so it reconnects
    instead of retrying on a dead connection forever.
  • plugins add and plugins remove no longer miss a plugin installed within
    the same instant as their previous look at the environment.