Qualcomm 远程信息处理 SDK - 用户指南(9)
4.3.9 使用 SAP API
此示例应用程序演示了如何使用 SAP API 传输 APDU 并侦听 SAP 事件。
- 获取PhoneFactory和PhoneManager实例
auto &phoneFactory = PhoneFactory::getInstance();
auto phoneManager = phoneFactory.getPhoneManager();
- 等待电话子系统初始化
bool subSystemsStatus = cardManager->isSubsystemReady();
if(!subSystemsStatus) {
std::cout << "Telephony subsystem is not ready, wait for it to be ready " << std::endl;
std::future<bool> f = cardManager->onSubsystemReady();
auto status = f.wait_for(std::chrono::seconds(5));
if(status == std::future_status::ready) {
subSystemsStatus = true;
}
}
- 获取默认SAP Card Manager实例
std::shared_ptr<ISapCardManager> sapCardMgr = phoneFactory.getSapCardManager();
4.实例化ICommandResponseCallback、IAtrResponseCallback和ISapCardCommandCallback
auto mySapCmdResponseCb = std::make_shared<MySapCommandResponseCallback>();
auto myAtrCb = std::make_shared<MyAtrResponseCallback>();
auto myTransmitApduResponseCb = std::make_shared<MySapTransmitApduResponseCallback>();
4.1 实现 ICommandResponseCallback 接口,用于接收 SAP 事件(如打开连接和关闭连接)的通知
class MySapCommandResponseCallback : public ICommandResponseCallback {
public:
void commandResponse(ErrorCode error);
};
void MySapCommandResponseCallback::commandResponse(ErrorCode error) {
std::cout << "commandResponse, error: " << (int)error << std::endl;
}
4.2 实现 IAtrResponseCallback 接口,用于接收 SAP 事件的通知,例如重置请求应答 (ATR)
class MyAtrResponseCallback : public IAtrResponseCallback {
public:
void atrResponse(std::vector<int> responseAtr, ErrorCode error);
};
void MyAtrResponseCallback::atrResponse(std::vector<int> responseAtr, ErrorCode error) {
std::cout << "atrResponse, error: " << (int)error << std::endl;
}
4.3 ISapCardCommandCallback 接口的实现,用于接收 SAP 事件(如传输 apdu)的通知
class MySapTransmitApduResponseCallback : public ISapCardCommandCallback {
public:
void onResponse(IccResult result, ErrorCode error);
};
void MySapTransmitApduResponseCallback::onResponse(IccResult result, ErrorCode error) {
std::cout << "transmitApduResponse, error: " << (int)error << std::endl;
}
5.打开SAP连接并等待请求完成
sapCardMgr->openConnection(SapCondition::SAP_CONDITION_BLOCK_VOICE_OR_DATA, mySapCmdResponseCb);
std::cout << "Opening SAP connection to Transmit the APDU..." << std::endl;
6.请求SAP ATR并等待完成
sapCardMgr->requestAtr(myAtrCb);
7.发送SAP APDU并等待请求完成
std::cout << "Transmit Sap APDU request made..." << std::endl;
Status ret = sapCardMgr->transmitApdu(CLA, INSTRUCTION, P1, P2, LC, DATA, 0,
myTransmitApduResponseCb);
8.关闭SAP连接并等待请求完成
sapCardMgr->closeConnection(mySapCmdResponseCb);
4.3.10 请求网络选择模式
此示例应用程序演示了如何请求当前网络选择模式。
- 获取手机工厂和网络选择管理器实例
auto &phoneFactory = telux::tel::PhoneFactory::getInstance();
auto networkMgr
= phoneFactory.getNetworkSelectionManager(DEFAULT_SLOT_ID);
2.等待网络选择子系统初始化
bool subSystemStatus = networkMgr->isSubsystemReady();
2.1 如果网络选择子系统未准备好,则等待其准备好
if(!subSystemStatus) {
std::cout << "network selection subsystem is not ready" << std::endl;
std::cout << "wait unconditionally for it to be ready " << std::endl;
std::future<bool> f = networkMgr->onSubsystemReady();
// If we want to wait unconditionally for network selection subsystem to be ready
subSystemStatus = f.get();
}
- 如果网络选择子系统无法初始化,则退出应用程序
if(subSystemsStatus) {
std::cout << " *** Network selection subsystem ready *** " << std::endl;
} else {
std::cout << " *** ERROR - Unable to initialize network selection subsystem" << std::endl;
return 1;
}
- 实现响应回调,接收请求网络选择模式的响应
class SelectionModeResponseCallback {
public:
void selectionModeResponse(
telux::tel::NetworkSelectionMode networkSelectionMode,
telux::common::ErrorCode errorCode) {
if(errorCode == telux::common::ErrorCode::SUCCESS) {
std::cout << "Network selection mode: "
<< static_cast<int>(networkSelectionMode)
<< std::endl;
} else {
std::cout << "\n requestNetworkSelectionMode failed, ErrorCode: "
<< static_cast<int>(errorCode)
<< std::endl;
}
}
};
- 发送 requestNetworkSelectionMode 以及响应回调
if(networkMgr) {
auto status = networkMgr->requestNetworkSelectionMode(
SelectionModeResponseCallback::selectionModeResponse);
std::cout << static_cast<int>(status) <<std::endl;
}
}
现在,将使用当前网络选择模式信息调用 SelectionModeResponse() 回调。
4.3.11 使用远程 SIM 管理器 API
此示例应用程序演示了如何使用远程 SIM 管理器 API 进行远程 SIM 卡操作。
- 获取PhoneFactory和RemoteSimManager实例
#include <telux/tel/PhoneFactory.hpp>
using namespace telux::common;
using namespace telux::tel;
PhoneFactory &phoneFactory = PhoneFactory::getInstance();
std::shared_ptr<IRemoteSimManager> remoteSimMgr =
phoneFactory.getRemoteSimManager(DEFAULT_SLOT_ID);
2.实例化并注册RemoteSimListener
std::shared_ptr<IRemoteSimListener> listener = std::make_shared<RemoteSimListener>();
remoteSimMgr.registerListener(listener);
2.1 接收Remote SIM通知的IRemoteSimListener接口的实现
class RemoteSimListener : public IRemoteSimListener {
public:
void onApduTransfer(const unsigned int id, const std::vector<uint8_t> &apdu) override {
// Send APDU to SIM card
}
void onCardConnect() override {
// Connect to SIM card and request AtR
}
void onCardDisconnect() override {
// Disconnect from SIM card
}
void onCardPowerUp() override {
// Power up SIM card and request AtR
}
void onCardPowerDown() override {
// Power down SIM card
}
void onCardReset() override {
// Reset SIM card
}
void onServiceStatusChange(ServiceStatus status) {
// Handle case where modem goes down or comes up
}
};
2.2 异步请求的事件回调实现
void eventCallback(ErrorCode errorCode) {
std::cout << "Received event response with errorcode " << static_cast<int>(errorCode)
<< std::endl;
}
3.等待远程SIM子系统初始化
int timeoutSec = 5;
if (!(remoteSimMgr->isSubsystemReady())) {
auto f = remoteSimMgr->onSubsystemReady();
if (f.wait_for(std::chrono::seconds(timeoutSec)) != std::future_status::ready) {
std::cout << "Remote SIM subsystem did not initialize!" << std::endl;
}
}
- 发送连接可用事件请求
当远程卡可用并准备就绪时,通过发送连接可用请求使其可供调制解调器使用。
if (remoteSimMgr->sendConnectionAvailable(eventCallback) != Status::SUCCESS) {
std::cout << "Failed to send connection available request!" << std::endl;
}
- 收到监听器的 onCardConnect() 通知后发送卡重置请求
当调制解调器接受连接时,您将在侦听器上收到 onCardConnect 通知。
// After connecting to SIM card, requesting AtR, and receiving response with AtR bytes
if (remoteSimMgr->sendCardReset(atr, eventCallback) != Status::SUCCESS) {
std::cout << "Failed to send card reset request!" << std::endl;
}
- 收到监听器的onTransmitApdu()通知后发送响应APDU
// After sending command APDU to SIM and receiving the response
if (remoteSimMgr->sendApdu(id, apdu, true, apdu.size(), 0, eventCallback) != Status::SUCCESS) {
std::cout << "Failed to send response APDU!" << std::endl;
}
7.退出前发送连接不可用请求
当卡变得不可用时(或在退出之前),请断开与调制解调器的连接。
if (remoteSimMgr->sendConnectionUnavailable() != Status::SUCCESS) {
std::cout << "Failed to send connection unavailable request!" << std::endl;
}
4.3.12 使用远程 SIM 参考应用程序
本节介绍如何使用提供的远程 SIM 参考应用程序 – Remote-sim-daemon 和 sap-card-provider。Remote-sim-daemon 应用程序将在没有 SIM 卡的设备上运行,而 sap-card-provider 应用程序将在有 SIM 卡的设备上运行。这两个应用程序将通过标准 IP 以太网连接进行通信,为无需插入 SIM 卡的设备提供远程 SIM 卡的 WWAN 功能。两个设备都需要支持 Telematics SDK 并通过以太网相互连接。
所需物品
假设两台设备都配置为启用必要的功能来支持远程 SIM 功能。
- 设置以太网连接
首先,需要建立两个设备之间的连接。
1.1 禁用自动配置IP地址
根据设备类型,可能需要首先禁用两台设备上的自动配置 IP (169.254.xx) 地址。
brctl delif bridge0 eth0
1.2 配置两台设备的IP地址
ifconfig eth0 192.168.1.2
具有 SIM 卡的设备可以使用 192.168.1.3。
注意:根据设备的不同,由于自动配置设置,每当设备重新启动或断开连接时,可能需要再次执行步骤 1.1 和 1.2。
- 在没有 SIM 的设备上在后台运行远程 SIM 守护程序
remote-sim-daemon &
-d 和 -s 标志也可用于调试目的(使用 -h 来获取使用说明)。
- 在具有 SIM 卡的设备上运行 Sap Card Provider
sap-card-provider -i 192.168.1.2
使用 -i 标志提供运行remote-sim-daemon 的设备的IP 地址。-d 和 -s 标志也可用于调试目的(使用 -h 来获取使用说明)。
4.3.13 发送短信
此示例应用程序演示了如何向手机号码指定的给定手机发送短信。
- 获取PhoneFactory和PhoneManager实例
auto &phoneFactory = PhoneFactory::getInstance();
auto phoneManager = phoneFactory.getPhoneManager();
- 检查电话子系统是否准备就绪
bool subSystemsStatus = phoneManager->isSubsystemReady();
2.1 如果电话子系统未准备好,则等待其准备好
电话子系统用于确保设备准备好使用电话、短信等服务。如果子系统没有准备好,则无条件等待。
if(!subSystemsStatus) {
std::future<bool> f = phoneManager->onSubsystemReady();
subSystemsStatus = f.get();
}
3.实例化短信发送和投递回调
auto smsSentCb = std::make_shared<SmsCallback>();
auto smsDeliveryCb = std::make_shared<SmsDeliveryCallback>();
3.1 实现ICommandResponseCallback接口,了解短信发送及送达状态
class SmsCallback : public ICommandResponseCallback {
public:
void commandResponse(ErrorCode error) override;
};
void SmsCallback::commandResponse(ErrorCode error) {
std::cout << "onSmsSent callback" << std::endl;
}
class SmsDeliveryCallback : public ICommandResponseCallback {
public:
void commandResponse(ErrorCode error) override;
};
void SmsDeliveryCallback::commandResponse(ErrorCode error) {
std::cout << "SMS Delivery callback" << std::endl;
}
- 获取默认短信管理器实例
std::shared_ptr<ISmsManager> smsManager = phoneFactory.getSmsManager();
- 使用 ISmsManager 发送短信,传递文本和接收者号码以及所需的回调
if(smsManager) {
std::string receiverAddress("+18989531755");
std::string message("TEST message");
smsManager->sendSms(message, receiverAddress, smsSentCb, smsDeliveryCb);
}
现在,我们将在步骤 3 中定义的回调中接收响应(smsSentCb、smsDeliveryCb)。
4.3.14 监听传入的短信
此示例应用程序演示了如何侦听传入的 SMS。
- 实现ISmsListener接口来接收传入的短信
class MySmsListener : public ISmsListener {
public:
void onIncomingSms(int phoneId, std::shared_ptr<SmsMessage> message) override;
};
void MySmsListener::onIncomingSms(int phoneId, std::shared_ptr<SmsMessage> smsMsg) {
std::cout << "MySmsListener::onIncomingSms from PhoneId : " << phoneId << std::endl;
std::cout << "smsReceived: From : " << smsMsg->toString() << std::endl;
}
- 获取PhoneFactory和PhoneManager实例
auto &phoneFactory = PhoneFactory::getInstance();
auto phoneManager = phoneFactory.getPhoneManager();
- 检查电话子系统是否准备就绪
bool subSystemStatus = phoneManager->isSubsystemReady();
- 如果电话子系统无法初始化,则退出应用程序
if(subSystemStatus) {
std::cout << " *** Subsystem Ready *** " << std::endl;
} else {
std::cout << " *** ERROR - Unable to initialize telephony subsystem" << std::endl;
return 1;
}
5.实例化全局ISmsListener
auto myPhoneListener = std::make_shared<MyPhoneListener>();
- 获取默认短信管理器实例
std::shared_ptr<ISmsManager> smsMgr = phoneFactory.getSmsManager();
- 注册接收短信
auto mySmsListener = std::make_shared<MySmsListener>();
if(smsMgr) {
smsMgr->registerListener(mySmsListener);
}
- 等待收到短信
std::cout << " *** wait for MyPhoneListener::onIncomingSms() to be triggered*** " << std::endl;
std::cout << " *** Press enter to exit the application *** " << std::endl;
std::string input;
std::getline(std::cin, input);
return 0;