[英]DJI drone not connecting (sdkManagerProductDidChange delegate method not called)
I can't seem to get my own app to connect to a particular drone. 我似乎无法获得自己的应用程序以连接到特定的无人机。 I have downloaded the bridger app and am using it to debug.
我已经下载了bridger应用程序,并正在使用它进行调试。 I copied the "DJIBaseViewController" from the sample app and have made my own view controller a delegate of it.
我从示例应用程序复制了“ DJIBaseViewController”,并将自己的视图控制器作为它的委托。 After adding alot of breakpoints to the code I have found that the major difference between my app and the sample app is that the delegate method "sdkManagerProductDidChange."
在代码中添加了很多断点后,我发现我的应用程序与示例应用程序之间的主要区别在于委托方法“ sdkManagerProductDidChange”。
// DJIBaseViewController.swift
import UIKit
import DJISDK
protocol DJIProductObjectProtocol {
func fetchAircraft() -> DJIAircraft?
func fetchCamera() -> DJICamera?
func fetchGimbal() -> DJIGimbal?
func fetchFlightController() -> DJIFlightController?
func fetchRemoteController() -> DJIRemoteController?
func fetchBattery() -> DJIBattery?
func fetchAirLink() -> DJIAirLink?
func fetchHandheldController() -> DJIHandheldController?
}
class ConnectedProductManager: DJIProductObjectProtocol {
static let sharedInstance = ConnectedProductManager()
var connectedProduct:DJIBaseProduct? = nil
func fetchAircraft() -> DJIAircraft? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft)
}
return nil
}
func fetchCamera() -> DJICamera? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).camera
}
else if (self.connectedProduct is DJIHandheld) {
return (self.connectedProduct as! DJIHandheld).camera
}
return nil
}
func fetchGimbal() -> DJIGimbal? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).gimbal
}
else if (self.connectedProduct is DJIHandheld) {
return (self.connectedProduct as! DJIHandheld).gimbal
}
return nil
}
func fetchFlightController() -> DJIFlightController? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).flightController
}
return nil
}
func fetchRemoteController() -> DJIRemoteController? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).remoteController
}
return nil
}
func fetchBattery() -> DJIBattery? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).battery
}
else if (self.connectedProduct is DJIHandheld) {
return (self.connectedProduct as! DJIHandheld).battery
}
return nil
}
func fetchAirLink() -> DJIAirLink? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIAircraft) {
return (self.connectedProduct as! DJIAircraft).airLink
}
else if (self.connectedProduct is DJIHandheld) {
return (self.connectedProduct as! DJIHandheld).airLink
}
return nil
}
func fetchHandheldController() -> DJIHandheldController? {
if (self.connectedProduct == nil) {
return nil
}
if (self.connectedProduct is DJIHandheld) {
return (self.connectedProduct as! DJIHandheld).handheldController
}
return nil
}
func setDelegate(delegate:DJIBaseProductDelegate?) {
self.connectedProduct?.delegate = delegate
}
}
class DJIBaseViewController: UIViewController, DJIBaseProductDelegate, DJIProductObjectProtocol {
//var connectedProduct:DJIBaseProduct?=nil
var moduleTitle:String?=nil
override func viewDidLoad() {
super.viewDidLoad()
if (moduleTitle != nil) {
self.title = moduleTitle
}
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if (ConnectedProductManager.sharedInstance.connectedProduct != nil) {
ConnectedProductManager.sharedInstance.setDelegate(self)
}
}
override func viewWillDisappear(
animated: Bool) {
super.viewWillDisappear(animated)
if (ConnectedProductManager.sharedInstance.connectedProduct != nil &&
ConnectedProductManager.sharedInstance.connectedProduct?.delegate === self) {
ConnectedProductManager.sharedInstance.setDelegate(nil)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func product(product: DJIBaseProduct, connectivityChanged isConnected: Bool) {
if isConnected {
NSLog("\(product.model) connected. ")
ConnectedProductManager.sharedInstance.connectedProduct = product
ConnectedProductManager.sharedInstance.setDelegate(self)
}
else {
NSLog("Product disconnected. ")
ConnectedProductManager.sharedInstance.connectedProduct = nil
}
}
func componentWithKey(withKey key: String, changedFrom oldComponent: DJIBaseComponent?, to newComponent: DJIBaseComponent?) {
// (newComponent as? DJICamera)?.delegate = self
if ((newComponent is DJICamera) == true && (self is DJICameraDelegate) == true) {
(newComponent as! DJICamera).delegate = self as? DJICameraDelegate
}
if ((newComponent is DJICamera) == true && (self is DJIPlaybackDelegate) == true) {
(newComponent as! DJICamera).playbackManager?.delegate = self as? DJIPlaybackDelegate
}
if ((newComponent is DJIFlightController) == true && (self is DJIFlightControllerDelegate) == true) {
(newComponent as! DJIFlightController).delegate = self as? DJIFlightControllerDelegate
}
if ((newComponent is DJIBattery) == true && (self is DJIBatteryDelegate) == true) {
(newComponent as! DJIBattery).delegate = self as? DJIBatteryDelegate
}
if ((newComponent is DJIGimbal) == true && (self is DJIGimbalDelegate) == true) {
(newComponent as! DJIGimbal).delegate = self as? DJIGimbalDelegate
}
if ((newComponent is DJIRemoteController) == true && (self is DJIRemoteControllerDelegate) == true) {
(newComponent as! DJIRemoteController).delegate = self as? DJIRemoteControllerDelegate
}
}
func showAlertResult(info:String) {
// create the alert
var message:String? = info
if info.hasSuffix(":nil") {
message = info.stringByReplacingOccurrencesOfString(":nil", withString: " success")
}
let alert = UIAlertController(title: "Message", message: "\(message ?? "")", preferredStyle: .Alert)
// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
// show the alert
self.presentViewController(alert, animated: true, completion: nil)
}
func fetchAircraft() -> DJIAircraft?{
return ConnectedProductManager.sharedInstance.fetchAircraft()
}
func fetchCamera() -> DJICamera? {
return ConnectedProductManager.sharedInstance.fetchCamera()
}
func fetchGimbal() -> DJIGimbal? {
return ConnectedProductManager.sharedInstance.fetchGimbal()
}
func fetchFlightController() -> DJIFlightController? {
return ConnectedProductManager.sharedInstance.fetchFlightController()
}
func fetchRemoteController() -> DJIRemoteController? {
return ConnectedProductManager.sharedInstance.fetchRemoteController()
}
func fetchBattery() -> DJIBattery? {
return ConnectedProductManager.sharedInstance.fetchBattery()
}
func fetchAirLink() -> DJIAirLink? {
return ConnectedProductManager.sharedInstance.fetchAirLink()
}
func fetchHandheldController() -> DJIHandheldController?{
return ConnectedProductManager.sharedInstance.fetchHandheldController()
}
}
The first view that loads after the splashscreen loads is. 启动屏幕加载后加载的第一个视图是。
// MenuViewController.swift
import UIKit
import DJISDK
let enterDebugMode=true
class MenuViewController: DJIBaseViewController {
@IBOutlet weak var aircraft: UILabel!
@IBOutlet weak var productID: UILabel!
// Do any additional setup after loading the view.
@IBOutlet weak var appConectivity: UILabel!
var connectedProduct:DJIBaseProduct?=nil
var componentDictionary = Dictionary<String, Array<DJIBaseComponent>>()
let APP_KEY = "*******"//Please enter App Key Here
override func viewDidLoad() {
super.viewDidLoad()
let air = self.fetchAircraft()
if air == nil{
aircraft.text?="no aircraft connected"
}
print(air?.model)
initUI();
guard !APP_KEY.isEmpty else {
showAlert("Please enter your app key.")
return
}
DJISDKManager.registerApp(APP_KEY, withDelegate: self)
if DJISDKManager.product() == nil{
productID.text?="Drone Not Connected"
}
else{
productID.text? = "Drone Connected"
}
}
func initUI() {
self.title = "DJI iOS SDK Sample"
//sdkVersionLabel.text = "DJI SDK Version: \(DJISDKManager.getSDKVersion())"
//openComponents.isEnabled = false;
//bluetoothConnectorButton.isEnabled = true;
//productModel.isHidden = true
//productFirmwarePackageVersion.isHidden = true
//debugModeLabel.isHidden = !enterDebugMode
}
func showAlert(msg: String?) {
// create the alert
let alert = UIAlertController(title: "", message: msg, preferredStyle: .Alert)
// add the actions (buttons)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
// show the alert
self.presentViewController(alert, animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension MenuViewController: DJISDKManagerDelegate{
func sdkManagerDidRegisterAppWithError(error: NSError?) {
guard error == nil else {
self.showAlertResult("Error:\(error!.localizedDescription)")
appConectivity.text?="app isn't registering properly"
return
}
//Debug("Registered!")
if enterDebugMode {
DJISDKManager.enterDebugModeWithDebugId("10.202.38.238")
print("WTF")
}else{
//DJISDKManager.enterDebugModeWithDebugId("10.202.38.238")
DJISDKManager.startConnectionToProduct()
}
}
func sdkManagerProductDidChange(From oldProduct: DJIBaseProduct?, To newProduct: DJIBaseProduct?) {
print("entered changed product")
if oldProduct==nil{
print("old product is nill")
}
if newProduct==nil{
print("new product is nill")
}
guard let newProduct = newProduct else
{
appConectivity.text? = "Status: No Product Connected"
ConnectedProductManager.sharedInstance.connectedProduct = nil
//logDebug("Product Disconnected")
return
}
//Updates the product's model
productID.text = "Model: \((newProduct.model)!)"
productID.hidden = false
if let oldProduct = oldProduct {
print("Product changed from: \(oldProduct.model) to \((newProduct.model)!)")
}
//Updates the product's firmware version - COMING SOON
//Updates the product's connection status
//appConectivity.text = "Status: Product Connected"
ConnectedProductManager.sharedInstance.connectedProduct = newProduct
productID.text?="product connected"
//openComponents.isEnabled = true;
//openComponents.alpha = 1.0;
//logDebug("Product Connected")
}
override func product(product: DJIBaseProduct, connectivityChanged isConnected: Bool) {
if isConnected {
print("Status: Product Connected")
//appConectivity.text?="Drone Recognized"
} else {
print("Status: No Product Connected")
//appConectivity.text="Atleast Its trying"
}
}
}
The sdkManager is registering properly with the given app key and bundler identifier. sdkManager正在使用给定的应用程序密钥和捆绑程序标识符正确注册。 I have also added "Supported external accessory protocols" to my info.plist file with three elements com.dji.video, com.dji.protocol, and com.dji.common.
我还在我的info.plist文件中添加了“受支持的外部附件协议”,其中包含三个元素com.dji.video,com.dji.protocol和com.dji.common。
Been stuck here for quite some time and it's been damn frustrating. 被困在这里已经有一段时间了,真是令人沮丧。 Hope someone call help.
希望有人打电话帮助。
Thanks in advance. 提前致谢。
I figured it out. 我想到了。 The issue here is that the sample app has named its delegate
这里的问题是示例应用程序已为其委托命名
func sdkManagerProductDidChange(from oldProduct: DJIBaseProduct?, to newProduct: DJIBaseProduct?)
whereas for whatever reason in my sample app the DJISDK knows my delegates function as 而无论出于何种原因,DJISDK都知道我的委托函数是
func sdkManagerProductDidChangeFrom(oldProduct: DJIBaseProduct?, to newProduct: DJIBaseProduct?)
a bit annoying that that made such a big difference but that's what I get for copying code I guess. 有点烦人,这带来了很大的不同,但这就是我猜到的复制代码所得到的。 Hope this is helpful to someone else down the road...
希望这对以后的人有帮助...
Cheers 干杯
PS they may change it again the way I found it is when I typed func into my extension section Xcode spit out a list of functions I could use and the sdkManagerDidChange was one of them with different input variables. PS,当我在扩展部分的Xcode中键入func时,他们可能会再次更改它,方法是吐出我可以使用的功能列表,而sdkManagerDidChange是其中一个具有不同输入变量的函数。
edit: if anyone can explain why it worked on the sample app and not mine that would be sweet too. 编辑:如果有人可以解释为什么它可以在示例应用程序上运行,而不是我认为那也很好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.