Skip to content

Repository files navigation

Slatly

Swift 6, xcodegen-driven watchOS + iOS app that drives Somfy ExteriorVenetianBlind devices over the Overkiz cloud API. Watch is standalone after first sign-in: it talks to Somfy directly over LTE / Wi-Fi without needing the iPhone nearby. Available in EN / CS / DE / FR / ES.

Requirements

  • macOS with Xcode 26
  • xcodegen (brew install xcodegen)
  • An Apple Developer account (for code signing; free account works for sideloading)
  • A Somfy / TaHoma / Cozytouch account with at least one ExteriorVenetianBlind device registered on a Connexoon, TaHoma or Cozytouch box

Build

xcodegen generate
open Zaluzky.xcodeproj

In project.yml, set DEVELOPMENT_TEAM to your own team identifier (currently GB4KCN39XD). Run the ZaluzkyWatch scheme for watch-only development on a paired simulator, or the Zaluzky scheme to build the iOS host + embedded watch app.

Direct install on real devices via xcrun devicectl:

# iOS host (also auto-syncs the watch app to your paired Apple Watch)
xcodebuild -project Zaluzky.xcodeproj -scheme Zaluzky \
    -destination 'generic/platform=iOS' -configuration Debug build
xcrun devicectl device install app --device <iphone-udid> \
    ~/Library/Developer/Xcode/DerivedData/Zaluzky-*/Build/Products/Debug-iphoneos/Zaluzky.app

# Watch directly (faster than waiting for iPhone-to-watch sync)
xcodebuild -project Zaluzky.xcodeproj -scheme ZaluzkyWatch \
    -destination 'generic/platform=watchOS' -configuration Debug build
xcrun devicectl device install app --device <watch-udid> \
    ~/Library/Developer/Xcode/DerivedData/Zaluzky-*/Build/Products/Debug-watchos/ZaluzkyWatch.app

Watch needs the screen awake for the tunnel to stay connected during install.

Caveat: watchOS-only distribution

Apple's 2025–2026 tooling refuses watchOS-only IPAs at upload (Unknown platform alias received: watchOS), so even though the watch app runs fully standalone, App Store / TestFlight distribution still requires the tiny iOS host target as a wrapper. See this Apple Developer Forum thread.

Architecture

App/                    watchOS SwiftUI app
iOS/                    iPhone companion (Dashboard / Rooms / Scenes / Settings)
Shared/                 cross-platform code
WidgetExtension/        watchOS launch complication
iOSWidgets/             iOS home-screen widget (deep-link tiles)
Packages/OverkizKit/    SwiftPM library wrapping the Somfy Europe OAuth2 + exec/apply flow

Key modules in Shared/:

  • OverkizClient (in OverkizKit) actor wrapping the Overkiz REST API with URLProtocol-mocked Swift Testing suite
  • CredentialsStore (iCloud Keychain, kSecAttrSynchronizable) for Somfy credentials sync between iPhone + Watch
  • BlindScene model + SceneStore (iCloud Keychain backed) + SceneSync (WatchConnectivity push for immediate cross-device delivery)
  • SceneRunner fans out a scene's per-device setpoints in parallel
  • BlindNameStore (UserDefaults, per-device rename override) + BlindThemeStore (per-device slat colour) + MyPositionStore (per-device "My" button override)
  • BlindsGraphic SwiftUI view, BlindTheme palette, ColorPaletteView

Sync paths:

  • Credentials → iCloud Keychain (kSecAttrSynchronizable), no extra entitlement needed
  • Scenes → iCloud Keychain mirror + WatchConnectivity updateApplicationContext for immediate push between paired iPhone and Watch
  • Per-device overrides (name, colour, My position) → local UserDefaults only

Internal naming

The Xcode project, target names (Zaluzky, ZaluzkyWatch, ZaluzkyWidgets, ZaluzkyiOSWidgets) and Bundle Identifiers (com.punkhive.zaluzky*) keep the original identifiers from when the app was first named "Žaluzky". They are intentionally left untouched: renaming them would invalidate iCloud Keychain entitlements (existing installs would lose their stored Somfy credentials).

Localization

UI strings live in per-target Localizable.xcstrings (Xcode 26 string catalog format). Source language is English; cs, de, es, fr translations included. Per-locale CFBundleDisplayName overrides are in InfoPlist.xcstrings (currently fixed to "Slatly" across all locales).

Pre-release TODO

Two capabilities live in Entitlements/*.entitlements but are commented out of project.yml because they require enabling in the Apple Developer portal first:

  • iCloud Key-Value Store (com.apple.developer.ubiquity-kvstore-identifier) as an additional cross-device scene-sync fallback alongside the current Keychain + WatchConnectivity paths
  • App Groups which would enable a richer iOS widget that runs scenes inline via App Intents

After enabling those in App Store Connect, uncomment the CODE_SIGN_ENTITLEMENTS lines in project.yml and rerun xcodegen generate.

About

Slatly — control Somfy ExteriorVenetianBlind devices straight from Apple Watch. Standalone watchOS app, no iPhone needed at runtime. Works with Connexoon, TaHoma and Cozytouch boxes.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages