Qualcomm 远程信息处理 SDK - 用户指南(7)

281 篇文章 30 订阅
150 篇文章 17 订阅
该文档是Qualcomm的C-V2X远程信息处理SDK的用户指南,详细介绍了如何接收和传输C-V2X数据,设置验证负载以及拨打电话(包括普通语音和紧急电话)。用户需要创建回调方法,获取C-V2X状态,初始化无线电并处理数据收发。同时,文档还涵盖了油门管理器的使用,包括设置过滤率通知和监听器注册。
摘要由CSDN通过智能技术生成


4.2.2 接收数据

此示例应用程序演示了如何使用 C-V2X 无线电管理器 API 接收 C-V2X 数据。

  1. 为 ICv2xRadio 和 ICv2xRadioManager 方法创建回调方法
static Cv2xStatus gCv2xStatus;
static promise<ErrorCode> gCallbackPromise;
static shared_ptr<ICv2xRxSubscription> gRxSub;
static uint32_t gPacketsReceived = 0u;
static array<char, G_BUF_LEN> gBuf;
// Resets the global callback promise
static inline void resetCallbackPromise(void) {
    gCallbackPromise = promise<ErrorCode>();
}
// Callback method for Cv2xRadioManager->requestCv2xStatus()
static void cv2xStatusCallback(Cv2xStatus status, ErrorCode error) {
    if (ErrorCode::SUCCESS == error) {
        gCv2xStatus = status;
    }
    gCallbackPromise.set_value(error);
}
// Callback method for Cv2xRadio->createRxSubscription() and Cv2xRadio->closeRxSubscription()
static void rxSubCallback(shared_ptr<ICv2xRxSubscription> rxSub, ErrorCode error) {
    if (ErrorCode::SUCCESS == error) {
        gRxSub = rxSub;
    }
    gCallbackPromise.set_value(error);
}

注意:我们还可以使用 Lambda 函数而不是定义全局范围回调。

  1. 获取 ICv2xRadioManager 实例的句柄
auto & cv2xFactory = Cv2xFactory::getInstance();
auto cv2xRadioManager = cv2xFactory.getCv2xRadioManager();
  1. 请求C-V2X状态
    在尝试接收任何数据之前,我们希望验证 C-V2X RX 状态是否为“ACTIVE”。
// Get C-V2X status and make sure Rx is enabled
assert(Status::SUCCESS == cv2xRadioManager->requestCv2xStatus(cv2xStatusCallback));
assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());
if (Cv2xStatusType::ACTIVE == gCv2xStatus.rxStatus) {
    cout << "C-V2X RX status is active" << endl;
}
else {
    cerr << "C-V2X RX is inactive" << endl;
    return EXIT_FAILURE;
}
  1. 获取 C-V2X 无线电的句柄
auto cv2xRadio = cv2xRadioManager->getCv2xRadio(TrafficCategory::SAFETY_TYPE);

5.等待C-V2X无线电准备就绪

if (not cv2xRadio->isReady()) {
    if (Status::SUCCESS == cv2xRadio->onReady().get()) {
        cout << "C-V2X Radio is ready" << endl;
    }
    else {
        cerr << "C-V2X Radio initialization failed." << endl;
        return EXIT_FAILURE;
    }
}
  1. 创建RX订阅并使用RX套接字接收数据
resetCallbackPromise();
assert(Status::SUCCESS == cv2xRadio->createRxSubscription(TrafficIpType::TRAFFIC_NON_IP,
                                                          RX_PORT_NUM,
                                                          rxSubCallback));
assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());
// Read from the RX socket in a loop
for (uint32_t i = 0; i < NUM_TEST_ITERATIONS; ++i) {
    // Receive from RX socket
    sampleRx();
}
  1. 关闭RX订阅
    我们在此示例中提供回调并检查其状态,但请注意它是可选的。
resetCallbackPromise();
assert(Status::SUCCESS == cv2xRadio->closeRxSubscription(gRxSub,
                                                         rxSubCallback));
assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());

4.2.3 传输数据

此示例应用程序演示了如何使用 C-V2X 无线电管理器 API 发送 C-V2X 数据。

  1. 为 ICv2xRadio 和 ICv2xRadioManager 方法创建回调方法
static Cv2xStatus gCv2xStatus;
static promise<ErrorCode> gCallbackPromise;
static shared_ptr<ICv2xTxFlow> gSpsFlow;
static array<char, G_BUF_LEN> gBuf;
// Resets the global callback promise
static inline void resetCallbackPromise(void) {
    gCallbackPromise = promise<ErrorCode>();
}
// Callback method for ICv2xRadioManager->requestCv2xStatus()
static void cv2xStatusCallback(Cv2xStatus status, ErrorCode error) {
    if (ErrorCode::SUCCESS == error) {
        gCv2xStatus = status;
    }
    gCallbackPromise.set_value(error);
}
// Callback method for ICv2xRadio->createTxSpsFlow()
static void createSpsFlowCallback(shared_ptr<ICv2xTxFlow> txSpsFlow,
                                  shared_ptr<ICv2xTxFlow> unusedFlow,
                                  ErrorCode spsError,
                                  ErrorCode unusedError) {
    if (ErrorCode::SUCCESS == spsError) {
        gSpsFlow = txSpsFlow;
    }
    gCallbackPromise.set_value(spsError);
}
// Callback for ICv2xRadio->closeTxFlow()
static void closeFlowCallback(shared_ptr<ICv2xTxFlow> flow, ErrorCode error) {
    gCallbackPromise.set_value(error);
}

注意:我们还可以使用 Lambda 函数而不是定义全局范围回调。

  1. 获取 ICv2xRadioManager 实例的句柄
// Get handle to Cv2xRadioManager
auto & cv2xFactory = Cv2xFactory::getInstance();
auto cv2xRadioManager = cv2xFactory.getCv2xRadioManager();
  1. 请求C-V2X状态
    在尝试发送数据之前,我们希望验证 C-V2X TX 状态是否为 ACTIVE。
// Get C-V2X status and make sure Tx is enabled
assert(Status::SUCCESS == cv2xRadioManager->requestCv2xStatus(cv2xStatusCallback));
assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());
if (Cv2xStatusType::ACTIVE == gCv2xStatus.txStatus) {
    cout << "C-V2X TX status is active" << endl;
}
else {
    cerr << "C-V2X TX is inactive" << endl;
    return EXIT_FAILURE;
}
  1. 获取 C-V2X 无线电的句柄
auto cv2xRadio = cv2xRadioManager->getCv2xRadio(TrafficCategory::SAFETY_TYPE);

5.等待C-V2X无线电准备就绪

if (not cv2xRadio->isReady()) {
    if (Status::SUCCESS == cv2xRadio->onReady().get()) {
        cout << "C-V2X Radio is ready" << endl;
    }
    else {
        cerr << "C-V2X Radio initialization failed." << endl;
        return EXIT_FAILURE;
    }
}
  1. 创建TX SPS流并使用TX套接字发送数据
// Set SPS parameters
SpsFlowInfo spsInfo;
spsInfo.priority = Priority::PRIORITY_2;
spsInfo.periodicity = Periodicity::PERIODICITY_100MS;
spsInfo.nbytesReserved = G_BUF_LEN;
spsInfo.autoRetransEnabledValid = true;
spsInfo.autoRetransEnabled = true;
// Create new SPS flow
resetCallbackPromise();
assert(Status::SUCCESS == cv2xRadio->createTxSpsFlow(TrafficIpType::TRAFFIC_NON_IP,
                                                     SPS_SERVICE_ID,
                                                     spsInfo,
                                                     SPS_SRC_PORT_NUM,
                                                     false,
                                                     0,
                                                     createSpsFlowCallback));
 assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());
 // Send message in a loop
 for (uint16_t i = 0; i < NUM_TEST_ITERATIONS; ++i) {
     fillBuffer();
     sampleSpsTx();
     usleep(100000u);
 }
  1. 关闭TX SPS流程
// Deregister SPS flow
resetCallbackPromise();
assert(Status::SUCCESS == cv2xRadio->closeTxFlow(gSpsFlow, closeFlowCallback));
assert(ErrorCode::SUCCESS == gCallbackPromise.get_future().get());

4.2.4 设置验证负载

此示例应用程序演示了如何使用 C-V2X 无线电管理器 API 来设置验证负载。

1.创建验证加载回调方法

static std::promise<telux::common::ErrorCode> gCallbackPromise;
// Callback method for Cv2xThrottleManager->setVerificationLoad()
static void cv2xsetVerificationLoadCallback(telux::common::ErrorCode error) {
    std::cout << "error=" << static_cast<int>(error) << std::endl;
    gCallbackPromise.set_value(error);
}

2.创建初始化状态回调方法

bool cv2xTmStatusUpdated = false;
telux::common::ServiceStatus cv2xTmStatus =
     telux::common::ServiceStatus::SERVICE_UNAVAILABLE;
std::condition_variable cv;
std::mutex mtx;
auto statusCb = [&](telux::common::ServiceStatus status) {
     std::lock_guard<std::mutex> lock(mtx);
     cv2xTmStatusUpdated = true;
     cv2xTmStatus = status;
     cv.notify_all();
};
  1. 获取 ICv2xThrottleManager 实例的句柄
// Get handle to Cv2xThrottleManager
auto & cv2xFactory = Cv2xFactory::getInstance();
auto cv2xThrottleManager = cv2xFactory.getCv2xThrottleManager(statusCb);

4.等待油门管理器完成初始化

std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&] { return cv2xTmStatusUpdated; });
if (telux::common::ServiceStatus::SERVICE_AVAILABLE !=
    cv2xTmStatus) {
    std::cout << "Error: failed to initialize Cv2xThrottleManager." << std::endl;
    return EXIT_FAILURE;
}
  1. 设置验证负载
cv2xThrottleManager->setVerificationLoad(load, cv2xsetVerificationLoadCallback);
if (telux::common::ErrorCode::SUCCESS != gCallbackPromise.get_future().get()) {
     std::cout << "Error : failed to set verification load" << std::endl;
     return EXIT_FAILURE;
 } else {
     std::cout << "set verification load success" << std::endl;
 }
 gCallbackPromise = std::promise<telux::common::ErrorCode>();

4.2.5 获取调整过滤率通知

此示例应用程序演示了如何通知客户端调整传入消息过滤率。

  1. 实现ICv2xThrottleManagerListener接口
class Cv2xTmListener : public ICv2xThrottleManagerListener {
    public:
        void onFilterRateAdjustment(int rate) override;
 };

2.创建初始化状态回调方法

bool cv2xTmStatusUpdated = false;
telux::common::ServiceStatus cv2xTmStatus =
    telux::common::ServiceStatus::SERVICE_UNAVAILABLE;
std::condition_variable cv;
std::mutex mtx;
std::cout << "Running TM app" << std::endl;
auto statusCb = [&](telux::common::ServiceStatus status) {
    std::lock_guard<std::mutex> lock(mtx);
    cv2xTmStatusUpdated = true;
    cv2xTmStatus = status;
    cv.notify_all();
};
  1. 获取 ICv2xThrottleManager 对象的句柄
// Get handle to Cv2xThrottleManager
auto & cv2xFactory = Cv2xFactory::getInstance();
auto cv2xThrottleManager = cv2xFactory.getCv2xThrottleManager(statusCb);

4.等待油门管理器完成初始化

std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&] { return cv2xTmStatusUpdated; });
if (telux::common::ServiceStatus::SERVICE_AVAILABLE !=
    cv2xTmStatus) {
    std::cout << "Error: failed to initialize Cv2xThrottleManager." << std::endl;
    return EXIT_FAILURE;
}

5.实例化Cv2xTmListener

auto listener = std::make_shared<Cv2xTmListener>();

6.注册监听器

if (cv2xThrottleManager->registerListener(listener) !=
    telux::common::Status::SUCCESS) {
    std::cout << "Failed to register listener" << std::endl;
    return EXIT_FAILURE;
}

7.等待过滤率调整通知

void Cv2xTmListener::onFilterRateAdjustment(int rate) {
     std::cout << "Updated rate: " << rate << std::endl;
}

4.3 电话

4.3.1 拨打语音电话

此示例应用程序演示了如何进行语音呼叫。

  1. 实现ResponseCallback接口接收子系统初始化状态
std::promise<telux::common::ServiceStatus> cbProm = std::promise<telux::common::ServiceStatus>();
void initResponseCb(telux::common::ServiceStatus status) {
   if(subSystemsStatus == SERVICE_AVAILABLE) {
      std::cout << Call Manager subsystem is ready << std::endl;
   } else if(subSystemsStatus == SERVICE_FAILED) {
      std::cout << Call Manager subsystem initialization failed << std::endl;
   }
   cbProm.set_value(status);
}
  1. 获取PhoneFactory和Call Manager实例
auto &phoneFactory = PhoneFactory::getInstance();
auto callManager = phoneFactory.getCallManager(initResponseCb);
if(callManager == NULL) {
   std::cout << " Failed to get Call Manager instance" << std::endl;
   return -1;
}
  1. 等待呼叫管理器子系统准备就绪
telux::common::ServiceStatus status = cbProm.get_future().get();
if(status != SERVICE_AVAILABLE) {
   std::cout << Unable to initialize Call Manager subsystem << std::endl;
   return -1;
}
  1. (可选)实现 IMakeCallCallback 接口以接收拨号请求的响应
class DialCallback : public IMakeCallCallback {
public:
   void DialCallback::makeCallResponse(ErrorCode error, std::shared_ptr<ICall> call) {
      // will be invoked with response of makeCall operation
   }
};
std::shared_ptr<DialCallback> dialCb = std::make_shared<DialCallback> ();
5. Send a dial request
  1. 发送拨号请求
if(callManager) {
   std::string phoneNumber("+18989531755");
   int phoneId = 1;
   auto makeCallStatus = callManager->makeCall(phoneId, phoneNumber, dialCb);
   std::cout << "Dial Call Status:" << (int)makeCallStatus << std::endl;
}

