|
|
|
@ -1,4 +1,5 @@ |
|
|
|
import Foundation |
|
|
|
import UIKit |
|
|
|
import AVFoundation |
|
|
|
import ble_service |
|
|
|
import location_service |
|
|
|
@ -856,7 +857,8 @@ private func handleJSONDictionary(_ jsonDict: [String: Any], toolName: String) - |
|
|
|
if let cardMusiclist = jsonDict["data"] as? [[String: Any]], toolName == "music_searchandplay_songs" { |
|
|
|
processMusicListCard(cardMusiclist) |
|
|
|
} else if let cardNavigation = jsonDict["card_navigation"] as? [String: Any] { |
|
|
|
processNavigationCard(cardNavigation) |
|
|
|
let isinternal = processNavigationCard(cardNavigation) |
|
|
|
metadata["isinternal"] = isinternal |
|
|
|
} else if let cardQQMusiclist = jsonDict["data"] as? [[String: Any]], toolName == "qqmusic_searchandplay_songs" { |
|
|
|
processQQMusicPlayList(cardQQMusiclist) |
|
|
|
} else if toolName == "maps_weather" { |
|
|
|
@ -982,11 +984,293 @@ private func jsonToString(_ json: [String: Any]) -> String? { |
|
|
|
} |
|
|
|
|
|
|
|
// 处理导航卡片 |
|
|
|
private func processNavigationCard(_ cardNavigation: [String: Any]) { |
|
|
|
private func processNavigationCard(_ cardNavigation: [String: Any]) -> Bool { |
|
|
|
let start = cardNavigation["start"] as? String ?? "" |
|
|
|
let end = cardNavigation["end"] as? String ?? "" |
|
|
|
// 实际处理导航逻辑 |
|
|
|
print("启动导航: 从 \(start) 到 \(end)") |
|
|
|
let destination = cardNavigation["end"] as? String ?? "" |
|
|
|
let endlatitude = cardNavigation["endlatitude"] as? String ?? "" |
|
|
|
let endlongitude = cardNavigation["endlongitude"] as? String ?? "" |
|
|
|
let mode = cardNavigation["mode"] as? String ?? "driving" |
|
|
|
|
|
|
|
print("启动导航: 从 \(start) 到 \(destination), 坐标: \(endlatitude),\(endlongitude), 模式: \(mode)") |
|
|
|
|
|
|
|
// 根据导航模式选择不同的导航方式 |
|
|
|
switch mode { |
|
|
|
case "internal_gaode": |
|
|
|
// 使用内置高德导航 |
|
|
|
// startInternalNavigation(start: start, destination: destination, |
|
|
|
// latitude: endlatitude, longitude: endlongitude, mode: mode) |
|
|
|
return true |
|
|
|
case "external_baidu": |
|
|
|
// 使用外部百度地图 |
|
|
|
openBaiduMap(destination: destination, latitude: endlatitude, |
|
|
|
longitude: endlongitude, mode: mode) |
|
|
|
return false |
|
|
|
case "external_gaode": |
|
|
|
// 使用外部高德地图 |
|
|
|
openGaodeMap(destination: destination, latitude: endlatitude, |
|
|
|
longitude: endlongitude, mode: mode) |
|
|
|
return false |
|
|
|
case "external_google": |
|
|
|
// 使用外部谷歌地图 |
|
|
|
openGoogleMap(destination: destination, mode: mode) |
|
|
|
return false |
|
|
|
default: |
|
|
|
// 默认使用自动选择 |
|
|
|
return autoSelectNavigation(start: start, destination: destination, |
|
|
|
latitude: endlatitude, longitude: endlongitude, mode: mode) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 启动内置高德导航 |
|
|
|
private func startInternalNavigation(start: String, destination: String, |
|
|
|
latitude: String, longitude: String, mode: String) { |
|
|
|
// 发送导航事件通知 |
|
|
|
NotificationCenter.default.post(name: .navigationdEvent, object: nil, userInfo: [ |
|
|
|
"start": start, |
|
|
|
"destination": destination, |
|
|
|
"latitude": latitude, |
|
|
|
"longitude": longitude, |
|
|
|
"mode": mode |
|
|
|
]) |
|
|
|
print("启动内置导航: 从 \(start) 到 \(destination)") |
|
|
|
} |
|
|
|
|
|
|
|
// 打开百度地图 |
|
|
|
private func openBaiduMap(destination: String, latitude: String, longitude: String, mode: String) { |
|
|
|
guard let bundleId = Bundle.main.bundleIdentifier else { |
|
|
|
print("无法获取应用包名") |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
let src = "ios.\(bundleId)" |
|
|
|
|
|
|
|
// 百度地图导航模式映射 |
|
|
|
let baiduMode: String |
|
|
|
switch mode { |
|
|
|
case "transit": |
|
|
|
baiduMode = "transit" // 公交 |
|
|
|
case "walking": |
|
|
|
baiduMode = "walking" // 步行 |
|
|
|
case "cycling": |
|
|
|
baiduMode = "riding" // 骑行 |
|
|
|
case "driving": |
|
|
|
fallthrough |
|
|
|
default: |
|
|
|
baiduMode = "driving" // 驾车 |
|
|
|
} |
|
|
|
|
|
|
|
var components = URLComponents() |
|
|
|
components.scheme = "baidumap" |
|
|
|
components.host = "map" |
|
|
|
components.path = "/direction" |
|
|
|
components.queryItems = [ |
|
|
|
URLQueryItem(name: "destination", value: "name:\(destination)|latlng:\(latitude),\(longitude)"), |
|
|
|
URLQueryItem(name: "coord_type", value: "gcj02"), |
|
|
|
URLQueryItem(name: "mode", value: baiduMode), |
|
|
|
URLQueryItem(name: "src", value: src) |
|
|
|
] |
|
|
|
|
|
|
|
guard let url = components.url else { |
|
|
|
print("构建百度地图URL失败") |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
print("百度导航链接: \(url.absoluteString)") |
|
|
|
|
|
|
|
if UIApplication.shared.canOpenURL(url) { |
|
|
|
UIApplication.shared.open(url, options: [:]) { success in |
|
|
|
if success { |
|
|
|
print("成功打开百度地图") |
|
|
|
} else { |
|
|
|
print("打开百度地图失败") |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
print("百度地图未安装") |
|
|
|
// 可以在这里添加提示用户安装百度地图的逻辑 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 打开高德地图 |
|
|
|
private func openGaodeMap(destination: String, latitude: String, longitude: String, mode: String) { |
|
|
|
guard let bundleId = Bundle.main.bundleIdentifier else { |
|
|
|
print("无法获取应用包名") |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
let src = "ios.\(bundleId)" |
|
|
|
|
|
|
|
// 导航模式映射 |
|
|
|
let gaodeMode: String |
|
|
|
switch mode { |
|
|
|
case "transit": |
|
|
|
gaodeMode = "1" // 公交 |
|
|
|
case "walking": |
|
|
|
gaodeMode = "2" // 步行 |
|
|
|
case "cycling": |
|
|
|
gaodeMode = "3" // 骑行 |
|
|
|
case "driving": |
|
|
|
fallthrough |
|
|
|
default: |
|
|
|
gaodeMode = "0" // 驾车 |
|
|
|
} |
|
|
|
|
|
|
|
var components = URLComponents() |
|
|
|
components.scheme = "amapuri" |
|
|
|
components.host = "route" |
|
|
|
components.path = "/plan" |
|
|
|
components.queryItems = [ |
|
|
|
URLQueryItem(name: "dlat", value: latitude), |
|
|
|
URLQueryItem(name: "dlon", value: longitude), |
|
|
|
URLQueryItem(name: "dname", value: destination), |
|
|
|
URLQueryItem(name: "dev", value: "0"), // 0: gcj02 |
|
|
|
URLQueryItem(name: "t", value: gaodeMode), |
|
|
|
URLQueryItem(name: "sourceApplication", value: src) |
|
|
|
] |
|
|
|
|
|
|
|
guard let url = components.url else { |
|
|
|
print("构建高德地图URL失败") |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
print("高德导航链接: \(url.absoluteString)") |
|
|
|
|
|
|
|
if UIApplication.shared.canOpenURL(url) { |
|
|
|
UIApplication.shared.open(url, options: [:]) { success in |
|
|
|
if success { |
|
|
|
print("成功打开高德地图") |
|
|
|
} else { |
|
|
|
print("打开高德地图失败") |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
print("高德地图未安装") |
|
|
|
// 可以在这里添加提示用户安装高德地图的逻辑 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 打开谷歌地图 |
|
|
|
private func openGoogleMap(destination: String, mode: String) { |
|
|
|
// 方案1: 尝试使用Google Maps应用的URL scheme |
|
|
|
var components = URLComponents() |
|
|
|
components.scheme = "comgooglemaps" |
|
|
|
components.queryItems = [ |
|
|
|
URLQueryItem(name: "saddr", value: "Current Location"), |
|
|
|
URLQueryItem(name: "daddr", value: destination), |
|
|
|
URLQueryItem(name: "directionsmode", value: mode) |
|
|
|
] |
|
|
|
|
|
|
|
if let appUrl = components.url, UIApplication.shared.canOpenURL(appUrl) { |
|
|
|
UIApplication.shared.open(appUrl, options: [:]) { success in |
|
|
|
if success { |
|
|
|
print("成功打开谷歌地图应用") |
|
|
|
} else { |
|
|
|
print("打开谷歌地图应用失败") |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 方案2: 使用网页版谷歌地图 |
|
|
|
let webUrlString = "https://www.google.com/maps/dir/?api=1&origin=Current+Location&destination=\(destination)&travelmode=\(mode)" |
|
|
|
if let webUrl = URL(string: webUrlString) { |
|
|
|
UIApplication.shared.open(webUrl, options: [:]) { success in |
|
|
|
if success { |
|
|
|
print("成功打开谷歌地图网页版") |
|
|
|
} else { |
|
|
|
print("打开谷歌地图网页版失败") |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 打开苹果地图 |
|
|
|
private func openAppleMap(destination: String, mode: String) { |
|
|
|
var components = URLComponents() |
|
|
|
components.scheme = "maps" |
|
|
|
components.queryItems = [ |
|
|
|
URLQueryItem(name: "daddr", value: destination), |
|
|
|
URLQueryItem(name: "dirflg", value: mode == "driving" ? "d" : "r") // d=驾车, r=公交 |
|
|
|
] |
|
|
|
|
|
|
|
guard let url = components.url else { |
|
|
|
print("构建苹果地图URL失败") |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
if UIApplication.shared.canOpenURL(url) { |
|
|
|
UIApplication.shared.open(url, options: [:]) { success in |
|
|
|
if success { |
|
|
|
print("成功打开苹果地图") |
|
|
|
} else { |
|
|
|
print("打开苹果地图失败") |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
print("苹果地图不可用") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 自动选择导航应用 |
|
|
|
private func autoSelectNavigation(start: String, destination: String, |
|
|
|
latitude: String, longitude: String, mode: String) -> Bool { |
|
|
|
// 1. 优先尝试百度地图 |
|
|
|
if canOpenBaiduMap() { |
|
|
|
print("自动选择:使用百度地图") |
|
|
|
openBaiduMap(destination: destination, latitude: latitude, longitude: longitude, mode: mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 2. 其次尝试高德地图 |
|
|
|
if canOpenGaodeMap() { |
|
|
|
print("自动选择:使用高德地图") |
|
|
|
openGaodeMap(destination: destination, latitude: latitude, longitude: longitude, mode: mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 3. 然后尝试谷歌地图 |
|
|
|
if canOpenGoogleMap() { |
|
|
|
print("自动选择:使用谷歌地图") |
|
|
|
openGoogleMap(destination: destination, mode: mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 尝试苹果地图 |
|
|
|
if canOpenAppleMap() { |
|
|
|
print("自动选择:使用苹果地图") |
|
|
|
openAppleMap(destination: destination, mode: mode) |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 5. 最后尝试内置高德导航 |
|
|
|
print("自动选择:使用内置导航") |
|
|
|
// startInternalNavigation(start: start, destination: destination, |
|
|
|
// latitude: latitude, longitude: longitude, mode: mode) |
|
|
|
return true |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否可以打开百度地图 |
|
|
|
private func canOpenBaiduMap() -> Bool { |
|
|
|
guard let url = URL(string: "baidumap://") else { return false } |
|
|
|
return UIApplication.shared.canOpenURL(url) |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否可以打开高德地图 |
|
|
|
private func canOpenGaodeMap() -> Bool { |
|
|
|
guard let url = URL(string: "amapuri://") else { return false } |
|
|
|
return UIApplication.shared.canOpenURL(url) |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否可以打开谷歌地图 |
|
|
|
private func canOpenGoogleMap() -> Bool { |
|
|
|
guard let url = URL(string: "comgooglemaps://") else { return false } |
|
|
|
return UIApplication.shared.canOpenURL(url) |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否可以打开苹果地图 |
|
|
|
private func canOpenAppleMap() -> Bool { |
|
|
|
guard let url = URL(string: "maps://") else { return false } |
|
|
|
return UIApplication.shared.canOpenURL(url) |
|
|
|
} |
|
|
|
|
|
|
|
// 后台播放单曲 |
|
|
|
@ -1294,6 +1578,7 @@ class ChatApiStreamCallback: StreamCallback { |
|
|
|
private var responseBuilder = "" |
|
|
|
private var metadata = "" |
|
|
|
private var userMetadata:[String: Any] = [:] |
|
|
|
private var iscard = false; |
|
|
|
private var reply = true; //是否回复 |
|
|
|
private var broadcast = true //是否播发 |
|
|
|
|
|
|
|
@ -1443,15 +1728,19 @@ class ChatApiStreamCallback: StreamCallback { |
|
|
|
metadata = resultmap["meta"] as? String ?? "" |
|
|
|
broadcast = resultmap["broadcast"] as? Bool ?? true |
|
|
|
reply = !(resultmap["notreply"] as? Bool ?? true) |
|
|
|
agentService.sendEvent(name: "function_call_result", data: [ |
|
|
|
"function_call": functionCall, |
|
|
|
"result": functionCallResult, |
|
|
|
"meta":metadata, |
|
|
|
]) |
|
|
|
os_log("收到函数调用结果! broadcast: %{public}@ reply: %{public}@ %{metadata}@", |
|
|
|
log: agentService.logger, |
|
|
|
type: .info, |
|
|
|
"\(broadcast)", "\(reply)", "\(metadata)") |
|
|
|
iscard = !(resultmap["iscard"] as? Bool ?? false) |
|
|
|
if (iscard){ |
|
|
|
agentService.sendEvent(name: "function_call_result", data: [ |
|
|
|
"function_call": functionCall, |
|
|
|
"result": functionCallResult, |
|
|
|
"meta":metadata, |
|
|
|
]) |
|
|
|
os_log("收到函数调用结果! broadcast: %{public}@ reply: %{public}@ %{metadata}@", |
|
|
|
log: agentService.logger, |
|
|
|
type: .info, |
|
|
|
"\(broadcast)", "\(reply)", "\(metadata)") |
|
|
|
} |
|
|
|
|
|
|
|
}catch{ |
|
|
|
print("liwei--------------- AI Call onFunctionCallResult 异常: \(error)") |
|
|
|
} |
|
|
|
|