Repository navigation
Releases: CX1-ApS/bricklogger
Release list
Bricklogger 0.3.1
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 initsets 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 theenvfile 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(copyingpostgresql.conffirst) and enable the
service, throughsudoin the terminal; it creates the database, the role
and the extension, aspostgreslocally or with an admin login asked for
on another host and never kept. The role's password is generated and
written to theenvfile. Nothing is ever deleted, and where it cannot act
it prints the remaining commands and goes on.init --dbruns the step
alone. init --non-interactivewrites the missing files and never replaces;
--plugin PACKAGEinstalls plugins, and withBRICKLOGGER_DB_PASSWORDset
(and optionallyBRICKLOGGER_DB_HOST,_PORT,_NAME,_USER) it writes
a workingtsdbdestination 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 bybricklogger plugins catalogue,
GET /v1/plugins/catalogue, the Plugins screen's new Catalogue part with an
Install per entry, and the MCP server'sbricklogger://catalogueand
list_catalogue. The MCP server still installs nothing. - Every installed plugin has an origin,
built-in,catalogueorcustom,
shown bybricklogger plugins, the Plugins screen andGET /v1/plugins.
Custom plugins are installed exactly as before. cataloguejoins the words no type may be named.
The compose file brings its database
- docker-compose.yml now has a
dbservice,timescale/timescaledb-ha:pg18
with a volume of its own, and every service, the web interface and the MCP
server included, starts withdocker 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. .envbeside the compose file must setPOSTGRES_PASSWORD(the database's
admin) andBRICKLOGGER_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 inBRICKLOGGER_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}andPOST /v1/daemon/reloadanswer202with a
configorreloadjob instead of answering when they are done. Their
steps arevalidating,writing, andstopping <instance>and
starting <instance>; a configuration that does not hold fails the job
with the422problem and itserrors. They queue with model uploads and
activations, one job at a time.GET /v1/jobslists 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
withstop_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 with202, throughGET /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.4when it should go on working
with 0.2 — since one bound to<0.3holdsupdate coreat 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 statusnames 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 thedbservice 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
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 statusanddestinations 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 tobricklogger>=0.2,<0.3keep working
unchanged; a plugin that uses the addition requiresbricklogger>=0.2.5,<0.3.
Bricklogger 0.2.4
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, andbricklogger statusshows
both on all three lines, however each process was started.
For plugin authors
- The SDK gains, as an addition:
stores_modelon DestinationDeclaration
(False by default), Destination.timeseries_ids() and
Destination.write_model(), and ModelDocument. Plugins bound to
bricklogger>=0.2,<0.3keep working unchanged; a plugin that uses the
addition requiresbricklogger>=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, oruv tool upgrade bricklogger; in a
container, ghcr.io/cx1-aps/bricklogger:0.2.4.
Bricklogger 0.2.3
Bricklogger 0.2.3
Installing
- Bricklogger is installed per login with uv:
uv tool install bricklogger,
thenbricklogger 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;initoffers it as its last step.
services uninstallandservices statuscomplete the group.- Plugins are kept in uv's record of the tool environment, so
bricklogger updateanduv tool upgrade brickloggerkeep them. Do not run
uv tool install brickloggeragain 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
withdata_dirin 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 updaterewrites only the units that are set up.
Bricklogger 0.2.2
Bricklogger 0.2.2
Upgrading
bricklogger updateupgrades Bricklogger and its plugins from PyPI:
update statusshows what there is,update coreupgrades Bricklogger as
far as the installed plugins allow,update <type>one plugin, and
update alleverything 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 alltakes over.- The daemon looks for newer releases once a day and names them in
status
and the daily summary mail.updates: {check: false}indaemon.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 anibosinstance 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,coreandstatuscannot name a plugin type.- The systemd units are written from templates in the package, by the
install script and byupdatealike.
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
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 anedge
tag. - The plugin SDK grows:
bricklogger.sdk.bacnet(BACnet's object types and
the map from its engineering units to QUDT),expandandUnknownPrefix
for prefixed names, andDURATION_HELP,parse_durationand
format_duration. A plugin built for 0.1 pinsbricklogger<0.2and 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 addandplugins removeno longer miss a plugin installed within
the same instant as their previous look at the environment.