v2.0.0
- Reworked concurrency: all IoMapping (DBus) access is now funnelled through a
  single owner thread (IoWorker) via a bounded command queue. Reads, writes,
  toggle and timed operations, plus input polling, all run on that one thread.
  This removes the previous design where the main loop (io_service.run()), a
  polling thread, the MQTT network thread and timer threads used the same DBus
  connection concurrently - the condition that could deadlock/hang the whole
  app when a digital input cycled quickly.
- Removed io_service.run(mayBlock=True) from the main loop and the relay
  notification callback; relay state changes are now detected by polling on the
  IoWorker thread. The main thread only waits for shutdown.
- Added StallWatchdog: if the IoWorker stops making progress for
  application_stall_timeout seconds the process exits (os._exit) so barix-wd
  restarts it. No hardware /dev/watchdog / reboot is used.
- Added digital-input debounce (input_debounce_interval, default 50 ms) so
  switch-contact bounce no longer floods the broker with state changes.
- Bounded the paho outbound queue (mqtt_max_queued_messages /
  mqtt_max_inflight_messages) to prevent unbounded memory growth when the
  broker is slow or unreachable.
- Performance (validated with a UX8 extension, whose USB-attached I/O is
  slower): monitored inputs/relays are now polled with a single batched
  read_values() call (~13 ms vs ~145 ms for 33 addresses), the IoWorker drains
  a batch of queued commands per cycle so reads/writes are not starved by
  polling, and the IO service is pumped non-blocking each cycle. Sustained
  throughput improved from a few ops/s to ~100+ ops/s; under overload the
  command queue stays bounded and drains within seconds.
- Added optional publish_initial_state: when enabled, current input/relay
  states are (re)published on each broker connection.
- Change monitoring reduced to digital inputs and relays (per spec). Counters,
  analog inputs, temperatures and system registers (e.g. uptime) are no longer
  auto-published as "changes"; they remain available via on-demand reads.
- Timed relay operations no longer use threading.Timer; expiries are handled on
  the IoWorker thread. A manual write/toggle cancels a running timer for that
  address. Graceful shutdown resets outputs that still have a running timer.
- Fixed publish() qos/retain handling (explicit None checks) so QoS 0 and
  retain=False can be used. Removed duplicate "MQTT disconnected" log line.

Previous:
- Implemented full IO Addresses control with "special" functions for relays/outputs/virtual IOs: timed and toggle operations
- Only compatible with Flexa Firmware v2.3.1
