YannisDC YannisDC - 3 months ago 24
iOS Question

OBD2Kit Swift example can't typecast, keep getting nil

Since there was no example code for using OBD2Kit and Swift I forked it into https://github.com/YannisDC/OBD2Kit and used it as a pod.

I translated some OBJ-C example code but can't seem to downcast the FLWiFiScanTool into the ELM327 type. Why do I keep getting nil?

import UIKit
import OBD2Kit

class ViewController: UIViewController, FLScanToolDelegate {

@IBOutlet weak var hostIpAddress: UITextField!

var scanTool: ELM327!

@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var scanToolLabel: UILabel!
@IBOutlet weak var rpmLabel: UILabel!
@IBOutlet weak var speedLabel: UILabel!
@IBOutlet weak var tempLabel: UILabel!
var scanning = false

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.hostIpAddress.text = "192.168.0.10"
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

@IBAction func scanButton(sender: UIButton) {
if !scanning {
startScan()
} else {
stopScan()
}
}

func startScan() {
if let scanTool = ELM327(host: self.hostIpAddress.text!, andPort: 35000) {
self.statusLabel.text = "Initializing..."
scanTool.useLocation = true
scanTool.delegate = self
scanTool.startScanWithSensors({() -> [AnyObject] in
dispatch_async(dispatch_get_main_queue(), {() -> Void in
self.statusLabel.text = "Scanning..."
self.scanToolLabel.text = scanTool.scanToolName
})

// let sensors: [AnyObject] = [ OBD2Sensor.SensorEngineRPM as! AnyObject,
// OBD2Sensor.SensorVehicleSpeed as! AnyObject,
// OBD2Sensor.SensorOxygenSensorsPresent as! AnyObject ]

let sensors: [AnyObject] = [ 0x0C,
0x0D,
0x13 ]
return sensors
})
self.scanTool = scanTool
print("So far succesfull")
scanning = !scanning
} else {
self.statusLabel.text = "Not working"
}
}

func stopScan() {
statusLabel.text = "Stopped"
let scanTool: ELM327 = self.scanTool
scanTool.cancelScan()
scanTool.sensorScanTargets = nil
scanTool.delegate = nil
scanning = !scanning
}

// MARK: - FLScanToolDelegate


func scanTool(scanTool: FLScanTool, sensor: FLECUSensor) {
var sensorLabel: UILabel? = nil
switch sensor.pid {

case OBD2Sensor.SensorEngineRPM:
sensorLabel = self.rpmLabel

case OBD2Sensor.SensorVehicleSpeed:
sensorLabel = self.speedLabel

default:
sensorLabel = self.tempLabel
}

self.showSensorValue(sensor, onLabel: sensorLabel!)
}

func showSensorValue(sensor: FLECUSensor, onLabel label: UILabel) {
let sensorValue: String = "\(sensor.valueStringForMeasurement1(false)) \(sensor.imperialUnitString)"
dispatch_async(dispatch_get_main_queue(), {() -> Void in
label.text = sensorValue
})
}

}


Edit 1:

I can already scan for the tool now since ELM327 is a FLWiFiScanTool and not the other way around. I can get the toolname so it's connecting but can't seem to get the sensors output.

Answer

I managed to figure it out. The expected sensors array should be one of NSNumbers so I casted the sensors UInt's to NSNumbers. And I also missed the didUpdateSensor part in the scanTool function.

Make sure to use the metric system, this is somehow way more reliable in my case. (My car is using the metric system as well, maybe that's why.)

import UIKit
import OBD2Kit

class ViewController: UIViewController, FLScanToolDelegate {
    var scanTool: ELM327!

    @IBOutlet weak var statusLabel: UILabel!
    @IBOutlet weak var scanToolLabel: UILabel!
    @IBOutlet weak var rpmLabel: UILabel!
    @IBOutlet weak var speedLabel: UILabel!
    @IBOutlet weak var tempLabel: UILabel!
    var scanning = false

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func scanButton(sender: UIButton) {
        if !scanning {
            startScan()
        } else {
            stopScan()
        }
    }

    func startScan() {
        if let scanTool = ELM327(host: "192.168.0.10", andPort: 35000) {
            self.statusLabel.text = "Initializing..."
            scanTool.useLocation = true
            scanTool.delegate = self
            scanTool.startScanWithSensors({() -> [AnyObject] in
                dispatch_async(dispatch_get_main_queue(), {() -> Void in
                    self.statusLabel.text = "Scanning..."
                    self.scanToolLabel.text = scanTool.scanToolName
                })

                let sensors: [AnyObject] = [ OBD2Sensor.SensorEngineRPM as NSNumber, OBD2Sensor.SensorVehicleSpeed as NSNumber, OBD2Sensor.SensorOxygenSensorsPresent as NSNumber ]

                return sensors
            })
            self.scanTool = scanTool
            print("So far succesfull")
            scanning = !scanning
        } else {
            self.statusLabel.text = "Not working"
        }
    }

    func stopScan() {
        statusLabel.text = "Stopped"
        let scanTool: ELM327 = self.scanTool
        scanTool.cancelScan()
        scanTool.sensorScanTargets = nil
        scanTool.delegate = nil
        scanning = !scanning
    }

    // MARK: - FLScanToolDelegate

    func scanTool(scanTool: FLScanTool!, didUpdateSensor sensor: FLECUSensor!) {
        var sensorLabel: UILabel? = nil
        switch sensor.pid {

        case OBD2Sensor.SensorEngineRPM:
            sensorLabel = self.rpmLabel

        case OBD2Sensor.SensorVehicleSpeed:
            sensorLabel = self.speedLabel

        default:
            sensorLabel = self.tempLabel
        }

        self.showSensorValue(sensor, onLabel: sensorLabel!)
    }

    func showSensorValue(sensor: FLECUSensor, onLabel label: UILabel) {
        let sensorValue: String = "\(sensor.valueStringForMeasurement1(true)) \(sensor.metricUnitString)"
        dispatch_async(dispatch_get_main_queue(), {() -> Void in
            label.text = sensorValue
        })
    }

}
Comments