五. SECS/GEM封装库RapidSecs开发手记-基础库DEMO开发-1

1.库结构

RapidSecs的C++基础库包括:

文件

描述

rapid_secs.h

头文件

RapidSecs.dll

动态库

RapidSecs.lib

动态库对应的Lib

2.头文件

主要是定义了一些基本的数据结构和接口函数供用户调用,接口功能在上一章的博文中已经进行了介绍,这里就不再重复了。头文件的代码如下:

3.Demo功能设计

  • 采用Dos界面,简单明了即可;
  • 支持基本的主机端和设备端功能,主要侧重设备端;
  • 提供一些基本的功能演示,目标覆盖所有的接口函数,演示接口调用方法即可;

4.Demo功能开发

4.1 用户输入

程序启动时首先由用户选择是作为主机端?还是作为设备端?然后进一步由用户选择是采用主动模式?还是被动模式?代码如下:

hint00:
	unsigned char modeHE = 0;
	bool bHost = true;
	cout << "Choose mode, Host or Equipment? (Enter H or E): " << endl;
	cin >> modeHE;
	if (modeHE == 'H' || modeHE == 'h') {
		bHost = true;
	}
	else if (modeHE == 'E' || modeHE == 'e') {
		bHost = false;
	}
	else {
		goto hint00;
	}

hint01:
	unsigned char mode = 0;
	cout << "Choose HSMS mode, Passive or Active? (Enter P or A): " << endl;
	cin >> mode;
	if (mode == 'P' || mode == 'p') {
		mode = HSMS_PASSIVE;
	}
	else if (mode == 'A' || mode == 'a') {
		mode = HSMS_ACTIVE;
	}
	else {
		goto hint01;
	}

4.2 初始化

首先,程序要运行需要传入一些基本的配置信息,除上边的运行模式、HSMS模式外还应包括:本机IP/Port、远程IP/Port、设备ID和几个特定的超时等。代码如下:

此处最重要的是几个回调函数如下:

BOOL WINAPI OnConnect(
	RSECSH hServer,
	RSECSH hSecs,
	USHORT usDevId)
{
	g_eq_ptr->hsms_session = hSecs;
	cout << "Host connected." << endl;
	return TRUE;
}

连接建立时调用,保存好句柄,并打印连接成功信息。

DWORD WINAPI OnRecvMessage(
	RSECSH session_handle,
	unsigned long id,
	unsigned char stream,
	unsigned char function,
	RAPID_SECS_ITEM* ptr_item)
{
	secs_log::secs_log_msg_to_console(id, stream, function, ptr_item);
	// process message
	return proc_result;
}

接收到消息后触发的回调,后面所有对接收到消息的处理都要基于此回调函数。

VOID WINAPI OnClose(
	RSECSH hSecs)
{
	g_eq_ptr->hsms_session = NULL;
	cout << "Host disconnected." << endl;
}

连接断开时的回调函数,示例仅打印信息。

void WINAPI OnReplyTimeout(
	RSECSH session_handle,
	unsigned long id)
{
	cout << "message[" << id << "] reply timeout" << endl;

	if (g_eq_ptr->m_comm_fsm.m_msgid_s1f13 == id) {
		comm_fsm_send_event(&(g_eq_ptr->m_comm_fsm), gem_impl::RECV_S1_F14_TIMEOUT);
	}
}

当之前发送的消息在T3时间内没收到回应时,RapidSecs库触发此回调。示例仅打印信息。

然后,就是根据配置信息开启服务,那么无论是主机端还是设备端首先都要调用“rapid_create_secs”创建secs对象,再根据是主动模式?还是被动模式来决定是调用“rapid_secs_startup_server”?还是“rapid_secs_connect”,主要的代码如下:

int start_gem_service(gem_impl::GEM_EQUIPMENT* eq, RAPID_SECS_CFG* settings)
{
	eq->m_comm_fsm.state = gem_impl::DISABLED;
	eq->server_handle = NULL;
	eq->active_handle = NULL;
	eq->hsms_session = NULL;

	start_comm_fsm(eq);
	comm_fsm_send_event(&eq->m_comm_fsm, gem_impl::EV_ENABLE_COMM);

	RSECSH secs_inst = rapid_create_secs(settings);
	if (secs_inst == NULL) {
		cout << "rapid_create_secs failed." << endl;
		return E_FAILED;
	}

	BOOL start_up_ok = false;
	switch(settings->mode) {
	case HSMS_PASSIVE: {
			start_up_ok = rapid_secs_startup_server(secs_inst);
			if (!start_up_ok) {
				cout << "rapid_secs_startup_server failed." << endl;
				rapid_destroy_secs(secs_inst);
				return E_FAILED;
			}
			else {
				cout << "SIM equipment started, PASSIVE mode." << endl;
				eq->server_handle = secs_inst;
			}
		}
		break;
	case HSMS_ACTIVE: {
			cout << "start SIM equipment in ACTIVE mode." << endl;
			start_up_ok = rapid_secs_connect(secs_inst);
			if (start_up_ok) {
				g_eq_ptr->hsms_session = secs_inst;
				cout << "connect OK." << endl;
			}
			else {
				cout << "connect failed. RapidSecs will retry after T7 time..." << endl;
			}
			g_eq_ptr->active_handle = secs_inst;
		}
		break;
	default:
		break;
	}
	return E_SUCCESS;
}

4.3 建立连接

初始化完成之后的下一步就是要建立连接,然后才能进行下一步的通讯过程。当使用测试工具与Demo程序建立连接时,OnConnect将会被调用,如下图所示:

五. SECS/GEM封装库RapidSecs开发手记-基础库DEMO开发-1_第1张图片

到此,主机端和设备端Demo已经能够建立连接了,但是还不能建立真正的有效通信,因为建立连接后由于Demo程序是设备端被动模式,而测试工具是主机端主动模式,所以在建立连接后主机端会主动发送S1F13命令请求与设备端建立通信,而设备端Demo则回复S1F14命令进行确认,而设备端目前还不具备状态机、数据接收处理和数据组装功能,还无法响应S1F13命令。

你可能感兴趣的:(SECS/GEM实战)