zoukankan      html  css  js  c++  java
  • 动环监控系统中B接口的实现

    动环监控系统简述

    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        https://www.linaro.org/downloads/

    SOAP/XML 关于C/C++ 语言的实现    gsoap_2.8.83      https://sourceforge.net/projects/gsoap2/files/

    XML数据的生成和解析       tinyxml2

    XML数据的生成和解析   libxml2   ftp://xmlsoft.org/libxml2/

    结合主要开发为C环境且尽量占用较少资源,推荐使用minixml

    XML数据的生成和解析      minixml   https://www.msweet.org/mxml/


     

    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_ns1__invoke() 在客户端调用,实现发送和接收(它调用send和recv);

    服务器接口过程:

    soap_serve() 服务器调用,部署 SOAP 服务器,它会调用soap_serve_request(),当收到 ns1:invoke 的请求时,

    服务器调用 soap_serve_ns1__invoke(),在调用应用层用户接口 ns1__invoke(),来获取接收数据和填充应答数据。

    2.2 SOAP通信简单示例

     我的工程目录如下图所示:

    客户端程序:

    /**
    **********************************************************************************
    * @file        main.c
    * @brief       soap客户端测试程序
    * @details  基于东环监控 B 接口的soap客户端程序
    * @author      wanghuan  any question please send mail to 371463817@qq.com
    * @date        2019-06-17
    * @version     V1.0
    * @copyright    Copyright (c) 2019-2022  江苏亨通光网科技有限公司
    **********************************************************************************
    */
    #include "soapH.h"
    #include "stdsoap2.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #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消息传输超时
        soap_set_namespaces(fsuSoap, namespaces);
    //    soap_set_mode(fsuSoap, SOAP_C_NOIOB);
    
        struct ns1__invokeResponse soap_tmp_ns1__invokeResponse;
        char * soap_tmp_SOAP_ENC__string;
        soap_default_ns1__invokeResponse(fsuSoap, &soap_tmp_ns1__invokeResponse);
        soap_tmp_SOAP_ENC__string = NULL;
        soap_tmp_ns1__invokeResponse._invokeReturn = &soap_tmp_SOAP_ENC__string;
    
        // 手动组成LOGIN的xml数据字符串
        char xmlData[500];
        memset(xmlData, 0x00, sizeof(xmlData));
        strcat(xmlData, "<?xml version="1.0" encoding="UTF-8"?>
    ");
        strcat(xmlData, "<Request>
    ");
        strcat(xmlData, "<PK_Type>
    ");
        strcat(xmlData, "<Name>LOGIN</Name>
    ");
        strcat(xmlData, "</PK_Type>
    ");
        strcat(xmlData, "<Info>
    ");
        strcat(xmlData, "<UserName>123</UserName>
    ");
        strcat(xmlData, "<PassWord>123</PassWord>
    ");
        strcat(xmlData, "<FsuId>10004</FsuId>
    ");
        strcat(xmlData, "<FsuIP>192.168.1.124</FsuIP>
    ");
        strcat(xmlData, "<FsuPort>10000</FsuPort>
    ");
        strcat(xmlData, "</Info>
    ");
        strcat(xmlData, "</Request>
    ");
    
        printf("soap_tmp_ns1__invoke._xmlData:
    ");
        printf("%s", xmlData);
        
        // saop 客户端程序
    //    char * server_addr = "http://10.10.62.83:8080/HT_SC/services/SCService";
        char * server_addr = "http://192.168.1.123:8080";
    
        int iRet = soap_call_ns1__invoke(fsuSoap, server_addr, NULL, xmlData, soap_tmp_ns1__invokeResponse._invokeReturn);
        if ( iRet == SOAP_ERR)
        {
            printf("Error while calling the soap_call_ns1__invoke");
        }
        else
        {
            printf("Calling the soap_call_ns1__invoke success。
    ");
            printf("%s
    ", *soap_tmp_ns1__invokeResponse._invokeReturn);
        }
    
        return 0;
    }

    服务端程序:

    /**
    **********************************************************************************
    * @file        main.c
    * @brief       soap服务端测试程序
    * @details  基于东环监控 B 接口的soap服务器程序
    * @author      wanghuan  any question please send mail to 371463817@qq.com
    * @date        2019-06-17
    * @version     V1.0
    * @copyright    Copyright (c) 2019-2022  江苏亨通光网科技有限公司
    **********************************************************************************
    */
    #include "soapH.h"
    #include "stdsoap2.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #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
    ",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 
    ",    
                    ((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
    ",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
    ");
        printf("%s
    ", _xmlData);
    
        char xmlData[500];
        memset(xmlData, 0, sizeof(xmlData));
        strcat(xmlData, "<?xml version="1.0" encoding="UTF-8"?>
    ");
        strcat(xmlData, "<Response>
    ");
        strcat(xmlData, "<PK_Type>
    ");
        strcat(xmlData, "<Name>LOGIN_ACK</Name>
    ");
        strcat(xmlData, "</PK_Type>
    ");
        strcat(xmlData, "<Info>
    ");
        strcat(xmlData, "<RightLevel/>
    ");
        strcat(xmlData, "</Info>
    ");
        strcat(xmlData, "</Response>");
    
        *_invokeReturn = xmlData;
    //    *_invokeReturn = "<?xml version="1.0" encoding="UTF-8"?>
    <Response>
    <PK_Type>
    <Name>LOGIN_ACK</Name>
    </PK_Type>
    <Info>
    <RightLevel/>
    </Info>
    </Response>";
    
        printf("_invokeReturn _xmlData
    ");
        printf("%s
    ", *_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 += ../soap_sc/soapServer.c
    SOURCES_FSU += ../soap_sc/stdsoap2.c
    
    SOURCES_COMM :=
    
    # 目标文件
    OBJECTS_FSU := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_FSU)))
    OBJECTS_COMM := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES_COMM)))
    
    # 头文件路径
    INCLUDE += -I../soap_sc/                            
               -I../minixml/                             
    #           -I../libxml2/include                         
    #           -I../tinyxml2/                             
    #           -I../comm/                                
    #           -I$(OPENSSL_DIR)/include                  
    
    # 共享库链接OpenSSL
    #LDLIBS += -L$(OPENSSL_DIR)/lib                      
    #          -lssl                                     
    #          -lcrypto                                  
    
    # 静态库链接OpenSSL
    #LDLIBS += $(OPENSSL_DIR)/lib/libssl.a                
    #          $(OPENSSL_DIR)/lib/libcrypto.a             
    #          -ldl                                       
    
    # 静态库链接libxml2
    #LDLIBS += ../libxml2/libxml2.a                          
    #          -lm
    
    # 静态库链接minixml
    LDLIBS += ../minixml/libmxml.a
    #LDLIBS += -lmxml                  
    
    # 链接库(其他)
    LDLIBS += -lpthread
    
    %.o: %.cpp
        @echo "  CPP     " $@;
        @$(CPP) $(CFLAGS) -c -o $@ $<
    
    %.o: %.c
        @echo "  CC      " $@;
        @$(CC) $(CFLAGS) -c -o $@ $<
    
    .PHONY: all clean

    客户端client的Makefile

    include ../Makefile.inc
    
    PROGRAM = fsuc
    
    SOURCES += main.c
    
    OBJECTS := $(patsubst %.c,$(TEMPDIR)%.o,$(filter %.c, $(SOURCES)))
    
    all: $(OBJECTS_FSU) $(OBJECTS_COMM) $(OBJECTS)
        $(CC) -o $(PROGRAM) $(OBJECTS_FSU) $(OBJECTS_COMM) $(OBJECTS) $(LDLIBS)
    
    clean:
        rm -f $(OBJECTS_FSU)
        rm -f $(OBJECTS_COMM)
        rm -f $(OBJECTS)
        rm -f $(PROGRAM)

    编译之后 先执行服务端程序,在执行客户端程序

    服务端收到request

    客户端发送request,并收到response

     接下来开始尝试使用 libxml2 库生成和解析 xml

    2.3 libxml2安装移植(改用minixml)

    新建安装文件夹,这样方便我们提取库文件使用

    mkdir /home/wangh/workspace/wh_tools/libxml-install

    编写安装及配置脚本 wh_configure.sh 如下:

    #!/bin/sh
    
    #sh文件需设置可执行权限 chmod +x wh_configure.sh
    #--prefix=PATH,指定make install时目标文件存放路径
    PREFIX=/home/wangh/workspace/wh_tools/libxml-install
    #--host=target-platform  指定目标平台
    HOST=arm-linux
    #交叉编译绝对路径
    CC_DIR=/home/wangh/Tools/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
    #编译配置
    #sudo ./configure --prefix=$PREFIX --host=$HOST CC=$CC_DIR --with-python=/home/wangh/workspace/wh_tools/libxml2-2.9.9/python
    #编译时由于提示没有python相关的头文件出错,又因为项目中不使用python相关的内容,所以没有讲python进库中,读者应该按照自己的需要要配置该选项。对于zlib同样的道理,--without-zlib不添加会编译出错
    sudo ./configure --prefix=$PREFIX --host=$HOST --target=arm CC=$CC_DIR --without-zlib --without-python
    sudo make
    sudo make install

    执行安装脚本

    2.4 minixml安装移植

    是一个小型的开源的XML解析器,采用 C 语言开发。该解析器最大的特点就是小型、无须依赖其他类库,在嵌入式系统中,minixml解析器很小巧(200k多点),很常用。

    待续。。。。。

  • 相关阅读:
    eslint and stylelint config
    CSS3 animaion 和 transition 比较
    css之px、em、rem
    Three.js 中 相机的常用参数含义
    ES6中函数调用自身需要注意的问题
    MySQL数据库迁移之data目录
    ES6扩展运算符(三点运算符)...的用法
    Vue 组件通信方案
    关于ES6中Promise的应用-顺序合并Promise,并将返回结果以数组的形式输出
    Ubuntu 使用gps
  • 原文地址:https://www.cnblogs.com/silencehuan/p/11018966.html
Copyright © 2011-2022 走看看