CocoaPods trunk is moving to be read-only. Read more on the blog, there are 8 months to go.

TJHanaSDK 1.0.0

TJHanaSDK 1.0.0

Maintained by tjlabs-dev.



TJHanaSDK 1.0.0

  • By
  • tjlabs-dev

TJHanaSDK

Version 1.0.0

CI Status Version License Platform

TJHanaSDK is an iOS SDK for TJLabs Hana indoor services.

It provides authentication, Warp-based ward interaction UI, Venus-based indoor result delivery, and Jupiter-based indoor positioning and navigation features in a single SDK.


✨ Features

  • 🔐 SDK authentication
  • 🫧 Warp ward detection and click interaction
  • 📍 Venus indoor result delivery
  • 🧭 Jupiter indoor positioning and navigation
  • 🔄 Real-time delegate-based event handling

📦 Requirements

  • iOS 16.0+
  • Swift 5.0+
  • Info.plist
    • Privacy - Motion Usage Description
    • Privacy - Bluetooth Peripheral Usage Description
    • Privacy - Bluetooth Always Usage Description
    • Privacy - Location When In Use Usage Description
  • Recommended device capabilities
    • Accelerometer
    • Gyroscope
    • Magnetometer
    • Bluetooth Low Energy
  • Recommended background modes when continuous indoor service is required
    • App communicates using CoreBluetooth
    • App registers for location updates

🚀 Installation

CocoaPods

pod 'TJHanaSDK'

📌 Example

If you cannot find TJHanaSDK in CocoaPods, add the source below to your Podfile.

source 'https://github.com/CocoaPods/Specs.git'

🏁 Guide

1. Import

import TJHanaSDK

2. Authentication

  • You must authenticate before using Warp, Venus, or Jupiter.
TJHanaAuth.shared.auth(
    accessKey: "YOUR_ACCESS_KEY",
    secretAccessKey: "YOUR_SECRET_ACCESS_KEY"
) { code, success in
    print("Auth:", success, "code:", code)
}

🫧 Warp

TJWarpView provides a ward interaction view that can be attached to your screen and started after initialization.

Initialize and Start

final class WarpViewController: UIViewController, TJWarpViewDelegate {
    private let warpView = TJWarpView()

    override func viewDidLoad() {
        super.viewDidLoad()

        warpView.delegate = self
        warpView.initialize(id: "USER_ID", sectorId: 1, forceUpdate: true)
    }

    func onInitSuccess(_ view: TJWarpView, _ isSuccess: Bool, _ code: WarpInitErrorCode?) {
        guard isSuccess else { return }

        warpView.startService()
        warpView.configureFrame(to: self.view, warpImage: UIImage(named: "ic_warp"))
    }
}

Stop

warpView.stopService()

Delegate

extension ViewController: TJWarpViewDelegate {
    func onInitSuccess(_ view: TJWarpView, _ isSuccess: Bool, _ code: WarpInitErrorCode?) {}

    func onWarpSuccess(_ view: TJWarpView, _ isSuccess: Bool, _ code: WarpErrorCode?) {}

    func onClick(_ view: TJWarpView, warpWards: [WarpWard]) {}
}

Core Models

public struct WarpWard: Codable {
    public let id: Int
    public let name: String
    public let rssi: Int
    public let contents: [WardContents]
}

public struct WardContents: Codable {
    public let id: Int
    public let name: String
    public let url: URL
}

📍 Venus

TJVenusManager provides indoor result delivery through delegate callbacks.

Initialize and Start

final class VenusViewController: UIViewController, TJVenuseManagerDelegate {
    private var venusManager: TJVenusManager?

    override func viewDidLoad() {
        super.viewDidLoad()

        let manager = TJVenusManager(id: "USER_ID", sectorId: 1, forceUpdate: true)
        manager.delegate = self
        venusManager = manager
    }

    func onInitSuccess(_ manager: TJVenusManager, _ isSuccess: Bool, _ code: VenusInitErrorCode?) {
        guard isSuccess else { return }
        manager.startService()
    }
}

Stop

venusManager?.stopService()

Delegate

extension ViewController: TJVenuseManagerDelegate {
    func onInitSuccess(_ manager: TJVenusManager, _ isSuccess: Bool, _ code: VenusInitErrorCode?) {}

    func onVenusSuccess(_ manager: TJVenusManager, _ isSuccess: Bool, _ code: VenusErrorCode?) {}

    func onVenusResult(_ manager: TJVenusManager, _ result: VenusResult) {}
}

VenusResult

public struct VenusResult: Codable {
    public let mobile_time: Int
    public let building_id: Int
    public let building_name: String
    public let level_id: Int
    public let level_name: String
    public let x: Int
    public let y: Int
}

🧭 Jupiter

TJJupiterManager provides indoor positioning, in/out state changes, destination updates, and routing requests.

Initialize

let manager = TJJupiterManager(id: "USER_ID", sectorId: 1, debugOption: false)
manager.delegate = self

Start Service

manager.startService(mode: .MODE_AUTO)

Stop Service

manager.stopService { success, message in
    print("Stopped:", success, "message:", message)
}

Set Navigation Destination

manager.setNavigationDestination(
    dest: Point(level_id: 2, x: 120, y: 240)
)

Request Routing

manager.requestRouting(
    start: RoutingStart(level_id: 2, x: 100, y: 200, absolute_heading: 90),
    end: Point(level_id: 2, x: 120, y: 240),
    waypoints: []
)

Delegate

extension ViewController: TJJupiterManagerDelegate {
    func onInitSuccess(_ manager: TJJupiterManager, _ isSuccess: Bool, _ code: JupiterInitErrorCode?) {}

    func onJupiterSuccess(_ manager: TJJupiterManager, _ isSuccess: Bool, _ code: JupiterErrorCode?) {}

    func onJupiterReport(_ manager: TJJupiterManager, _ code: JupiterServiceCode, _ msg: String) {}

    func onJupiterResult(_ manager: TJJupiterManager, _ result: JupiterResult) {}

    func isJupiterInOutStateChanged(_ manager: TJJupiterManager, _ state: InOutState) {}

    func isUserGuidanceOut() {}

    func isNavigationRouteChanged(_ manager: TJJupiterManager, _ routes: [(String, String, Int, Float, Float)]) {}

    func isNavigationRouteFailed() {}

    func isWaypointChanged(_ manager: TJJupiterManager, _ waypoints: [[Double]]) {}
}

JupiterResult

public struct JupiterResult: Codable {
    public var mobile_time: Int
    public var index: Int
    public var building_name: String
    public var level_name: String
    public var jupiter_pos: Position
    public var navi_pos: Position?
    public var llh: LLH?
    public var velocity: Float
    public var is_vehicle: Bool
    public var is_indoor: Bool
    public var validity_flag: Int
}

Core Models

public struct Position: Codable {
    public var x: Float
    public var y: Float
    public var heading: Float
}

public struct LLH: Codable {
    public var lat: Double
    public var lon: Double
    public var azimuth: Double
}

public struct RoutingStart: Codable {
    public let level_id: Int
    public let x: Int
    public let y: Int
    public var absolute_heading: Int
}

public struct Point: Codable {
    public let level_id: Int
    public let x: Int
    public let y: Int
}

Core Enums

public enum UserMode: String {
    case MODE_PEDESTRIAN = "PDR"
    case MODE_VEHICLE = "DR"
    case MODE_AUTO = "AUTO"
}

public enum InOutState: Int {
    case UNKNOWN = -1
    case OUT_TO_IN = 0
    case INDOOR = 1
    case IN_TO_OUT = 2
    case OUTDOOR = 3
}

public enum JupiterInitErrorCode: Int {
    case UNKNOWN = -1
    case INVALID_ID = 0
    case INVALID_MODE = 1
    case NETWORK_DISCONNECT = 2
    case DUPLICATED_SERVICE = 3
    case LOGIN_FAIL = 4
    case CALC_INIT_FAIL = 5
}

public enum JupiterErrorCode: Int {
    case UNKNOWN = -1
    case INVALID_ID = 0
    case INVALID_MODE = 1
    case NETWORK_DISCONNECT = 2
    case DUPLICATED_SERVICE = 3
    case LOGIN_FAIL = 4
    case GENERATOR_FAIL = 5
    case CALC_INIT_FAIL = 6
}

public enum JupiterServiceCode: Int {
    case UNKNOWN = -1
    case SERVICE_FAIL = 0
    case SERVICE_SUCCESS = 1
    case BECOME_BACKGROUND = 2
    case BECOME_FOREGROUND = 3
    case BLUETOOTH_UNAVAILABLE = 4
    case BLUETOOTH_OFF = 5
    case BLUETOOTH_SCAN_STOP = 6
    case NETWORK_DISCONNECT = 7
}

📌 Example


📄 License

See the LICENSE file for details.