polarofficial / polar-ble-sdk

Repository includes SDK and code examples. More info https://polar.com/en/developers
Other
487 stars 155 forks source link

Hello I'm in need of assistance from someone who's good at development. #469

Closed OmniPrecedence closed 4 months ago

OmniPrecedence commented 4 months ago

Platform your question concerns:

Device:

Description: Can someone help with this code, or is there a generic working code that works for iOS and ignite 3 that's not deprecated or changed? please help, thank you. either I'm stupid or I don't know how to implement a heart rate onto the iOS app I'm building. I've marked out the error in //Error. its on line 86, 87 and 88 and it throws an error saying: Value of type 'PolarHrData' (aka 'Array<(hr: UInt8, rrsMs: Array, rrAvailable: Bool, contactStatus: Bool, contactStatusSupported: Bool)>') has no member 'hr'

//
//  PolarConnect.swift
//  LifeGuard
//
//  Created by OmniPrecedence on 28/06/2024.
//

import Foundation
import CoreBluetooth
import PolarBleSdk
import RxSwift

enum DeviceConnectionState {
    case disconnected(String)
    case connecting(String)
    case connected(String)

    var description: String {
        switch self {
        case .disconnected(let deviceId):
            return "Disconnected from \(deviceId)"
        case .connecting(let deviceId):
            return "Connecting to \(deviceId)"
        case .connected(let deviceId):
            return "Connected to \(deviceId)"
        }
    }
}

class PolarConnect: NSObject, ObservableObject, PolarBleApiObserver, PolarBleApiDeviceFeaturesObserver, PolarBleApiPowerStateObserver {
    func hrFeatureReady(_ identifier: String) {
        <#code#>
    }

    func ftpFeatureReady(_ identifier: String) {
        <#code#>
    }

    func streamingFeaturesReady(_ identifier: String, streamingFeatures: Set<PolarBleSdk.PolarDeviceDataType>) {
        <#code#>
    }

    @Published var isBluetoothOn: Bool = false
    @Published var deviceConnectionState: DeviceConnectionState = .disconnected("")
    @Published var heartRate: Int = 0
    @Published var discoveredPeripherals: [PolarDeviceInfo] = []
    @Published var connectedPeripheral: PolarDeviceInfo?

    private var polarApi: PolarBleApi!
    private let disposeBag = DisposeBag()

    override init() {
        super.init()
        polarApi = PolarBleApiDefaultImpl.polarImplementation(DispatchQueue.main, features: Set<PolarBleSdkFeature>([.feature_hr]))
        polarApi.observer = self
        polarApi.deviceFeaturesObserver = self
        polarApi.powerStateObserver = self
        isBluetoothOn = polarApi.isBlePowered
    }

    func startScanning(completion: @escaping (Result<Void, Error>) -> Void) {
        polarApi.searchForDevice()
            .observe(on: MainScheduler.instance)
            .subscribe(onNext: { [weak self] deviceInfo in
                print("Discovered device: \(deviceInfo.name)")
                if deviceInfo.name.contains("Polar Ignite 3") {
                    self?.discoveredPeripherals.append(deviceInfo)
                }
                completion(.success(()))
            }, onError: { error in
                print("Device search failed: \(error)")
                completion(.failure(error))
            })
            .disposed(by: disposeBag)
    }

    func stopScanning(completion: @escaping (Result<Void, Error>) -> Void) {
        // Implement the stop scanning method
        completion(.success(()))
    }

    func startHeartRateStreaming(deviceId: String, completion: @escaping (Result<Void, Error>) -> Void) {
        polarApi.startHrStreaming(deviceId)
            .observe(on: MainScheduler.instance)
            .subscribe(onNext: { hrData in
                self.heartRate = Int(hrData.hr) //Value of type 'PolarHrData' (aka 'Array<(hr: UInt8, rrsMs: Array<Int>, rrAvailable: Bool, contactStatus: Bool, contactStatusSupported: Bool)>') has no member 'hr'
                self.heartRate = Int(hrData.hr)
                print("Heart Rate: \(hrData.hr) bpm")
                completion(.success(()))
            }, onError: { error in
                print("HR streaming failed: \(error)")
                completion(.failure(error))
            })
            .disposed(by: disposeBag)
    }

    func connectToDevice(_ device: PolarDeviceInfo, completion: @escaping (Result<Void, Error>) -> Void) {
        do {
            try polarApi.connectToDevice(device.deviceId)
            completion(.success(()))
        } catch {
            print("Failed to connect to device: \(error)")
            completion(.failure(error))
        }
    }

    func disconnectDevice(completion: @escaping (Result<Void, Error>) -> Void) {
        if let connectedPeripheral = connectedPeripheral {
            do {
                try polarApi.disconnectFromDevice(connectedPeripheral.deviceId)
                completion(.success(()))
            } catch {
                print("Failed to disconnect from device: \(error)")
                completion(.failure(error))
            }
        } else {
            completion(.failure(NSError(domain: "No device connected", code: -1, userInfo: nil)))
        }
    }

    // PolarBleApiPowerStateObserver
    func blePowerOn() {
        isBluetoothOn = true
        print("Bluetooth is on")
    }

    func blePowerOff() {
        isBluetoothOn = false
        print("Bluetooth is off")
    }

    // PolarBleApiObserver
    func deviceConnecting(_ polarDeviceInfo: PolarDeviceInfo) {
        deviceConnectionState = .connecting(polarDeviceInfo.deviceId)
        print("Connecting to device: \(polarDeviceInfo.name)")
    }

    func deviceConnected(_ polarDeviceInfo: PolarDeviceInfo) {
        deviceConnectionState = .connected(polarDeviceInfo.deviceId)
        connectedPeripheral = polarDeviceInfo
        print("Connected to device: \(polarDeviceInfo.name)")
        startHeartRateStreaming(deviceId: polarDeviceInfo.deviceId) { result in
            switch result {
            case .success:
                break
            case .failure(let error):
                print("Failed to start heart rate streaming: \(error)")
            }
        }
    }

    func deviceDisconnected(_ polarDeviceInfo: PolarDeviceInfo, pairingError: Bool) {
        deviceConnectionState = .disconnected(polarDeviceInfo.deviceId)
        connectedPeripheral = nil
        print("Disconnected from device: \(polarDeviceInfo.name)")
    }

    // PolarBleApiDeviceFeaturesObserver
    func bleSdkFeatureReady(_ identifier: String, feature: PolarBleSdkFeature) {
        if feature == .feature_hr {
            startHeartRateStreaming(deviceId: identifier) { result in
                switch result {
                case .success:
                    break
                case .failure(let error):
                    print("Failed to start heart rate streaming: \(error)")
                }
            }
        }
        if feature == .feature_polar_online_streaming {
            polarApi.getAvailableOnlineStreamDataTypes(identifier)
                .observe(on: MainScheduler.instance)
                .subscribe(onSuccess: { availableDataTypes in
                    print("Available data types for streaming: \(availableDataTypes)")
                }, onFailure: { error in
                    print("Failed to get available streaming data types: \(error)")
                }).disposed(by: disposeBag)
        }
    }

    // PolarBleApiDeviceHrObserver
    func hrValueReceived(_ identifier: String, data: (hr: UInt8, rrs: [Int], rrsMs: [Int], contact: Bool, contactSupported: Bool)) {
        let heartRate = Int(data.hr)
        print("Heart rate received: \(heartRate) bpm")
        self.heartRate = heartRate
    }

    // Additional stubs for conformance
    func batteryLevelReceived(_ identifier: String, batteryLevel: UInt) { }
    func ecgFeatureReady(_ identifier: String) { }
    func accFeatureReady(_ identifier: String) { }
    func ppgFeatureReady(_ identifier: String) { }
    func ppiFeatureReady(_ identifier: String) { }
    func deviceConnected(_ identifier: String) { }
    func deviceDisconnected(_ identifier: String) { }
}

    // Stubs for methods
    func hrFeatureReady(_ identifier: String) {
        print("Heart rate feature is ready for device \(identifier)")
    }

    func ftpFeatureReady(_ identifier: String) {
        print("FTP feature is ready for device \(identifier)")
    }

    func streamingFeaturesReady(_ identifier: String, streamingFeatures: Set<PolarBleSdk.PolarDeviceDataType>) {
        print("Streaming features are ready for device \(identifier): \(streamingFeatures)")
    }