动环监控系统简述
1.术语介绍
1.1 省集中监控中心-Province Supervision Center(PSC)
面向多FSU管理的高级监控层次,即省集中监控中心,通过开放的数据协议,连接监控范围内的FSU。
1.2 现场监控单元-Field supervision unit(FSU)
监控系统的最小管理子系统,由若干监控模块和其它辅助设备组成,面向直接的设备数据采集、处理的监控层次,可以包含采样、数据处理、数据中继等功能,
监控范围一般为一个独立的通信局(站)或大型局(站)内相对独立的电源、空调设备及环境。
1.3 监控对象 Supervision Object(SO)
被监控的各种电源、空调设备及机房环境。
1.4 B接口
为省集中监控中心(PSC)与现场监控单元(FSU)之间的接口。(即FSU的北向接口)
2. 接口网络结构
FSU与PSC之间通过WebService和FTP方式互联,二者同时形成完整的B接口协议标准。
B接口在嵌入式arm监控主机上的实现
环境
宿主机平台:Ubuntu 16.04.6
目标机平台:iMX6UL
交叉编译:gcc-linaro-4.9-2014.11 arm-linux-gnueabihf-gcc
SOAP/XML 关于C/C++ 语言的实现 gsoap_2.8.83
XML数据的生成和解析 tinyxml2
XML数据的生成和解析 libxml2
结合主要开发为C环境且尽量占用较少资源,推荐使用minixml
XML数据的生成和解析 minixml
1. gsaop 生成 B接口报文协议 C代码框架
gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。
绝大多数的C++web服务工具包提供一组API函数类库来处理特定的SOAP数据结构,这样就使得用户必须改变程序结构来适应相关的类库。
与之相反,gSOAP利用编译器技术提供了一组透明化的SOAP API,并将与开发无关的SOAP实现细节相关的内容对用户隐藏起来。
1.1 gsaop在linux下的安装
gsoap安装编译依赖
sudo apt-get install build-essential libgtk2.0-dev libglib2.0-dev checkinstall m4 flex bison automake autoconf openssl libssl-dev
为了成功编译gSOAP,您需要安装GTK+的开发文件和GLib库(libraries)。
安装Checkinstall以便管理您系统中直接由源代码编译安装的软件。
安装YACC,YACC是Unix/Linux上一个用来生成编译器的编译器(编译器代码生成器),sudo apt-get install flex bison
安装OpenSSL,web通信的加密(https)及鉴权 sudo apt-get install openssl libssl-dev
安装编译步骤:
解压
unzip gsoap_2.8.83.zip
mkdir gsoap_install
cd gsoap-2.8/
配置安装路径、编译、安装
./configure --prefix=/home/wangh/workspace/wh_tools/gsoap_install
sudo make
sudo make install
使用gsoap生成 fsu 代码框架
新建gsoap_fsu文件夹,从gsoap_install文件夹中拷贝以下文件
bin/soapcpp2 bin/wsdl2h
gsoap2.8/gsoap/typemap.dat
custom和import文件夹
1.使用wsdl2h工具,根据WSDL产生头文件,执行以下命令
./wsdl2h -P -x -c -s -t ./typemap.dat -o fsu.h FSUService.wsdl
其中-c为产生纯c代码,默认生成 c++代码;
-x 不产生xml文件(可用可不用,xml有一定帮助,但是太多);
-s为不使用STL库,-t为typemap.dat的标识。
详情可通过wsdl2h.exe -help查看帮助。
这里的WSDL文件,可以在wsdl2h命令中在线下载,也可以先下载到本地,然后引用本地WSDL文件,我这里是采用本地文件方式。
2. 使用soapcpp2工具,根据头文件 fsu.h 产生框架代码,执行以下命令
./soapcpp2 -2 -L -c -x -I import:custom fsu.h
-2 生成 SOAP 1.2
-L 不生成客户端、服务器库文件
-c 为产生纯c代码,默认生成 c++代码
-I path 引用文件路径
3. 提取有效核心代码用于应用编程,应用工程使用文件如下:
2. B接口报文协议分析与实现
2.1 SOAP函数接口分析
根据 FSUService.wsdl 生成 soap API 如下,在 soapStub.h 的最后定义
我们不用去关心 SOAP 接口的实现细节,直接调用对应 API 即可实现客户端与服务器的 xml 数据收发。
客户端接口过程:
soap_call_ns1invoke() 在客户端调用,实现发送和接收(它调用send和recv);
服务器接口过程:
soap_serve() 服务器调用,部署 SOAP 服务器,它会调用soap_serve_request(),当收到 ns1:invoke 的请求时,
服务器调用 soap_serve_ns1invoke(),在调用应用层用户接口 ns1invoke(),来获取接收数据和填充应答数据。
2.2 SOAP通信简单示例
我的工程目录如下图所示:
客户端程序:
/
**
@file main.c
@brief //代码效果参考:http://www.jhylw.com.cn/131930863.html
soap客户端测试程序@details 基于东环监控 B 接口的soap客户端程序
@date 2019-06-17
@version V1.0
@copyright Copyright (c) 2019-2022 江苏亨通光网科技有限公司
**
/
#include "soapH.h"
#include "stdsoap2.h"
#include
#include
#include
#include "FSUServiceSoapBinding.nsmap"
int main(int argc, char **argv)
{
// struct soap fsuSoap;
// soap_init(&fsuSoap);
struct soap fsuSoap = soap_new();
fsuSoap->send_timeout = fsuSoap->recv_timeout = 5; //soap发送、接收超时
fsuSoap->transfer_timeout = 30; //soap消息传//代码效果参考:http://www.jhylw.com.cn/030134813.html
输超时soap_set_namespaces(fsuSoap, namespaces);
// soap_set_mode(fsuSoap, SOAP_C_NOIOB);
struct ns1invokeResponse soap_tmp_ns1invokeResponse;
char * soap_tmp_SOAP_ENCstring;
soap_default_ns1invokeResponse(fsuSoap, &soap_tmp_ns1invokeResponse);
soap_tmp_SOAP_ENCstring = NULL;
soap_tmp_ns1invokeResponse._invokeReturn = &soap_tmp_SOAP_ENCstring;
// 手动组成LOGIN的xml数据字符串
char xmlData【500】;
memset(xmlData, 0x00, sizeof(xmlData));
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "
\n");
strcat(xmlData, "LOGIN\n");
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "123\n");
strcat(xmlData, "
123\n");
strcat(xmlData, "10004\n");
strcat(xmlData, "192.168.1.124\n");
strcat(xmlData, "10000\n");
strcat(xmlData, "\n");
strcat(xmlData, "\n");
printf("soap_tmp_ns1invoke._xmlData:\n");
printf("%s", xmlData);
// saop 客户端程序
// char server_addr = "";
char server_addr = "";
int iRet = soap_call_ns1invoke(fsuSoap, server_addr, NULL, xmlData, soap_tmp_ns1invokeResponse._invokeReturn);
if ( iRet == SOAP_ERR)
{
printf("Error while calling the soap_call_ns1invoke");
}
else
{
printf("Calling the soap_call_ns1invoke success。\n");
printf("%s\n", soap_tmp_ns1__invokeResponse._invokeReturn);
}
return 0;
}
服务端程序:
/
**
@file main.c
@brief soap服务端测试程序
@details 基于东环监控 B 接口的soap服务器程序
@date 2019-06-17
@version V1.0
@copyright Copyright (c) 2019-2022 江苏亨通光网科技有限公司
**
/
#include "soapH.h"
#include "stdsoap2.h"
#include
#include
#include
#include "FSUServiceSoapBinding.nsmap"
/
启动soap服务器
/
int main(int argc, char argv)
{
SOAP_SOCKET iSocket_master, iSocket_slave;
struct soap fsuSoap = soap_new(); //新建soap
fsuSoap->send_timeout = fsuSoap->recv_timeout = 5; //soap发送、接收超时
fsuSoap->transfer_timeout = 30; //soap消息传输超时
// soap_set_mode(fsuSoap, SOAP_C_NOIOB);
// saop 服务器程序 8080为端口号,最后一个参数不重要。
iSocket_master = soap_bind(fsuSoap, NULL, 8080, 100); //绑定到相应的IP地址和端口()NULL指本机,然后监听
if (iSocket_master< 0) //绑定出错
{
soap_print_fault(fsuSoap, stderr);
exit(-1);
}
printf("SoapBind success,the master socket number is:%d\n",iSocket_master); //绑定成功返回监听套接字
while(1)
{
iSocket_slave = soap_accept(fsuSoap); //收到套接字连接
if(iSocket_slave < 0)
{
soap_print_fault(fsuSoap, stderr);
exit(-1);
}
//客户端的IP地址
fprintf(stderr,"Accepted connection fromIP= %d.%d.%d.%d socket = %d \n", \
((fsuSoap->ip)]24)&&0xFF,((fsuSoap->ip)]16)&0xFF,((fsuSoap->ip)]8)&0xFF,(fsuSoap->ip)&0xFF,(fsuSoap->socket));
printf("Socket connect success,the slave socket number is:%d\n",iSocket_slave);
soap_serve(fsuSoap);
printf("soap_serve end...");
soap_end(fsuSoap); //服务器出错才到这一步
}
soap_done(fsuSoap);
free(fsuSoap);
return 0;
}
/**
soap服务器用户数据处理函数
@param【in】 _xmlData 接收客户端的xml格式字符串
@param【out】 **_invokeReturn 服务器要回复大数据
@return SOAP_OK or error code
/
SOAP_FMAC5 int SOAP_FMAC6 ns1__invoke(struct soap soap, char _xmlData, char **_invokeReturn)
{
printf("ns1__invoke _xmlData\n");
printf("%s\n", _xmlData);
char xmlData【500】;
memset(xmlData, 0, sizeof(xmlData));
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "
\n");
strcat(xmlData, "LOGIN_ACK\n");
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "\n");
strcat(xmlData, "");
_invokeReturn = xmlData;
// _invokeReturn = "\n\n
\nLOGIN_ACK\n\n\n\n\n";
printf("_invokeReturn _xmlData\n");
printf("%s\n", _invokeReturn);
return SOAP_OK;
}
程序makefile:
顶层Makefile与Makefile.inc
DIRS :=
DIRS += sc_client
DIRS += sc_server
#DIRS += xml_test
# Dummy targets for building and clobbering everything in all subdirectories
all:
@ for dir in ${DIRS}; do (cd $${dir}; ${MAKE}) ; done
clean:
@ for dir in ${DIRS}; do (cd $${dir}; ${MAKE} clean) ; done
Makefile.inc
SHELL = /bin/bash
#CC := gcc -m32
#CPP := g++
#LD := ld
#AR := ar
#STRIP := strip
CC := arm-linux-gnueabihf-gcc
CPP := arm-linux-gnueabihf-g++
LD := arm-linux-gnueabihf-ld
AR := arm-linux-gnueabihf-ar
STRIP := arm-linux-gnueabihf-strip
# -DWITH_DOM -DWITH_OPENSSL两个宏是链接openssl时要用的;
# -DDEBUG宏用于开启SOAP协议收发日志,日志存于文件RECV.log、SENT.log、TEST.log之中
CFLAGS += -c -g -Wall
#CFLAGS += -DWITH_DOM -DWITH_OPENSSL
CFLAGS += -std=gnu99
CFLAGS += -DWITH_NO_C_LOCALE
#CFLAGS += -WITH_NONAMESPACES
CFLAGS += $(INCLUDE)
# openssl目录名
OPENSSL_DIR :=
#OPENSSL_DIR += ../openssl
# 源文件
SOURCES_FSU :=
SOURCES_FSU += ../soap_sc/soapC.c
SOURCES_FSU += ../soap_sc/soapClient.c
#SOURCES_FSU += ../