完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
【Nanopi M2试用】之基于gsaop的Webservice远程控制LED灯 在【Nanopi M2试用】之基于gsaop的Webservice开发,这篇试用报告中,详细介绍了如何开发运行在Nanopi M2上的Webservice程序,写了一个简单Add加法运算的Webservice服务端例程,在PC机ubuntu中编写了一个远程调用服务端Add函数的客户端程序,服务器端和客户端通过TCP/IP协议,经无线网络实现了produc-consume(生产与消费)工作模式的软件开发尝试。 本篇试用报告是上一篇试用的报告的基础上,开发基于Webserice的远程控制LED亮灭的实验,进而实现在远端,通过网络控制Nanopi M2的I/O输出。 服务器端为Nanopi M2,由M2承载Webservice服务,即M2实时监听客户端发出的服务请求,当M2根据客户端调用的函数为on时,M2控制gpio口输出低电平,使LED导通;当M2根据客户端调用的函数为off时,M2控制gpio口输出高电平,使LED关断。服务模型如图所示: 1. 搭建硬件环境 本实验采用Nanopi M2中的GPIOB30作为控制LED灯亮灭的输出引脚,如所示: 限流电阻采用300Ω,3.3V供电,硬件连接如图所示: 2. 设计服务器端例程 2.1 GPIO配置函数 Nanopi M2系统已经移植好了基于sysfs的GPIO驱动程序,编译内核时直接将GPIO驱动静态集成到了系统中,根据sysfs导出GPIO操作接口的方法,编写了GPIO设置通用函数如下: #include #include #include #include #include <time.h> #define A 0 #define B 1 #define C 2 #define D 3 #define E 4 /******************************************************************* gpio初始化 gpio_init(B,30,0); * 0 输出 * 1 输入 *******************************************************************/ void gpio_init( char port, char pin, chardirec ) { char buf[100]; int fd=-1,i=0; DIR *dir; fd = open( "/sys/class/gpio/export", O_WRONLY ); snprintf( buf, sizeof( buf ), "/sys/class/gpio/gpio%d", port *32 + pin ); if( ( dir = opendir( buf ) ) == NULL ) { snprintf( buf, sizeof( buf ), "%d", port * 32 + pin ); write( fd, buf, sizeof( buf ) ); } closedir( dir ); close( fd ); snprintf( buf, sizeof( buf ),"/sys/class/gpio/gpio%d/direction", port * 32 + pin ); if( fd = open( buf, O_WRONLY ) ) { printf("%dn",fd); if( direc == 0 ) { i=write( fd, "out", sizeof("out") ); printf( "GPIO %d.%d Outputn", port, pin ); } else { i= write( fd, "in", sizeof("in") ); printf( "GPIO %d.%d Inputn", port, pin ); } } close( fd ); printf( "GPIO %d.%d Init Success..n", port, pin ); } /******************************************************************* gpio电平配置 实例:gpio_write(B,30,1); *******************************************************************/ void gpio_write(char port, char pin, charvalue) { char buf[100]; int fd=-1,i=0; snprintf( buf, sizeof( buf ), "/sys/class/gpio/gpio%d/value",port * 32 + pin ); if( fd = open( buf, O_WRONLY) ) { if( value == 0 ) { i=write( fd, "0", sizeof("0") ); printf( "GPIO %d.%d Output lown", port, pin ); } else { i=write( fd, "1", sizeof("1") ); printf( "GPIO %d.%d Output highn", port, pin ); } close(fd); } } /******************************************************************* gpio输入读取 实例:int zhage=gpio_read(B,30); 0:低电平 1:高电平 *******************************************************************/ int gpio_read( char port, char pin ) { int keyValue=1; char buf[100]; int fd=-1; snprintf( buf, sizeof( buf ), "/sys/class/gpio/gpio%d/value",port * 32 + pin ); fd = open( buf, O_RDONLY ); printf("%dn",fd); if( read( fd, &keyValue, 1) == -1 ) { printf( "PIN%d.%d read errorn", port, pin ); } close(fd); return keyValue-48; } 2.2 编写Webservice服务器端程序 1)编写头文件SmsWBS.h //gsoap ns service name: SmsWBS //gsoap ns service style: rpc //gsoap ns service namespace:http://192.168.1.124:9000/SmsWBS.wsdl //gsoap ns service location:http://192.168.1.124:9000 //gsoap ns service encoding: encoded //gsoap ns schema namespace: urn:SmsWBS int ns_led_on(int* r); //返回值为0说明LED打开成功,返回-1说明LED打开失败 int ns_led_off(int* r); //返回值为0说明LED关闭成功,返回-1说明LED关闭失败 int ns_get_B31(int* r); //获取GPIO B31的引脚输入状态 2)编写服务实现函数文件SmsWBSserver.c #include "soapH.h" #include "SmsWBS.nsmap" #include #include #include #include #include /*******************************************************************/ #define A 0 #define B 1 #define C 2 #define D 3 #define E 4 /******************************************************************* gpio初始化 gpio_init(B,30,0); * 0 输出 * 1 输入 *******************************************************************/ void gpio_init( char port, char pin, chardirec ) { char buf[100]; intfd=-1,i=0; DIR *dir; fd = open( "/sys/class/gpio/export", O_WRONLY ); snprintf( buf, sizeof( buf ), "/sys/class/gpio/gpio%d", port *32 + pin ); if( ( dir = opendir( buf ) ) == NULL ) { snprintf( buf, sizeof( buf ), "%d", port * 32 + pin ); write( fd, buf, sizeof( buf ) ); } closedir( dir ); close( fd ); snprintf( buf, sizeof( buf ),"/sys/class/gpio/gpio%d/direction", port * 32 + pin ); if( fd = open( buf, O_WRONLY ) ) { printf("%dn",fd); if( direc == 0 ) { i=write( fd, "out", sizeof("out") ); printf( "GPIO %d.%d Outputn", port, pin ); } else { i= write( fd, "in", sizeof("in") ); printf( "GPIO %d.%dInputn", port, pin ); } } close( fd ); printf( "GPIO %d.%d Init Success..n", port, pin ); } /******************************************************************* gpio电平配置 实例:gpio_write(B,30,1); *******************************************************************/ void gpio_write(char port, char pin, charvalue) { char buf[100]; int fd=-1; int i=0; snprintf( buf, sizeof(buf), "/sys//class/gpio/gpio%d/value",port * 32 + pin ); if( fd = open( buf, O_WRONLY) ) { if( value == 0 ) { i=write( fd, "0", sizeof("0") ); printf( "GPIO %d.%d Output lown", port, pin ); } else { i=write( fd, "1", sizeof("1") ); printf( "GPIO %d.%d Output highn", port, pin ); } close(fd); } } /******************************************************************* gpio输入读取 实例:int zhage=gpio_read(B,30); 0:低电平 1:高电平 *******************************************************************/ int gpio_read( char port, char pin ) { int keyValue=1; char buf[100]; int fd=-1; snprintf( buf, sizeof( buf ), "/sys/class/gpio/gpio%d/value",port * 32 + pin ); fd = open( buf, O_RDONLY ); printf("%dn",fd); if( read( fd, &keyValue, 1) == -1 ) { printf( "PIN%d.%d read errorn", port, pin ); } close(fd); return keyValue-48; } int main(int argc, char **argv) { int m, s; /* masterand slave sockets */ struct soap SmsWBS_soap; soap_init(&SmsWBS_soap); soap_set_namespaces(&SmsWBS_soap, namespaces); //初始化B30引脚为GPIO输出 gpio_init(B,30,0); gpio_write(B,30,1); //初始化为高电平输出 //初始化B31引脚为GPIO输入 gpio_init(B,31,1); if (argc < 2) { printf("usage: %s exit(1); } else { m = soap_bind(&SmsWBS_soap,NULL, atoi(argv[1]), 100); if (m < 0) { soap_print_fault(&SmsWBS_soap, stderr); exit(-1); } fprintf(stderr, "Socketconnection successful: master socket = %dn", m); for (;;) { s =soap_accept(&SmsWBS_soap); if (s < 0) { soap_print_fault(&SmsWBS_soap, stderr); exit(-1); } fprintf(stderr,"Socket connection successful: slave socket = %dn", s); soap_serve(&SmsWBS_soap); soap_end(&SmsWBS_soap); } } return 0; } /* int ns__add(struct soap *add_soap, intnum1, int num2, int *sum) { *sum = num1 + num2; return 0; } */ int ns_led_on(struct soap *add_soap,int* r) { gpio_write(B,30,0); //输出低电平,点亮LED灯 *r= 0; return0; } int ns_led_off(struct soap *add_soap,int*r) { gpio_write(B,30,1); //输出高电平,熄灭LED灯 *r= 0; return0; } int ns_get_B31(struct soap *add_soap,int*r) { *r= gpio_read(B,31); //返回B31引脚状态 return0; } 3)编写Makefile文件 GSOAP_ROOT=/usr/local/gSOAP WSNAME0=soap WSNAME=SmsWBS CC=ARM-linux-g++ -g -DWITH_NONAMESPACES INCLUDE=-I $(GSOAP_ROOT)/include SERVER_OBJS=$(WSNAME0)C.o$(WSNAME0)Server.o stdsoap2.o CLIENT_OBJS=$(GSOAP_ROOT)/env/envC.o$(WSNAME0)ClientLib.o stdsoap2.o ALL_OBJS=${WSNAME}server.o $(WSNAME0)C.o$(WSNAME0)Server.o ${WSNAME}test.o $(WSNAME0)ClientLib.o #GSOAP_SRC=/usr/local/gsoap-2.7/gsoap all:server ${WSNAME}.wsdl:${WSNAME}.h $(GSOAP_ROOT)/bin/soapcpp2-c $(GSOAP_ROOT)/import ${WSNAME}.h #stdsoap2.o:$(GSOAP_ROOT)/src/stdsoap2.c stdsoap2.o:stdsoap2.c $(CC)-c $? $(INCLUDE) $(ALL_OBJS):%.o:%.c $(CC)-c $? $(INCLUDE) server:Makefile ${WSNAME}.wsdl${WSNAME}server.o $(SERVER_OBJS) $(CC)${WSNAME}server.o $(SERVER_OBJS) -o ${WSNAME}server client:Makefile ${WSNAME}.wsdl${WSNAME}test.c $(ALL_OBJS) stdsoap2.o $(CC)${WSNAME}test.o $(CLIENT_OBJS) -o ${WSNAME}test clean: rm-f *.o *.xml *.a *.wsdl *.nsmap $(WSNAME0)H.h $(WSNAME0)C.c $(WSNAME0)Server.c$(WSNAME0)Client.c $(WSNAME0)Stub.* $(WSNAME)$(WSNAME)Proxy.*$(WSNAME)$(WSNAME)Object.* $(WSNAME0)ServerLib.c $(WSNAME0)ClientLib.c$(WSNAME)server ns.xsd $(WSNAME)test 注意,该程序要在基于ARM架构的Nanopi M2上运行,一定要确保编译器为CC=arm-linux-g++ 4)执行make命令,生成SmsWBSserver可执行程序。 5)将SmsWBSserver拷贝到/nfsshare文件夹,以备Nanopi M2上电后挂载该网络文件系统,以在M2上直接执行/nfsshare/SmsWBSserver程序。 3. 设计客户端例程 1)将上一节创建代码的文件夹中创建客户端程序SmsWBStest.c #include #include #include "soapStub.h" #include "SmsWBS.nsmap" int ns_led_on(const char *server, int *r) { structsoap SmsWBS_soap; int result = 0; soap_init(&SmsWBS_soap); soap_set_namespaces(&SmsWBS_soap, namespaces); soap_call_ns_led_on(&SmsWBS_soap, server, "", r); if(SmsWBS_soap.error) { printf("soap error:%d, %s, %s ", SmsWBS_soap.error,*soap_faultcode(&SmsWBS_soap), *soap_faultstring(&SmsWBS_soap)); result = SmsWBS_soap.error; } soap_end(&SmsWBS_soap); soap_done(&SmsWBS_soap); return result; } int ns_led_off(const char *server, int *r) { structsoap SmsWBS_soap; int result = 0; soap_init(&SmsWBS_soap); soap_set_namespaces(&SmsWBS_soap, namespaces); soap_call_ns_led_off(&SmsWBS_soap, server, "", r); if(SmsWBS_soap.error) { printf("soap error:%d, %s, %s ", SmsWBS_soap.error,*soap_faultcode(&SmsWBS_soap), *soap_faultstring(&SmsWBS_soap)); result = SmsWBS_soap.error; } soap_end(&SmsWBS_soap); soap_done(&SmsWBS_soap); return result; } int ns_get_B31(const char *server, int *r) { structsoap SmsWBS_soap; int result = 0; soap_init(&SmsWBS_soap); soap_set_namespaces(&SmsWBS_soap, namespaces); soap_call_ns_get_B31(&SmsWBS_soap, server, "", r); if(SmsWBS_soap.error) { printf("soap error:%d, %s, %s ", SmsWBS_soap.error,*soap_faultcode(&SmsWBS_soap), *soap_faultstring(&SmsWBS_soap)); result = SmsWBS_soap.error; } soap_end(&SmsWBS_soap); soap_done(&SmsWBS_soap); return result; } int main(int argc, char **argv) { int result = -1; char* server="http://192.168.1.137:9000"; intcmd = 0; intr = -1; if( argc < 2 ) { printf("usage: %s cmdnumn", argv[0]); exit(0); } cmd = atoi(argv[1]); switch(cmd) { case 0: { result =ns_led_on(server, &r); if (result != 0) { printf("soap err, errcode = %d n", result); } else { printf("led onn"); } break; } case 1: { result =ns_led_off(server, &r); if (result != 0) { printf("soap err, errcode = %d n", result); } else { printf("led offn"); } break; } case 2: { result =ns_get_B31(server, &r); if (result != 0) { printf("soap err, errcode = %d n", result); } else { printf("Pin B31's status is %d n",r); } break; } default: printf("The cmd youinput is not supported!n"); } return 0; } 2)修改Makefile 由于客户端程序运行在PC机中的ubuntu系统下,为X86架构,所编译器也要选为X86架构下的gcc,只需将上一节中的CC=arm-linux-g++修改为CC=g++ 3)编译程序 顺序执行命令:make make client 至此,服务器端和客户端的程序就都建立起来了。 4. 测试 在Nanopi M2执行命令: sudo mount -t nfs 192.168.1.xxx:/nfsshare /mnt -o nolock ls /mnt 如下图所示: 可以看到SmsWBSserver已经出现在M2挂载的网络文件系统中了。 执行命令:./SmsWBSserver 9000 NanopiM2启动服务监听,如图所示: 在PC机ubuntu客户端没有发出命令请求时,面包板上的LED灯不亮,如下图所示: 在PC的ubuntu系统下自行如下命令: ./SmsWBStest 0 (参数为0说明,让Nanopi M2的GPB30端口输出低电平) 按下Enter键后,Nanopi M2根据客户端的请求,GPB30输出低电平,点亮LED灯,如图所示: 在PC机的ubuntu系统输入如下命令熄灭LED灯 ./SmsWBStest 1 如图所示: |
|
相关推荐
1 个讨论
|
|
只有小组成员才能发言,加入小组>>
371个成员聚集在这个小组
加入小组NanoPi m3适合刷什么系统,刚接触玩,我刷了一个比较卡
5494 浏览 1 评论
7208 浏览 1 评论
4799 浏览 1 评论
【NanoPC-T4试用体验】4、手把手教你从单片机移植驱动到ARM Linux上
7787 浏览 1 评论
【NanoPC-T4试用体验】NanoPC-T4控制步进电机
24621 浏览 1 评论
NanoPi m3适合刷什么系统,刚接触玩,我刷了一个比较卡
5495浏览 1评论
456浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 21:16 , Processed in 0.861218 second(s), Total 76, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号