Skip to content

Add diagnostic sensors and quality fixes#123

Open
italo-lombardi wants to merge 6 commits into
pink88:mainfrom
italo-lombardi:feat/sensors-and-quality-fixes
Open

Add diagnostic sensors and quality fixes#123
italo-lombardi wants to merge 6 commits into
pink88:mainfrom
italo-lombardi:feat/sensors-and-quality-fixes

Conversation

@italo-lombardi

Copy link
Copy Markdown

Hi! 👋

I'm a big fan of this integration — I have several Tuiss blinds at home and rely on it daily. Wanted to contribute back with some quality improvements and a richer set of sensors so I can get more visibility into what each blind is doing.

What's changed

New sensors (more visibility)

  • Connection Status — see if the blind is connected over Bluetooth
  • Lock Status — see if the blind is busy with an operation
  • Model — shows the blind model
  • Blind Speed — shows current speed setting (for supported models)
  • Last Battery Check — when the battery was last checked
  • Battery Check Interval — how often it's set to check
  • Traversal Speed — how fast the blind moves
  • Last Connection Error — last error seen, helpful for troubleshooting

Quality fixes

  • Speed setting now loads correctly at startup (previously had to be touched before it worked)
  • Battery check during a move can no longer get the blind stuck if something goes wrong with the check itself
  • Connection status only shows "connected" once the blind is fully ready
  • Lock sensor displays the right state (was inverted)
  • Cleaner repo: added .gitignore so cache files don't get committed

Under the hood

  • BLE command codes moved into named constants for readability
  • Switched to timezone-aware timestamps (matches HA conventions)
  • Fixed a typo: TRAVERALTRAVERSAL
  • Fixed a small bug where step-down sent the step-up command

Why these changes?

  • More sensors = better dashboards and automations
  • The fixes address things I hit personally while running this integration
  • Hopefully nothing breaks for existing users — defaults preserved everywhere

Feedback welcome 🙏

Thanks for building this integration!

@italo-lombardi

Copy link
Copy Markdown
Author

Pushed two follow-up commits:

fix: read model from blind object in options flow
Speed dropdown was hidden in the CONFIGURE dialog for some users (e.g. TS2600) because the options flow read model from the device registry, which can hold the BLE advertisement name (Tuiss Smartview) rather than the actual hardware model (TS2600). Now reads hub.blinds[0].model (live attribute) with device registry as fallback.

feat: add icon to model sensor
Added mdi:tag icon to the Model diagnostic sensor for visual consistency with the other sensors.

@italo-lombardi

Copy link
Copy Markdown
Author

@pink88

image

Thanks

@pink88

pink88 commented May 29, 2026

Copy link
Copy Markdown
Owner

Hello and thanks for submitting this! I'll take a look properly at the weekend.

I'm hesistant to add too many diagnostic entities that inflate the integration, without good reason. Are you able to explain your use case for them and how they have helped you out? Specifically Connection Status, Lock Status, Traversal Speed, Model and Last Connection Error?

@italo-lombardi

italo-lombardi commented May 29, 2026

Copy link
Copy Markdown
Author

Hey, thanks for the review! No rush at all, I know it's a big one, and there's another PR coming too, so take your time 😊

Zero impact on performance. The entities only update when the blind already fires a BLE event (no extra polling, no new connections, nothing added to the loop).

They're all diagnostic=True as well, so hidden from the default entity list (won't pollute anyone's dashboard).

Each one has a specific use case, but I'll give you my motivation about why I wanted to implement them:

  • Connection Status: helpful to understand why a blind isn't responding, e.g. dead battery or guard automations against sending commands to an offline blind
  • Lock Status: just to understand the current blind state
  • Traversal Speed: read current speed in automations, confirm speed changes took effect
  • Model: useful for bug reports because without it, I didn't even know that my blinds supported different speeds
  • Last Connection Error: gives users something actionable instead of just "unavailable"

And users can always disable any of them individually if they don't need them.

Let me know what you think. Thanks

@IainPHay

Copy link
Copy Markdown
Contributor

For what it's worth as a user I would like these included. Nice addition from my perspective 👍

@italo-lombardi italo-lombardi marked this pull request as draft May 30, 2026 13:30
- Add .gitignore excluding __pycache__, *.pyc, .venv/, .pytest_cache, .DS_Store, *.log
- Remove previously tracked __pycache__ directories and test_debug.log
Replace inline hex literals throughout hub.py with named constants in
const.py. Improves readability and protects against typos like the
limits_step_down bug that previously sent CMD_LIMITS_STEP_UP.

Also adds set_speed default case to prevent UnboundLocalError when
_blind_speed is unset or unrecognised.
New diagnostic sensors:
- ConnectionStatusSensor: Bluetooth connectivity state (binary)
- LockStatusSensor: blind busy/idle state (binary, LOCK device class)
- TuissModelSensor: blind hardware model
- TuissBlindSpeedSensor: current speed setting (gated by model support)
- TuissLastBatteryCheckSensor: timezone-aware timestamp of last battery check
- TuissBatteryCheckIntervalSensor: configured check interval
- TuissTraversalSpeedSensor: measured traversal speed (% per second)
- TuissLastConnectionErrorSensor: most recent connection error

Quality fixes:
- Seed _blind_speed/_battery_check_days/_restart_attempts from options at
  boot. update_listener only fires on option CHANGES, leaving values None
  until first edit, which makes set_speed() raise UnboundLocalError and
  diagnostic sensors read None.
- Read live model from blind object in options flow. Device registry's
  model field is set at registration and may hold the BLE advertisement
  name ("Tuiss Smartview") rather than hardware model ("TS2600"),
  hiding model-specific options like speed control.
- Switch _last_battery_check to dt_util.now() for timezone awareness.
- Call publish_updates() after option changes and lock state changes so
  diagnostic sensors reflect the new value without waiting for a poll.
The test was failing because str(exc.value) on the HomeAssistantError
raised by async_add_timer triggers HA's translation lookup, which
calls async_get_hass() and fails when invoked from a synchronous
test assertion outside a running event loop:

    HomeAssistantError: async_get_hass called from the wrong thread

The integration code is correct — the regression is in the test's
choice to stringify the exception. Switch the assertion to read the
translation_key attribute directly (HA stores translation kwargs as
plain attributes on the exception instance) so we never invoke
__str__ and never touch the translation machinery.

Full suite now: 83 passed, 0 failed.
- Drop unused UnitOfTime import in sensor.py
- Use CMD_TIMESTAMP_BASE constant in hub.send_timestamp() for consistency
  with the rest of the BLE-command refactor
@italo-lombardi italo-lombardi force-pushed the feat/sensors-and-quality-fixes branch from 4b8bd9f to 51b96c4 Compare May 30, 2026 13:58
@italo-lombardi italo-lombardi marked this pull request as ready for review May 30, 2026 14:03
Without persistence, every Home Assistant restart resets
_last_battery_check to None, forcing a battery read on the next
move regardless of the configured interval. This defeats the
purpose of the "battery check days" option.

TuissLastBatteryCheckSensor now inherits RestoreEntity and seeds
the blind's _last_battery_check from the recorder on entity add.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants