Skip to content

seosieve/VestellaSet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

227 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Vestella Set – Beacon Configuration Automation

Automated Minew iBeacon Configuration via OCR and QR Scanning




About


🧩 Simplify and automate multiple beacons to accelerate your workflow.

An iOS app that automates beacon writing using Vision and CoreBluetooth

  • Project Duration: 2025.08 - 2025.10 (v1.0.0)
  • Project Tech Stack: SwiftUI 5.0 + TCA(The Composable Architecture) 1.22.3
  • Hardware & Perception APIs: CoreBluetooth, Vision, AVFoundation

OverView


Time Comparison Simulation

  • Existing Problem: Setting up 100–200 beacons with the current manufacturer app is time-consuming, labor-intensive.
  • Approach: Created an automation app using OCR/QR vision technologies and a customized MinewBeacon SDK.
  • Business Impact: Achieved a time reduction from 1m 30s to 15s (β‰ˆ83% faster) βœ…

Architecture

Architecture

Hardware-Integrated TCA Architecture

  • Existing Problem: Managing multiple hardware states (Bluetooth, Camera, Vision) simultaneously leads to race conditions and inconsistent UI updates.
  • Approach: Implemented TCA's unidirectional data flow with centralized state management for all hardware interactions.
  • Technical Impact: Eliminated state synchronization issues and achieved 100% predictable hardware state transitions βœ…

Trouble Shooting

Trouble Shooting

Obj-C Delegate β†’ AsyncStream β†’ TCA Action Bridging

  • Existing Problem: MinewSDK's Obj-C delegate callbacks could not be directly received within TCA's Swift Concurrency-based unidirectional data flow.
  • Approach: Bridged hardware events to TCA Actions via a 3-step conversion (Delegate β†’ Closure β†’ AsyncStream), monitoring 3 streams concurrently with async let.
  • Technical Impact: SDK callbacks operate as first-class citizens within TCA's unidirectional flow, managing beacon discovery, detection, and connection in a single Reducer βœ…

Step 1. Delegate β†’ Closure (BeaconManager)

BeaconManager.swift

  var onBeaconNotFound: (() -> Void)?
  var onBeaconFound: ((MinewBeacon) -> Void)?
  var onBeaconConnect: ((ConnectionState) -> Void)?

  // MinewBeaconManagerDelegate
  func minewBeaconManager(_ manager: MinewBeaconManager!, didRangeBeacons beacons: [MinewBeacon]!) {
      let foundBeacon = beacons.first { $0.mac == identifier }
      foundBeacon.map { onBeaconFound?($0) } ?? onBeaconNotFound?()
  }

MinewBeaconManagerDelegate.swift

  func minewBeaconManager(_ manager: MinewBeaconManager!, didRangeBeacons beacons: [MinewBeacon]!) {
      let foundBeacon = beacons.first { $0.mac == identifier }
      foundBeacon.map { onBeaconFound?($0) } ?? onBeaconNotFound?()
  }

Step 2. Closure β†’ AsyncStream (BeaconClient)

BeaconClient.swift

  var onBeaconNotFound: AsyncStream<Void>
  var onBeaconFound: AsyncStream<MinewBeacon>
  var onBeaconConnect: AsyncStream<ConnectionState>

  self.onBeaconFound = AsyncStream { continuation in
      manager.onBeaconFound = { continuation.yield($0) }
  }

Step 3. AsyncStream β†’ TCA Action (Reducer)

BeaconEditorFeature.swift

  return .run { send in
      async let notFound: Void = {
          for await _ in client.onBeaconNotFound { await send(.increaseTimeoutCounter) }
      }()
      async let found: Void = {
          for await beacon in client.onBeaconFound { await send(.updateBeacon(beacon)) }
      }()
      async let connect: Void = {
          for await state in client.onBeaconConnect { await send(.updateConnectionState(state)) }
      }()
      _ = await (notFound, found, connect)
  }

Credits

Β© Minew Technology Co., Ltd. See MinewSDK for details.

Minew

License

Apache 2.0 Β© VestellaLab, Inc. See LICENSE for details.

VestellaLab

About

Make Custom Beacon Setting with Minew Beacon

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors