Commit Graph
6 Commits
Author SHA1 Message Date
Marc Billow 027768f7d7 fix: lower DTLS context security level to allow SHA-1 signed cert chain
The fullchain.pem we send as our client cert contains the AC14K_M
intermediate CA, which is SHA-1 signed. Samsung's OCF Root CA (trust
anchor) is also SHA-1 self-signed. OpenSSL 3.x SECLEVEL=2 rejects
SHA-1 in any certificate it touches — including our own outbound chain —
raising SSL_R_CA_MD_TOO_WEAK before the verify callback is reached.

Fix: call SSL_CTX_set_security_level(ctx, 1) before loading any certs.
Tries pyOpenSSL >= 24.0 ctx.set_security_level(), falls back to cffi,
then ctypes as a last resort. SECLEVEL=1 (80-bit minimum) allows SHA-1
while still enforcing meaningful key-strength constraints.
2026-06-30 16:34:39 -05:00
Marc Billow df4eeb0de5 fix: handle X509_V_ERR_CA_MD_TOO_WEAK in DTLS verify callback
@SECLEVEL=1 in the cipher string does not reliably lower the security
level for DTLS_METHOD contexts across all pyOpenSSL/OpenSSL builds.

Instead, explicitly allow error 66 (X509_V_ERR_CA_MD_TOO_WEAK) in the
verify callback. This is the error OpenSSL emits when a CA certificate
uses SHA-1 — which Samsung's OCF Root CA does. All other verification
errors (chain trust, expiry, key usage, revocation) are still enforced.
2026-06-30 16:34:39 -05:00
Marc Billow 58ecbaab46 fix: set SECLEVEL=1 to allow SHA-1 signed Samsung OCF Root CA
OpenSSL 3.x defaults to SECLEVEL=2, which rejects SHA-1 digests in the
certificate chain. Samsung's OCF Root CA is SHA-1 signed, so peer
verification failed with "ca md too weak" on every connect attempt.

SECLEVEL=1 (80-bit minimum) allows SHA-1 in the CA chain while still
enforcing meaningful key-strength and cipher constraints. Not going back
to SECLEVEL=0 which removes all restrictions.
2026-06-30 16:34:39 -05:00
Marc Billow b372bca377 feat: add translations and improve config flow UX
- translations/en.json: runtime translation file HA loads (strings.json
  is tooling-only); includes data_description hints for host, cert, key

- config_flow.py: cert_pem and key_pem rendered as multiline text areas
  via TextSelector so users can paste full PEM blocks; host stays single-line

- strings.json: expanded error messages and data_description to match

- entity.py: entities with name=None (pattern-cap doors, temps, icemmakers)
  now derive a human-readable title from their state key instead of
  displaying blank ("door_cooler_open1" → "Door Cooler Open 1")
2026-06-30 16:34:39 -05:00
Marc Billow cc2c1e5a1f refactor: move samsung_appliance/ into custom_components/localthings/ocf/
Makes the integration fully self-contained for HACS distribution.
Users installing via HACS get everything in one directory; no external
samsung_appliance package needed.

All component imports updated to relative (.ocf.*); all test imports
updated to custom_components.localthings.ocf.*. ocf_root_ca.pem moves
with the package and resolves correctly via Path(__file__).parent.
2026-06-30 16:34:20 -05:00
Marc Billow f7b58f00ee feat: replace MQTT bridge with localthings HA custom component
Convert from MQTT bridge architecture to a proper Home Assistant
integration (custom_components/localthings/):

- Config flow: IP-only entry, probes ports [49154,49155], cert/key
  reused from first device on subsequent adds
- Coordinator: DataUpdateCoordinator wrapping blocking DTLS session
  via async_add_executor_job; discovery on first poll; dynamic 5s/30s
  interval based on active_when
- Entity platforms: sensor, binary_sensor, switch, number, select
- Library cleanup: delete bridge.py, main.py, config.py, logger.py,
  keepalive.py, poll_scheduler.py, sensors.py, state_cache.py
- adapter.py stripped to flatten(), is_active(), _key()
- _parse_device0_batch moved to samsung_appliance/batch.py
2026-06-30 16:34:06 -05:00