View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
View antoinevalentinHA's full-sized avatar
  • Bordeaux, FRANCE

Block or report antoinevalentinHA

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse

antoinevalentinHA

I run one Home Assistant system in a family home, and I govern it like software: a written contract before any code, one decision authority per domain, and CI that blocks whatever contradicts the contract. I am not a developer. I use AI as an execution force under constraints I set, and I make the calls.

Almost everything on this account exists because that system needs it. Start with Arsenal.


Arsenal — the system

Arsenal is an in-production Home Assistant configuration for a family home. It covers heating, domestic hot water, air conditioning, ventilation, irrigation, energy, security, presence, indoor and outdoor measurement, dashboards and infrastructure observability.

46 contractual domains · ~1,800 YAML files · ~3,900 entities.

Three rules hold it together:

  • The contract comes first. Every domain is written down before it is built. If the code contradicts the contract, the code is wrong — not the contract.
  • Decision, execution and display are separate. One decision authority per domain produces a readable state, bounded executors apply it, dashboards observe it. Never the reverse.
  • CI is a boundary, not an oracle. Red is forbidden. Green only means a change is admissible to human judgement.

The same discipline governs the AI assistance: no invented entity IDs, no casual renames, whole files in their real tree, and contracts that bound what a proposal is allowed to claim. Fast execution is not allowed to turn into silent drift.

The documentation is in French; the repository README is an English entry point. Arsenal is not a configuration to copy — its entities and topology belong to one house. What travels is the method.


Written for this system

RepositoryWhat it is
ha-state-archiveArchival pipeline for the configuration: versioned states, integrity audits, release-oriented diffs, retention. It runs on my NAS and is published as a versioned container image on GHCR, with a CI test suite and automated publishing.
ha-archive-searchSearch, inspection and export over those archives: corpus engine, CLI, small web app, Markdown export. Same packaging — versioned GHCR image, CI tests. When a domain behaves oddly, the answer is usually in here.
boilerackA transactional MQTT bridge over an existing vcontrold, for Viessmann boilers on an Optolink link. Commands are identified, expirable and confirmed by reading the boiler back — never assumed to have succeeded. Same ground as Arsenal's boiler contracts, which specify acknowledged transactional commands. Under construction: nothing is released, and none of it has been exercised against a real boiler or broker.
ha-termux-toolsBash scripts that mirror the configuration onto an Android phone, so it can be searched and inspected from Termux.

Derived work — the forks, and what is mine in them

Arsenal runs on these. They are pinned, patched and kept in working order, and fix branches are kept ready for upstream.

ForkUpstreamWhat is upstream, and what is mine
rainbird-esp32-elegoomaillme/rainbird-esp32 — Neil SmithThe upstream holds the original design and the vast majority of the code: SIP-over-BLE protocol, MQTT discovery, OTA. My fork retargets it at the ELEGOO ESP32 (WROOM-32) board — an esp32dev PlatformIO environment, light-sleep power management that compiles for both boards, and a two-station configuration. This is the firmware in service on my irrigation bridge. rainbird-esp32 is my copy of the upstream XIAO ESP32-C3 variant it grew out of.
ha_airstagedanielkaldheim/ha_airstageFujitsu air conditioning. Served from the arsenal-stable branch (manifest 1.7.1). Its Python library, pyairstage, is upstream and unforked: the manifest requires at least 2.4.1 and stops below 3.0.
hassio-bluetti-bt · bluetti-bt-libPatrick762Bluetti power stations. Arsenal vendors integration 0.2.2, which installs the library from an exact versioned wheel release of my fork (v1.1.0). Stability comes from that version pin, not from a branch.
ha-linkybokub/ha-linkyLinky smart meter, as a Supervisor add-on. Carries a fix branch anticipating a Home Assistant recorder statistics change.
atmofrancesebcaps/atmofranceAir quality for French cities. This one has moved past a pinned fork into a maintained distribution: its own releases (2.1.10 is what Arsenal runs), a local codeowner, documentation and issue tracker pointing here, and branches that track upstream.

audi_connect_ha is the exception: I contribute to the integration instead of running my own build. The fork exists to carry fix/* branches toward upstream — transient 403/502 handling, auth guards, French translation — while my installation stays on the official release (2.3.1).


Patterns pulled out of the system

Four small repositories, each isolating a single pattern from the running configuration:

They are self-contained, and they still answer questions people ask.


Outside Home Assistant

rallye-trip-meter-android — a rally trip meter for Android (Kotlin, Jetpack Compose): GPS partial distance corrected to the metre, total distance, instant speed, manual calibration. Different domain, same method: a functional contract before the code, and the package is fr.arsenal.rallyetripmeter. Tagged v0.3.0-preview — usable and validated on device, final field validation still ahead.

studio — a fork of marian-m12l/studio (Java), which creates and transfers story packs to and from the Lunii story teller device. I maintain the fork for robustness in real use: device detection that waits for the mount instead of timing out, a pack index that refuses a malformed .pi rather than fabricating a UUID, a free-space precheck that counts what the transfer actually adds, and an index installed by atomic move instead of written in place. CI runs the Java suite on Linux and Windows plus the JavaScript suite. Work in progress — the repository documents which write-path failure modes are still open.


Bordeaux, France.

Pinned Loading

  1. arsenalarsenalPublic

    Home Assistant as a governed system

    YAML 1 1

  2. rallye-trip-meter-androidrallye-trip-meter-androidPublic

    Android rally trip meter with GPS distance tracking, stage distance, total distance and manual calibration.

    Kotlin

  3. studiostudioPublic

    Forked from marian-m12l/studio

    STUdio - Story Teller Unleashed

    Java

  4. boilerackboilerackPublic

    Pont MQTT transactionnel pour chaudieres Viessmann via vcontrold

    Python