4.3.2 拨打紧急电话

此示例应用程序演示了如何拨打紧急 (E112) 语音呼叫。

  1. 实现ResponseCallback接口接收子系统初始化状态
std::promise<telux::common::ServiceStatus> cbProm = std::promise<telux::common::ServiceStatus>();
void initResponseCb(telux::common::ServiceStatus status) {
   if(subSystemsStatus == SERVICE_AVAILABLE) {
      std::cout << Call Manager subsystem is ready << std::endl;
   } else if(subSystemsStatus == SERVICE_FAILED) {
      std::cout << Call Manager subsystem initialization failed << std::endl;
   }
   cbProm.set_value(status);
}
  1. 获取PhoneFactory和Call Manager实例
auto &phoneFactory = PhoneFactory::getInstance();
auto callManager = phoneFactory.getCallManager(initResponseCb);
if(callManager == NULL) {
   std::cout << " Failed to get Call Manager instance" << std::endl;
   return -1;
}
  1. 等待呼叫管理器子系统准备就绪
telux::common::ServiceStatus status = cbProm.get_future().get();
if(status != SERVICE_AVAILABLE) {
   std::cout << Unable to initialize Call Manager subsystem << std::endl;
   return -1;
}
  1. (可选)实现 IMakeCallCallback 接口以接收拨号请求的响应
class DialCallback : public IMakeCallCallback {
public:
   void DialCallback::makeCallResponse(ErrorCode error, std::shared_ptr<ICall> call) {
      // will be invoked with response of makeCall operation
   }
};
std::shared_ptr<DialCallback> dialCb = std::make_shared<DialCallback> ();
  1. 初始化eCall所需的数据,如eCallMsdData、emergencyCategory和eCallVariant
ECallCategory emergencyCategory = ECallCategory::VOICE_EMER_CAT_AUTO_ECALL;
ECallVariant eCallVariant = ECallVariant::ECALL_TEST;
// Instantiate ECallMsdData structure and populate it with valid information
// such as Latitude, Longitude etc.
// Parameter values mentioned here are for illustrative purposes only.
ECallMsdData eCallMsdData;
eCallMsdData.msdData.msdVersion = 2;
eCallMsdData.msdData.messageIdentifier = 1; // Each MSD message should bear a unique id
eCallMsdData.optionals.recentVehicleLocationN1Present = true;
eCallMsdData.optionals.recentVehicleLocationN2Present = true;
eCallMsdData.optionals.numberOfPassengersPresent = 2;
eCallMsdData.msdData.control.automaticAvtivation = true;
eCallMsdData.control.testCall = true;
eCallMsdData.control.positionCanBeTrusted = true;
eCallMsdData.control.vehicleType = ECallVehicleType::PASSENGER_VEHICLE_CLASS_M1;
eCallMsdData.msdData.vehicleIdentificationNumber.isowmi = "ECA";
eCallMsdData.msdData.vehicleIdentificationNumber.isovds = "LLEXAM";
eCallMsdData.msdData.vehicleIdentificationNumber.isovisModelyear = "P";
eCallMsdData.msdData.vehicleIdentificationNumber.isovisSeqPlant = "LE02013";
eCallMsdData.msdData.vehiclePropulsionStorage.gasolineTankPresent = true;
eCallMsdData.msdData.vehiclePropulsionStorage.dieselTankPresent = false;
eCallMsdData.vehiclePropulsionStorage.compressedNaturalGas = false;
eCallMsdData.vehiclePropulsionStorage.liquidPropaneGas = false;
eCallMsdData.vehiclePropulsionStorage.electricEnergyStorage = false;
eCallMsdData.vehiclePropulsionStorage.hydrogenStorage = false;
eCallMsdData.vehiclePropulsionStorage.otherStorage = false;
eCallMsdData.timestamp = 1367878452;
eCallMsdData.vehicleLocation.positionLatitude = 123;
eCallMsdData.vehicleLocation.positionLongitude = 1234;
eCallMsdData.msdData.vehicleDirection = 4;
eCallMsdData.recentVehicleLocationN1.latitudeDelta = false;
eCallMsdData.recentVehicleLocationN1.longitudeDelta = 0;
eCallMsdData.recentVehicleLocationN2.latitudeDelta = true;
eCallMsdData.recentVehicleLocationN2.longitudeDelta = 0;
  1. 发送 eCall 请求
int phoneId = 1;
if(callManager) {
   auto makeCallStatus = callManager->makeECall(phoneId, eCallMsdData, emergencyCategory,
                                                eCallVariant, dialCb);
   std::cout << "Dial ECall Status:" << (int)makeCallStatus << std::endl;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值