Commit 1b8c1b49 authored by p x's avatar p x
Browse files

调试Http sse链接

parent 5c8123f6
package com.sd.cavphmi.bean
/***网联车辆位姿
*{"version":"2.0.0","data_id":"default","data_type":"OBU","data_list":[{"vid":"261","vmodel":"01010102001","vtype":"双层客车1","coord_type":"Geo","coord":"117.3499501,39.0072603","direction":333.573,"speed":1.0,"timestamp":1755156180282,"vinfo":{"door":0,"light":0,"wiper":1}},{"vid":"263","vmodel":"01010400006","vtype":"中型客车","coord_type":"Geo","coord":"117.3487397,39.0030869","direction":3.008699999999976,"speed":58.0,"timestamp":1755156180283,"vinfo":{"door":0,"light":0,"wiper":1}},{"vid":"265","vmodel":"01010400001","vtype":"清扫","coord_type":"Geo","coord":"117.3443229,39.0011612","direction":349.3043,"speed":54.0,"timestamp":1755156180283,"vinfo":{"door":0,"light":0,"wiper":1}},{"vid":"267","vmodel":"01010400003","vtype":"售卖","coord_type":"Geo","coord":"117.3463546,38.9986415","direction":348.0532,"speed":4.0,"timestamp":1755156180284,"vinfo":{"door":0,"light":36864,"wiper":1,"poleId":"1200003843"}},{"vid":"269","vmodel":"01010400004","vtype":"出租","coord_type":"Geo","coord":"117.3472319,38.994756","direction":190.48939999999993,"speed":41.0,"timestamp":1755156180283,"vinfo":{"door":0,"light":0,"wiper":1,"poleId":"1200003838"}},{"vid":"271","vmodel":"01010400008","vtype":"巡逻车","coord_type":"Geo","coord":"117.3470161,39.0023286","direction":87.26830000000001,"speed":60.0,"timestamp":1755156180284,"vinfo":{"door":0,"light":0,"wiper":1}}]}
* {
* "data": {
* "businessStatus": "DRIVING",
* "spaceName": "B075",
* "vehiclePos": [
* 116.50268,
* 39.808735,
* 59.688720703125
* ],
* "routing": [
*
* ],
* "progress": null
* }
* }
* **/
class CarVehicle : ArrayList<CarVehicleItem>()
//data class CarVehicle(
// val data: VehData
//)
class CarVehicleItem {
var acceSpeed: String = ""
var accessTime: Long = 0L
var deviceCode: String = ""
var deviceId: String = ""
var deviceStatus: Int = 0
var door: Int = 0
var drivingMode: Int = 0
var elevation = 0.0
var gear: Int = 0
var heading: Double = 0.0
var id: String = ""
var latitude: Double = 0.0
var light: Int = 0
var longitude: Double = 0.0
var msgId: String = ""
var modelId: String = ""
var parkInLot: Int = 0
var receiveTime: Long = 0L
var reportTime: Long = 0L
var soc: Double = 0.0
var speed: Double = 0.0
var sweeperState: Int = 0
var vehicleCode: String = ""
var vehicleId: String = ""
var vehiclePlate: String = ""
var vehiclePurpose: String = ""
var vehicle_purpose_special_vehicle_qs: String = ""
var waterState: Int = 0
var wheelAngle: String = ""
var wiper: Int = 0
class CarVehicle {
val businessStatus: String = ""
val progress: Any = ""
val routing: List<Any>? = null
val spaceName: String = ""
//vehiclePos 里面分别是 经度、纬度、航向角
val vehiclePos: List<Double>? = null
}
\ No newline at end of file
......@@ -11,7 +11,7 @@ import com.sd.cavphmi.utils.MyContants
* @constructor Create empty Tile json bean
*/
class TileJsonBean {
var host: String = MyContants.HOST_HTTP_3
var host: String = MyContants.HOST_MAP
var tiles3d = listOf(
// "/gis_data/3dtiles/road/CurbStrip/tileset.json",
"/gis_data/3dtiles/road/LanePolygon/tileset.json",
......
package com.sd.cavphmi.moudule
import com.sd.cavphmi.net.BaseUrlInterceptor
import com.sd.cavphmi.net.HeadParamsInterceptor
import com.sd.cavphmi.net.RetrofitApi
import com.sd.cavphmi.net.RetrofitApi.retrofitBuild
import com.sd.cavphmi.net.httpmothod.ClientRetrofitMethod
import dagger.Module
......@@ -12,22 +9,23 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.*
import javax.inject.Qualifier
import javax.inject.Singleton
import javax.net.ssl.*
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class OriginOkHttpClient
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient
//@Qualifier
//@Retention(AnnotationRetention.BINARY)
//annotation class AuthInterceptorOkHttpClient
@Qualifier
@Retention(AnnotationRetention.BINARY)
......@@ -38,7 +36,7 @@ annotation class NormalInterceptorOkHttpClient
@InstallIn(SingletonComponent::class)
object NetworkModule {
var logging = HttpLoggingInterceptor()
private var logging = HttpLoggingInterceptor()
init {
logging.level = HttpLoggingInterceptor.Level.BODY
......@@ -48,68 +46,75 @@ object NetworkModule {
@OriginOkHttpClient
@Provides
fun provideOriginOkHttpClient(): OkHttpClient {
var sslData = getSSlSocketFactory()
return OkHttpClient.Builder()
.addInterceptor(logging)
.sslSocketFactory(sslData.socketFactory, sslData.trustAllCert)
.hostnameVerifier { hostname, session -> true }
.build()
}
@NormalInterceptorOkHttpClient
@Provides
fun provideNormalInterceptorOkHttpClient(
headParamsInterceptor: HeadParamsInterceptor
fun provideSeeInterceptorOkHttpClient(
// headParamsInterceptor: HeadParamsInterceptor
// baseUrlInterceptor: BaseUrlInterceptor,
): OkHttpClient {
// 创建信任所有证书的 TrustManager
val trustAllCerts = arrayOf<TrustManager>(
object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
)
// 初始化 SSLContext
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, SecureRandom())
// val trustAllCerts = arrayOf<TrustManager>(
// object : X509TrustManager {
// override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
// override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
// override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
// }
// )
// // 初始化 SSLContext
// val sslContext = SSLContext.getInstance("TLS")
// sslContext.init(null, trustAllCerts, SecureRandom())
var sslData = getSSlSocketFactory()
return OkHttpClient.Builder()
.cache(RetrofitApi.cache)
// .addInterceptor(baseUrlInterceptor)
.addInterceptor(headParamsInterceptor)
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
.hostnameVerifier { hostname, session -> true }
// .addInterceptor(headParamsInterceptor)
.addInterceptor(logging)
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(sslData.socketFactory, sslData.trustAllCert)
.build()
}
//------------------API 方法---------------
@Singleton
@Provides
fun provideClientRetrofitService(@NormalInterceptorOkHttpClient okHttpClient: OkHttpClient): ClientRetrofitMethod {
fun provideClientRetrofitService(@OriginOkHttpClient okHttpClient: OkHttpClient): ClientRetrofitMethod {
return retrofitBuild.client(okHttpClient).build().create(ClientRetrofitMethod::class.java)
}
fun getSSlSocketFactory(): SslData {
val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm()
)
trustManagerFactory.init(null as KeyStore?)
val trustManagers: Array<TrustManager> = trustManagerFactory.getTrustManagers()
check(!(trustManagers.size != 1 || trustManagers[0] !is X509TrustManager)) {
("Unexpected default trust managers:"
+ Arrays.toString(trustManagers))
}
val trustManager = trustManagers[0] as X509TrustManager
// @Singleton
// @Provides
// fun provideClientRetrofitSeeService(@NormalInterceptorOkHttpClient okHttpClient: OkHttpClient): ClientRetrofitMethodSee {
// return retrofitBuild.client(okHttpClient).build()
// .create(ClientRetrofitMethodSee::class.java)
// }
fun getSSlSocketFactory(): SslData {
// 创建信任所有证书的 TrustManager
val trustAllCerts = arrayOf<TrustManager>(
object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
}
)
// 初始化 SSLContext
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
val sslSocketFactory = sslContext.socketFactory
sslContext.init(null, trustAllCerts, SecureRandom())
return SslData(sslSocketFactory, trustManager)
return SslData(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
}
data class SslData(val sslSocketFactory: SSLSocketFactory, var trustManager: X509TrustManager)
data class SslData(val socketFactory: SSLSocketFactory, var trustAllCert: X509TrustManager)
// 创建信任所有证书的 SSLSocketFactory
......
package com.sd.cavphmi.net
import com.sd.cavphmi.bean.WarningBean
import com.sd.cavphmi.moudule.NetworkModule.getSSlSocketFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.internal.closeQuietly
import java.io.IOException
import java.util.concurrent.TimeUnit
class SimpleSSEClient {
companion object {
val instance: SimpleSSEClient by lazy { SimpleSSEClient() }
}
// private var logging = HttpLoggingInterceptor()
// private val client = OkHttpClient()
private var client: OkHttpClient
private var responseBodys = mutableListOf<ResponseBody>()
private var calls = mutableListOf<Call>()
private constructor() {
var sslData = getSSlSocketFactory()
client = OkHttpClient.Builder()
// .addInterceptor(logging)
.readTimeout(0, TimeUnit.SECONDS)
.sslSocketFactory(sslData.socketFactory, sslData.trustAllCert)
.hostnameVerifier { hostname, session -> true }
.build()
}
fun startSSE(url: String, body: RequestBody?, listener: SSESimpleListener?) {
val build = Request.Builder()
.url(url)
.header("Accept", "text/event-stream")
.header("Cache-Control", "no-cache")
if (body != null) {
build.post(body)
}
val request = build.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
listener?.onError(e)
}
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
listener?.onError(IOException("HTTP ${response.code}"))
return
}
calls.add(call)
try {
response.body?.let { body ->
// println("----------- let SimpleSSEClient.onResponse")
responseBodys.add(body)
body.source().use { source ->
if (source == null)
return
listener?.onOpen()
while (true) {
val line = source.readUtf8Line() ?: break
when {
line.startsWith("data:") -> {
val data = line.substring(5).trim()
listener?.onEvent(data)
}
line.isEmpty() -> {
// 事件分隔符
}
}
}
listener?.onClosed()
}
}
} catch (e: IOException) {
} finally {
// response.closeQuietly()
}
}
})
}
interface SSESimpleListener {
fun onOpen()
fun onEvent(data: String)
fun onError(throwable: Throwable)
fun onClosed()
}
/**释放连接***/
fun cancelContect() {
CoroutineScope(Dispatchers.Default).launch {
// for (call in calls) {
// call.cancel()
// }
for (body in responseBodys) {
body.closeQuietly()
}
}
}
}
\ No newline at end of file
......@@ -36,10 +36,10 @@ interface ClientRetrofitMethod {
suspend fun getBindCar(): BindCarBean
// suspend fun getBindCar(@Body body: RequestBody): List<BindCarItem>
/**AVP状态***/
@POST("api/avpweb/hmi/monitor/v1/taskStatus")
suspend fun getAvpStatus(@Body body: RequestBody): AvpStatuBean
/***http 长连接 sse 协议 入参 {"id":车俩id}***/
// @POST("api/avpweb/app/monitor/v1/monitorDrivenStatus")
// suspend fun getCarPoseSee(@Body body: RequestBody): String
/***获取订单信息**/
......
package com.sd.cavphmi.repositorys
import com.sd.cavphmi.bean.AvpStatuBean
import com.sd.cavphmi.bean.BindResult
import com.sd.cavphmi.bean.SpaceInfoBean
import com.sd.cavphmi.bean.VehDetailBean
import com.sd.cavphmi.bean.req.SpaceInfo
import com.sd.cavphmi.net.MyResult
import com.sd.cavphmi.net.RequestBodyUtil
import com.sd.cavphmi.net.SimpleSSEClient
import com.sd.cavphmi.net.SimpleSSEClient.SSESimpleListener
import com.sd.cavphmi.net.httpmothod.ClientRetrofitMethod
import com.sd.cavphmi.utils.MyContants
import okhttp3.RequestBody
import retrofit2.HttpException
import retrofit2.http.Body
import javax.inject.Inject
/**AVP 接口**/
class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRetrofitMethod) {
class AvpDataRepo @Inject constructor(
private var retrofitMethod: ClientRetrofitMethod
) {
private var simpleSSEClient = SimpleSSEClient.instance
/**获取车辆详情
* @param id 正常应该是传场地ID,但是亦庄这个和太和桥车是一样的
......@@ -25,7 +29,7 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
// var map = mapOf()
var body = RequestBodyUtil.toRequestBody(mapOf())
try {
var bean = clientRetrofitMethod.getVehDetail(body)
var bean = retrofitMethod.getVehDetail(body)
return MyResult.Success(bean)
} catch (e: HttpException) {
// println("e.message = ${e.message}")
......@@ -44,7 +48,7 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
state = 1
}
var body = RequestBodyUtil.toRequestBody(spaceInfo)
var bean = clientRetrofitMethod.getSpaceInfo(body)
var bean = retrofitMethod.getSpaceInfo(body)
return MyResult.Success(bean)
} catch (e: HttpException) {
// println("e.message = ${e.message}")
......@@ -60,7 +64,7 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
suspend fun getBindCar(): MyResult<List<BindResult>> {
try {
// var body = RequestBodyUtil.toRequestBody(mapOf())
var bean = clientRetrofitMethod.getBindCar()
var bean = retrofitMethod.getBindCar()
return MyResult.Success(bean.result)
} catch (e: HttpException) {
// println("e.message = ${e.message}")
......@@ -70,24 +74,6 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
}
}
/**
* 获取AVP状态信息
* 我们车辆位姿数据用的是 车俩基础信息的id 可绑车辆接口 返回的是 avp车俩id
* 所以这里的id 是绑定车辆列表返回的id
*/
suspend fun getAvpStatus(): MyResult<AvpStatuBean> {
try {
var body = RequestBodyUtil.toRequestBody(mapOf("id" to 1))
var bean = clientRetrofitMethod.getAvpStatus(body)
return MyResult.Success(bean)
} catch (e: HttpException) {
// println("e.message = ${e.message}")
return MyResult.Error(e.code(), e.message() ?: "error")
} catch (e: Exception) {
return MyResult.Error(MyContants.HTTP_ERROR, e.message ?: "error")
}
}
/**登录***/
suspend fun login(user: String, pwd: String, verifyCode: Int): MyResult<String> {
......@@ -98,7 +84,7 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
var body = RequestBodyUtil.toRequestBody(map)
try {
var bean = clientRetrofitMethod.login(body)
var bean = retrofitMethod.login(body)
return MyResult.Success(bean.result.token)
} catch (e: HttpException) {
// println("e.message = ${e.message}")
......@@ -108,4 +94,30 @@ class AvpDataRepo @Inject constructor(private var clientRetrofitMethod: ClientRe
}
}
/**
* 获取AVP状态信息
* 我们车辆位姿数据用的是 车俩基础信息的id 可绑车辆接口 返回的是 avp车俩id
* 所以这里的id 是绑定车辆列表返回的id
*/
fun getAvpStatus(body: RequestBody?, listener: SSESimpleListener?) {
simpleSSEClient.startSSE(
"${MyContants.HOST}/api/avpweb/hmi/monitor/v1/taskStatus",
body, listener
)
}
/**获取车辆位姿****/
fun getCarPose(body: RequestBody?, listener: SSESimpleListener?) {
// try {
simpleSSEClient.startSSE(
"${MyContants.HOST}/api/avpweb/hmi/monitor/v1/monitorDrivenStatus",
body, listener
)
// } catch (e: HttpException) {
//// println("e.message = ${e.message}")
// } catch (e: Exception) {
// }
}
}
\ No newline at end of file
......@@ -62,10 +62,11 @@ class LoginActivity : AppCompatActivity() {
}
//获取可绑定车辆
private fun getBinderCars() {
mainVm.getBindCar().observe(this) { bindCars ->
var list = bindCars.map { it.plateNumber }
val dialog = CustomListDialog(this, "选择车辆", list)
var plateNumbers = bindCars.map { it.plateNumber }
val dialog = CustomListDialog(this, "选择车辆", plateNumbers)
dialog.setOnItemClickListener(object : CustomListDialog.OnItemClickListener {
override fun onItemClick(position: Int, selectedItem: String) {
// Toast.makeText(
......@@ -73,7 +74,7 @@ class LoginActivity : AppCompatActivity() {
// "点击了第${position + 1}项: $selectedItem",
// Toast.LENGTH_SHORT
// ).show()
// MyContants.VEHICLEID = list.get(position)
MyContants.VEHICLEID = bindCars.get(position).id
startActivity(Intent(this@LoginActivity, MainActivity::class.java))
finish()
}
......
......@@ -21,6 +21,7 @@ import com.sd.cavphmi.highmap.ParkStatu
import com.sd.cavphmi.highmap.Spinfo
import com.sd.cavphmi.highmap.UnityPtc
import com.sd.cavphmi.intfaces.OnConCan
import com.sd.cavphmi.net.SimpleSSEClient
import com.sd.cavphmi.ui.fragment.CarPanelFragment
import com.sd.cavphmi.ui.fragment.ExoPlayFragment
import com.sd.cavphmi.utils.DisplayUtil
......@@ -161,7 +162,7 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
//开启websocket
// mainVm.startWS()
//获取车位占用情况
getSpaceInfo()
// getSpaceInfo()
}
private fun getSpaceInfo() {
......@@ -229,8 +230,11 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
//联网车辆位姿数据
private fun getCarVehicle() {
mainVm.subVehicle().observe(this) { carBean ->
var car = carBean.first()
mainVm.subVehicle().observe(this) { car ->
// var car = carBean
if (car.vehiclePos == null)
return@observe
// setCarCamera(1)
//刷新右下角小车位置
mapOpt.showNavingCarPosition(car)
//刷新右下角小地图路径
......@@ -238,15 +242,31 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
// println("----car.heading ${car.heading}")
//刷新主车位置
HighMapApi.setCarPosition(
car.heading,
car.latitude,
car.longitude,
car.vehiclePos!!.get(2),
car.vehiclePos.get(1),
car.vehiclePos.get(0),
20.80189
// car.elevation
)
}
}
private var setCamera = false
//设置跟车视角
private fun setCarCamera(c: Int) {
if (setCamera)
return
if (c == 1) {
HighMapApi.setCameraAngle(30f)
HighMapApi.setCameraDistance(6f)
} else if (c == 2) {
HighMapApi.setCameraAngle(90f)
HighMapApi.setCameraDistance(80f)
}
setCamera = true
}
//联网车辆感知物
private fun getTarget() {
mainVm.subTarget().observe(this) {
......@@ -290,6 +310,8 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
//获取车辆详情,取车内摄像头地址打开左下角的车内视频
private fun getVehDetail() {
mainVm.getVehDetail().observe(this) { vehDetail ->
if (vehDetail.result.vehicleInfos.count() == 0)
return@observe
var cameraUrl = vehDetail.result.vehicleInfos?.get(0)?.vehicleVideoUrl
println("---cameraUrl = ${cameraUrl}")
if (exoPlayFragment.videoUrl.isNotEmpty())
......@@ -324,7 +346,6 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
}
//车位四周流光
binding.btParkround.setOnClickListener {
HighMapApi.setCameraAngle(75f)
lifecycleScope.launch {
......@@ -346,6 +367,9 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
}
//地锁绘制
binding.btLock.setOnClickListener {
//释放http资源
SimpleSSEClient.instance.cancelContect()
var lockStatu = LockStatu().apply {
code = "B021"
isHide = false
......
......@@ -98,15 +98,17 @@ class UnityFragment : Fragment(), IUnityPlayerLifecycleEvents {
mUnityPlayer.windowFocusChanged(true)
// mUnityPlayer.requestFocus()
//使用拼接服务器资源加载地图
mUnityPlayer.post {
unityMapVm.loadTileJson()
mUnityPlayer.postDelayed({
// try {
unityMapVm.loadTileJson()
HighMapApi.setCarBottomCircle(true)
// HighMapApi.setCameraAngle(90f)
// HighMapApi.setCameraDistance(80f)
HighMapApi.setCameraAngle(30f)
HighMapApi.setCameraDistance(6f)
// } catch (e: Exception) {
// }
}
},300)
}
......
package com.sd.cavphmi.ui.fragment
import android.graphics.Color
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.activity.viewModels
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.sd.cavphmi.BR
import com.sd.cavphmi.R
import com.sd.cavphmi.base.BaseFragment
import com.sd.cavphmi.base.MyBaseViewModel
import com.sd.cavphmi.bean.CarVehicle
import com.sd.cavphmi.bean.CarVehicleItem
import com.sd.cavphmi.bean.V2xStartBean
import com.sd.cavphmi.bean.WarningBean
import com.sd.cavphmi.databinding.FragmentCarPanelBinding
import com.sd.cavphmi.databinding.FragmentWarnBinding
import com.sd.cavphmi.viewmodels.MainVm
import com.sd.cavphmi.viewmodels.MockVM
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
......
......@@ -10,10 +10,10 @@ object MyContants {
//测试环境
// var HOST = "https://itg-dev.cu-sc.com:19443/"
//HTTP地址
var HOST = "https://172.24.124.130:19443"
const val HOST = "https://172.24.124.130:19443"
//智网生产环境地址用于拼接3dtile.json
var HOST_HTTP_3 = "https://itg-yz.cu-sc.com:13443"
var HOST_MAP = "https://itg-yz.cu-sc.com:13443"
// /***测试环境socket token***/
// private val WSTOKEN =
......@@ -36,15 +36,15 @@ object MyContants {
private var WSHOST = "wss://${BASE_HOST}/wsplus/socket?token=${HTTP_TOKEN}&reType=freedo&"
// if (IS_DEBUG) "wss://${BASE_HOST}/wsplus/socket?token=121&reType=freedo&" else "wss://${BASE_HOST}/wsplus/socket?token=121&reType=freedo&"
//车辆编号
var VEHICLEID = "27"
//车辆编号 27
var VEHICLEID = 27
/**网联车辆位姿 用于实车测试喽数据 &vehicleId=${VEHICLEID}***/
var WS_VEH_LOC = "${WSHOST}msgType=2&vehicleId=${VEHICLEID}"
/***感知目标物 &intersectionCode=17 停车场 不传就是整个园区***/
// var WS_FEEL_TARGET = "${WSHOST}msgType=1&intersectionCode=17"
var WS_FEEL_TARGET = "${WSHOST}msgType=1"
/***感知目标物 &intersectionCode=yz-15 停车场 不传就是整个园区***/
// var WS_FEEL_TARGET = "${WSHOST}msgType=1&intersectionCode=17 "
var WS_FEEL_TARGET = "${WSHOST}msgType=1&intersectionCode=yz-15"
/***V2X预警 VEHICLEID 传了就是获取某一辆车的预警 &vehicleId=${VEHICLEID}"=***/
var WS_V2X = "${WSHOST}msgType=4&vehicleId=${VEHICLEID}"
......
......@@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope
import com.sd.cavphmi.base.MyBaseViewModel
import com.sd.cavphmi.bean.CarPanelBean
import com.sd.cavphmi.bean.CarVehicle
import com.sd.cavphmi.bean.GearStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
......@@ -23,20 +22,20 @@ class CarPanelVM @Inject constructor() : MyBaseViewModel() {
/**展示车辆仪表*****/
fun setCarPanelBean(carVehicle: CarVehicle) {
// val vehicleInfo = event.vehicleInfo
if (carVehicle.count() == 0)
if (carVehicle.vehiclePos == null)
return
// val vehicleStatusInfo = event.vehicleStatusInfo
var bean = carVehicle.first()
// var bean = carVehicle.first()
//速度
carPanelBean.speed.set(bean.speed.toInt())
// carPanelBean.speed.set(bean.speed.toInt())
// //航向角
carPanelBean.heading.set(bean.heading.toInt())
carPanelBean.heading.set(carVehicle.vehiclePos.get(2).toInt())
//档位
carPanelBean.tapPos.set(bean.gear)
// carPanelBean.tapPos.set(bean.gear)
//驾驶模式
// carPanelBean.driveMode.set(vehicleInfo.driveMode.toInt())
//剩余电量
carPanelBean.remainSoc.set(bean.soc.toInt())
// carPanelBean.remainSoc.set(bean.soc.toInt())
//车灯状态
// carPanelBean.lights.set(vehicleStatusInfo?.lights)
// var a = 0
......
......@@ -27,6 +27,8 @@ import com.sd.cavphmi.highmap.Spinfo
import com.sd.cavphmi.highmap.WarnPtc
import com.sd.cavphmi.intfaces.OnWebSocketCb
import com.sd.cavphmi.net.MyResult
import com.sd.cavphmi.net.RequestBodyUtil
import com.sd.cavphmi.net.SimpleSSEClient
import com.sd.cavphmi.repositorys.AvpDataRepo
import com.sd.cavphmi.utils.FileIoUtils
import com.sd.cavphmi.utils.MyContants
......@@ -39,7 +41,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.net.URI
import javax.inject.Inject
......@@ -72,7 +73,7 @@ class MainVm @Inject constructor(
// private var vehStatuWSClient = VehStatuWSClient(URI(MyContants.WS_VEH_STATU))
//socket 管理
private var sockets = listOf(vecLocWSClient, feelTargetWSClient, v2xWSClient)
private var sockets = listOf(feelTargetWSClient, v2xWSClient)
//交通信号灯
// private var trafficLightWSClient: TrafficLightWSClient? = null
......@@ -124,10 +125,10 @@ class MainVm @Inject constructor(
/***清理资源***/
fun cleanRes() {
avpStatuJob?.cancel()
sockets.forEach {
it.close()
}
SimpleSSEClient.instance.cancelContect()
}
......@@ -135,16 +136,16 @@ class MainVm @Inject constructor(
fun getVehDetail(id: String = ""): LiveData<VehDetailBean> {
viewModelScope.launch {
// while (isActive) {
var result = avpDataRepo.getVehDetail(id)
when (result) {
is MyResult.Success<VehDetailBean> -> {
vehDetail.postValue(result.data)
}
var result = avpDataRepo.getVehDetail(id)
when (result) {
is MyResult.Success<VehDetailBean> -> {
vehDetail.postValue(result.data)
}
else -> {
}
else -> {
}
delay(2000)
}
delay(2000)
// }
}
return vehDetail
......@@ -170,29 +171,34 @@ class MainVm @Inject constructor(
return spaceInfo
}
//AVP咋混个太job
private var avpStatuJob: Job? = null
//HTTP获取AVP状态
fun getAvpStatus(): LiveData<AvpStatuBean> {
avpStatuJob = viewModelScope.launch {
while (isActive) {
var result = avpDataRepo.getAvpStatus()
when (result) {
is MyResult.Success<AvpStatuBean> -> {
var str = gson.toJson(result)
FileIoUtils.writeToFile(str, "avp_status.txt")
avpStatu.postValue(result.data)
}
if (isMock){
}else{
var body = RequestBodyUtil.toRequestBody(mapOf("id" to MyContants.VEHICLEID))
avpDataRepo.getAvpStatus(body, object : SimpleSSEClient.SSESimpleListener {
override fun onOpen() {
}
else -> {
override fun onEvent(data: String) {
viewModelScope.launch {
if (data.isNotEmpty()) {
println("-----AVP状态 = ${data}")
FileIoUtils.writeToFile(data, "avp_status.txt")
var result = gson.fromJson<AvpStatuBean>(data, AvpStatuBean::class.java)
avpStatu.postValue(result)
}
}
}
delay(2000)
}
}
avpStatuJob?.invokeOnCompletion {
override fun onError(throwable: Throwable) {
}
override fun onClosed() {
}
})
}
return avpStatu
}
......@@ -200,36 +206,35 @@ class MainVm @Inject constructor(
/**
* 联网车辆位姿数据
* 传入vehicleId 和url拼接代表某辆车的预警
* 用来控制主车移动
*/
fun subVehicle(): LiveData<CarVehicle> {
if (isMock) {
mockVM.onVehicleMock(carVehicle)
} else {
try {
vecLocWSClient.onWebSocketCb = object : OnWebSocketCb {
override fun onClose(code: Int, reason: String?, remote: Boolean) {
}
var body = RequestBodyUtil.toRequestBody(mapOf("id" to MyContants.VEHICLEID))
avpDataRepo.getCarPose(body, object : SimpleSSEClient.SSESimpleListener {
override fun onOpen() {
}
override fun onMsg(str: String) {
viewModelScope.launch {
//下载到sd卡下面的DownLoad文件夹下面
if (str.isNotEmpty()) {
FileIoUtils.writeToFile(str, "CarVehicle.txt")
}
var carBean = gson.fromJson(str, CarVehicle::class.java)
//更新主车位置
carVehicle.postValue(carBean)
override fun onEvent(data: String) {
viewModelScope.launch {
if (data.isNotEmpty()) {
println("-----车辆位姿 = ${data}")
FileIoUtils.writeToFile(data, "CarVehicle.txt")
var result = gson.fromJson<CarVehicle>(data, CarVehicle::class.java)
carVehicle.postValue(result)
}
}
}
if (!vecLocWSClient.isOpen) {
vecLocWSClient.connect()
override fun onError(throwable: Throwable) {
}
} catch (e: Exception) {
e.printStackTrace()
}
override fun onClosed() {
}
})
}
return carVehicle
}
......@@ -256,9 +261,9 @@ class MainVm @Inject constructor(
//下载到sd卡下面的DownLoad文件夹下面
if (str.isNotEmpty()) {
FileIoUtils.writeToFile(str, "PerTarget.txt")
var bean = gson.fromJson(str, PerceptionBean::class.java)
targetPre.postValue(bean)
}
var bean = gson.fromJson(str, PerceptionBean::class.java)
targetPre.postValue(bean)
}
}
}
......@@ -508,35 +513,36 @@ class MainVm @Inject constructor(
*/
/*** 交通信号灯**//*
fun subTrafficLight(): LiveData<TrafficLightBean> {
fun showVToTip() {
var imgs = VToXImgBean.imgs
ToastHelper.showCustViewShort(context, imgs.get("2")!!)
}
/*fun d1() {
try {
if (trafficLightWSClient == null) {
trafficLightWSClient = TrafficLightWSClient(URI(MyContants.WS_TRAFFIC_LIGHT))
trafficLightWSClient?.connect()
vecLocWSClient.onWebSocketCb = object : OnWebSocketCb {
override fun onClose(code: Int, reason: String?, remote: Boolean) {
}
trafficLightWSClient?.onDataCb = object : TrafficLightWSClient.OnDataCb {
override fun onMsg(str: String) {
viewModelScope.launch {
FileIoUtils.writeToFile(str, "traff_light.txt")
var bean = gson.fromJson(str, TrafficLightBean::class.java)
trafficLightBean.postValue(bean)
override fun onMsg(str: String) {
viewModelScope.launch {
//下载到sd卡下面的DownLoad文件夹下面
if (str.isNotEmpty()) {
FileIoUtils.writeToFile(str, "CarVehicle.txt")
}
var carBean = gson.fromJson(str, CarVehicle::class.java)
//更新主车位置
carVehicle.postValue(carBean)
}
}
}
if (!vecLocWSClient.isOpen) {
vecLocWSClient.connect()
}
} catch (e: Exception) {
e.printStackTrace()
}
return trafficLightBean
}*/
//显示气泡
fun showVToTip() {
var imgs = VToXImgBean.imgs
ToastHelper.showCustViewShort(context, imgs.get("2")!!)
}
}
\ No newline at end of file
......@@ -15,7 +15,7 @@ import com.minedata.minenavi.mapdal.LatLng
import com.minedata.minenavi.mapdal.NativeEnv
import com.minedata.minenavi.util.Tools
import com.sd.cavphmi.R
import com.sd.cavphmi.bean.CarVehicleItem
import com.sd.cavphmi.bean.CarVehicle
import com.sd.cavphmi.bean.DrivenDecision
import com.sd.cavphmi.bean.EndPoint
import com.sd.cavphmi.bean.Space
......@@ -100,10 +100,10 @@ class MapOpt @Inject constructor(
/**
* 刷新右下角小车位置
*/
fun showNavingCarPosition(carVehicleItem: CarVehicleItem) {
fun showNavingCarPosition(carVehicle: CarVehicle) {
synchronized(NativeEnv.SyncObject) {
var ndsLatLng = LatLng(carVehicleItem.latitude, carVehicleItem.longitude)
var heading = carVehicleItem.heading.toFloat()
var ndsLatLng = LatLng(carVehicle.vehiclePos!!.get(1), carVehicle.vehiclePos.get(0))
var heading = carVehicle.vehiclePos.get(2).toFloat()
//刷新小地图自车位置
if (mSmallMapCar != null) {
mSmallMapCar!!.orientAngle((heading + 40) % 360)
......@@ -132,12 +132,12 @@ class MapOpt @Inject constructor(
}
//更新小地图路径
fun upSmallMapLine(carVehicleItem: CarVehicleItem) {
fun upSmallMapLine(carVehicle: CarVehicle) {
deleteSmapLine()
viewModelScope.launch(Dispatchers.Default) {
if (coordinateSeries.count() > 0) {
//当前车辆位置
var latlng = LatLng(carVehicleItem.latitude, carVehicleItem.longitude)
var latlng = LatLng(carVehicle.vehiclePos!!.get(1), carVehicle.vehiclePos.get(0))
//投影计算结果
var result = Proj4jCoord.calculatePointProjection(
doubleArrayOf(latlng.latitude, latlng.longitude),
......
......@@ -19,14 +19,12 @@ import com.minedata.minenavi.mapdal.NdsPoint
import com.minedata.minenavi.util.Tools
import com.sd.cavphmi.R
import com.sd.cavphmi.bean.CarVehicle
import com.sd.cavphmi.bean.CarVehicleItem
import com.sd.cavphmi.bean.PerceptionBean
import com.sd.cavphmi.bean.V2xStartBean
import com.sd.cavphmi.bean.mock.MRoutes
import com.sd.cavphmi.bean.mock.ParkPath
import com.sd.cavphmi.highmap.AllLine
import com.sd.cavphmi.highmap.HighMapApi
import com.sd.cavphmi.highmap.LockStatu
import com.sd.cavphmi.highmap.ParkStatu
import com.sd.cavphmi.highmap.ReverCar
import com.sd.cavphmi.highmap.Spinfo
......@@ -68,7 +66,7 @@ class MockVM @Inject constructor(
) {
HighMapApi.setCameraAngle(30f)
viewModelScope.launch {
var cCar: CarVehicleItem? = null
var cCar: CarVehicle? = null
var gson = Gson()
var str =
......@@ -109,23 +107,24 @@ class MockVM @Inject constructor(
LatLng(pc[1], pc[0])
)
}
cCar = CarVehicleItem().apply {
cCar = CarVehicle().apply {
var temps=this.vehiclePos?.toMutableList()
if ((head - oldHead).absoluteValue < 45) {
this.heading = head
temps?.set(2,head)
}
latitude = it[1]
longitude = it[0]
temps?.set(0,it[0])
temps?.set(1,it[1])
// latitude = it[1]
// longitude = it[0]
}
oldHead = head
var carV = CarVehicle().apply {
add(cCar)
}
//更新主车位置
carVehicle.value = carV
carVehicle.value = cCar
//更新小地图小车
showNavingCarPosition(
Tools.latLngToNdsPoint(LatLng(cCar.latitude, cCar.longitude)),
cCar.heading.toFloat()
Tools.latLngToNdsPoint(LatLng(cCar.vehiclePos!!.get(1), cCar.vehiclePos.get(0))),
cCar.vehiclePos.get(2).toFloat()
)
//更新小地图路径
upSmallLine(index, mRoutes)
......@@ -152,20 +151,21 @@ class MockVM @Inject constructor(
//前进
var forword = parkPath.result.routes.find { it.gear == 3 }
forword?.polyline?.forEach { poly ->
cCar = CarVehicleItem().apply {
latitude = poly.get(1)
longitude = poly.get(0)
heading = poly.get(3)
}
var carV = CarVehicle().apply {
add(cCar)
cCar = CarVehicle().apply {
var temps=this.vehiclePos?.toMutableList()
temps?.set(0,poly.get(0))
temps?.set(1,poly.get(1))
temps?.set(2,poly.get(3))
// latitude = poly.get(1)
// longitude = poly.get(0)
// heading = poly.get(3)
}
//更新主车位置
carVehicle.value = carV
carVehicle.value = cCar
//更新小地图小车
showNavingCarPosition(
Tools.latLngToNdsPoint(LatLng(cCar.latitude, cCar.longitude)),
cCar.heading.toFloat()
Tools.latLngToNdsPoint(LatLng(cCar.vehiclePos!!.get(1), cCar.vehiclePos.get(0))),
cCar.vehiclePos.get(2).toFloat()
)
delay(300)
}
......@@ -182,20 +182,18 @@ class MockVM @Inject constructor(
//开始后退
var fBack = parkPath.result.routes.find { it.gear == 1 }
fBack?.polyline?.forEach { poly ->
cCar = CarVehicleItem().apply {
latitude = poly.get(1)
longitude = poly.get(0)
heading = poly.get(3)
}
var carV = CarVehicle().apply {
add(cCar)
cCar = CarVehicle().apply {
var temps=this.vehiclePos?.toMutableList()
temps?.set(0,poly.get(0))
temps?.set(1,poly.get(1))
temps?.set(2,poly.get(3))
}
//更新主车位置
carVehicle.value = carV
carVehicle.value = cCar
//更新小地图小车
showNavingCarPosition(
Tools.latLngToNdsPoint(LatLng(cCar.latitude, cCar.longitude)),
cCar.heading.toFloat()
Tools.latLngToNdsPoint(LatLng(cCar.vehiclePos!!.get(1), cCar.vehiclePos.get(0))),
cCar.vehiclePos!!.get(1).toFloat()
)
delay(300)
}
......
......@@ -41,13 +41,11 @@ class FeelTargetWSClient : BaseWsClient {
}
override fun onMessage(message: String?) {
println(TAG + " : " + message)
// println(TAG + " : " + message)
if (message.isNullOrEmpty())
return
onWebSocketCb?.onMsg(message)
// onDataCb?.onMsg(message)
// onSocketCb?.onMessage(message)
}
override fun onMessage(bytes: ByteBuffer?) {
......@@ -57,7 +55,7 @@ class FeelTargetWSClient : BaseWsClient {
override fun onClose(code: Int, reason: String?, remote: Boolean) {
System.out.println(TAG + " closed with exit code " + code + " additional info: " + reason);
onWebSocketCb?.onClose(code, reason, remote)
}
override fun onError(ex: Exception?) {
......
......@@ -48,7 +48,6 @@ class V2xWSClient : BaseWsClient {
override fun onError(ex: Exception?) {
// System.err.println(TAG + "an error occurred:" + ex)
}
// var onDataCb: OnDataCb? = null
......
......@@ -123,12 +123,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="车位占用情况"
android:visibility="visible" />
android:visibility="gone" />
<Button
android:id="@+id/bt_avpstatu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
android:text="获取AVP状态信息"
/>
<Button
......@@ -136,6 +137,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取可绑车辆列表"
android:visibility="visible"
/>
<Button
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment