




已阅读5页,还剩23页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
系统实现由于篇幅有限,下面只给出本系统与嵌入式相关的重点内容的实现。1Web Service接口按照Web Service技术,服务端提供的服务对客户是透明的,也就是说,客户端不知道服务的具体实现,只知道一个WSDL服务描述文档,所有客户端涉及到这些服务的程序编写都是以此文档为依据的。在VS 2005.NET中,关于Web服务的发现与相关编译等一系列操作都已经被封装起来了,客户端只需要根据服务端的位置,使用添加Web引用的方式,便可在程序中使用服务端提供的服务方法,这比前面提到的gSoap工具包使用起来更方便,当然它们底层封装的机制与协议都是一样的。1) 数据结构以下给出所有服务方法涉及到的一些数据结构。enum USER_PTY /用户权限 ADMIN,/管理员GUEST,/普通用户UNKNOWN/无效用户; struct USER_INFO /用户信息public int id; /用户IDpublic string username; /用户名public string psw; /密码public USER_PTY pty; /用户权限enum PSW_MODE /修改密码模式 RESET,/重置密码MODIFY/修改密码; enum UPDATEUSER_MODE /更改用户模式 ADD,/增加用户DELETE/删除用户; enum UPDATE_MODE /更新数据库模式 UPDATE,/修改INSERT, /增加DELETE /删除;enum MTR_TYPE /物资类型 FOOD, /食物COMMODITY, /日常用品MEDICINE, /药品OTHER, /其他UNKNOWN /无效值;struct MTR_INFO /物资信息public MTR_TYPE type; /物资类型 public string name; /物资名称 public int number; /物资数量 public string unit; /物资单位 public string remark; /备注;enum DISHMADE /菜做法类型 CHAO, /炒JIAN, /煎ZHENG, /蒸DUN, /炖BAN, /拌OTHER, /其他UNKNOWN /无效值;struct MENULIST /菜谱信息 public DISHMADE type; /菜做法类型 public string name; /菜名 public string material; /原料 public string fixing; /配料 public string method; /做法 public string remark; /备注;enum CROWD /人群类型 WEMEN, /女人CHILDRED, /小孩OLDMAN, /老人OTHER, /其他UNKNOWN /无效值; enum HEALTH_TYPE /健康类型 NURSE, /护理DISEASE, /疾病OTHER, /其他UNKNOWN /无效值;struct HEALTH_INFO /健康信息 public CROWD crowd; /人群类型 public HEALTH_TYPE type;/健康类型 public string description; /健康描述 public string remark;/备注;enum AFFIR_TYPE /事务类型DIARY, /日记CALENDAR /日程;struct AFFAIR /事务信息 public int ID;/事务所属用户ID public DateTime time;/事务时间 public AFFIR_TYPE type;/事务类型 public string content;/事务内容;struct FINANCE_INFO /财务信息 public int year; /财务时间年 public int month; /财务时间月 public int day; /财务时间日 public decimal income; /收入 public decimal outcome; /支出 public string remark; /备注;enum DEVICE /模拟设备 ALL, /所有电器,针对配置操作 DOOR, /门 COOKER, /电饭锅 AIRCONDITION, /空调 HUMIDIFIER, /湿度机 VEDIO, /视频设备 ROBOT /机器管家;enum OPERATE /家庭设备操作类型 MODIFY_STATE, /设备开关操作 QUERY_PARAM, /信息查询操作 ADJUST_PARAM, /调节控制操作 CONFIG_PARAM, /设备配置操作;2) Web Service 服务方法关于本系统涉及到的Web服务方法在前面各个模块的设计中已经有了较详细的说明,这里就不再赘述了。所有Web服务方法都是发布在服务端并在服务端实现的。关于如何在VS 2005.NET中使用这些数据结构和服务方法,这里不再详细介绍了,读者可以看一下其它资料。简单地说,就是在VS 2005.NET中通过添加Web引用,从而创建一个WebService的对象,该对象中有对应于远程服务方法的接口,可直接调用这些接口函数实现远程Web服务方法的调用,当然这个对象中也有与远程相同的数据结构。就像使用本地类和对象一样,很方便。2嵌入式开发板端主要数据结构和函数struct CurrentParam /当前家庭设备状态结构体bool door_state; /门的状态bool aircon_state; /空调的状态bool cooker_state; /电饭锅的状态bool humi_state; /湿度机的状态int temperature; /当前空调温度int humidity; /当前湿度机的湿度值int speed; /与空调温度对应的直流电机转速;CurrentParam结构体保存了当前各个设备的工作信息。在系统启动时,根据当前配置信息来初始化该结构体信息。/缺省设备配置信息的宏定义#define AUTOPEN_AIRCONDITION 1 /空调自启动#define AUTOPEN_HUMICONDITION 1 /湿度机自启动#define DEFAULT_TEMPERATURE 38 /空调启动温度为38度#define DEFAULT_HUMIDITY 35 /湿度机启动湿度值为35%#define DEFAULT_ROBOTSTEP 5 /机器管家步进长度为5像素#define DEFAULT_ROBOTCENTERX 320 /机器管家中心位置X=320#define DEFAULT_ROBOTCENTERY 240 /机器管家中心位置Y=240#define DEFAULT_ROBOTDIRECTION 0 /机器管家面部方向向上#define DEFAULT_SPEED 100 /空调38度时直流电机转速为100以上就是前文所提到的恢复配置文件的缺省配置信息。/退出程序线程的入口函数,该函数中一直等待用户退出命令void * check_input(void *)while (1)char input = getchar();if(input = O)bexit = true; /bexit为退出标志break;pthread_exit(NULL);用户在宿主机终端中输入大写字母O后,结束嵌入式开发板端的程序。/*当有客户建立Socket连接时,该函数则进行新连接的交互,即接收、处理*并响应客户的家庭设备监控请求,参数sock_fd就是进行交互的套接字。*/void * home_control(void * sock_fd)pthread_detach(pthread_self();pthread_mutex_lock(&count_mutex);thread_count+;/处理请求线程数加1pthread_mutex_unlock(&count_mutex);int sock = *(int *)sock_fd;int recvbytes, sendbytes;char buffMAXBUFSIZE;if(recvbytes = recv(sock, buff, sizeof(buff), 0) = -1)/接收客户的操作请求perror(recv error);close(sock);pthread_mutex_lock(&count_mutex);thread_count-;pthread_mutex_unlock(&count_mutex);pthread_exit(NULL);SockMsgFormat sockMsg;/Socket消息编解码对象struct RequestFormat * format;/Socket请求信息结构体struct ResponseFormat RestFormat;/Socket响应信息结构体 /对接收到的Socket消息进行解码,并将请求信息保存到format中format = sockMsg.DeRequest(unsigned char *)buff, recvbytes);if (format = NULL)/解码错误或接收到的数据出错,则返回错误消息RestFormat.IsSucceed = false;RestFormat.Value = 0;RestFormat.Info = (unsigned char *)Decode request message failed !n;RestFormat.Config = NULL;else switch(format-FunCode) /根据请求的设备操作类型调用具体的设备操作函数 case 0:/开关设备操作 OpenDevice(format-Device, format-State, format-Value, &RestFormat); break; case 1:/查询参数操作 Query(format-Device, format-Value, &RestFormat); break; case 2:/调节控制操作 Adjust(format-Device, format-Value, &RestFormat); break; case 3:/设备配置操作 SystemConfig(format-Device, format-Value, format-Config, &RestFormat); break; default:/无效的操作 RestFormat.IsSucceed = false; RestFormat.Value = 0; RestFormat.Info = (unsigned char *)Invalid Request Operation !n; RestFormat.Config = NULL; /计算所返回的操作消息的长度if (RestFormat.Info = NULL)RestFormat.InfoSize = 0;elseRestFormat.InfoSize=strlen(char*)RestFormat.Info); /对响应信息进行编码,并将编码后的消息保存到msg中unsigned char * msg = sockMsg.EnResponse(&RestFormat, &sendbytes);if(send(sock,(char*)msg, sendbytes, 0) = -1)/发送响应消息perror(send error!); /释放资源if (format)if (format-Config != NULL)delete format-Config;format-Config = NULL;delete format;format = NULL;if (msg)delete msg;msg = NULL;close(sock);pthread_mutex_lock(&count_mutex);thread_count-;/处理请求线程数减1pthread_mutex_unlock(&count_mutex);pthread_exit(NULL);上述函数根据家庭设备操作的请求来调用具体的操作函数,这些操作函数在前面的设计中已经有较详细的说明了,实现的时候就是针对具体的设备进行操作,可能有一些判断,代码逻辑性不是很难,此处不再给出。 /嵌入式开发板端的主函数int main(int argn, char * argv)int sockfd, client_fd;struct sockaddr_in my_addr;struct sockaddr_in remote_addr;int sin_size = 0;int recvbytes;Init_System();/读取配置文件初始化相关数据和家庭设备if(sockfd = socket(AF_INET,SOCK_STREAM,0) = -1)perror(socket creat new ResponseFormat();wrong!);exit(1);my_addr.sin_family = AF_INET;my_addr.sin_port = htons(SERVPORT);my_addr.sin_addr.s_addr = INADDR_ANY;bzero(&(my_addr.sin_zero),8);if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr) = -1)perror(bind wrong!);exit(1);if(listen(sockfd, BACKLOG) = -1)perror(listen wrong!);exit(1);pthread_t th_a, th_check; /*创建用于退出程序的线程,即等待退出命令的线程,check_input为该线程的入口*函数。*/ pthread_create(&th_check, NULL, check_input, NULL);for(; ;)if (bexit) break;sin_size = sizeof(struct sockaddr);if (client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size) = -1) /建立了一个Socket连接perror(accept error!);continue;if (thread_count MAXTHREAD) /*若与客户交互的线程数小于最大允许的线程数,则创建新线程并*在 client_fd上进行新连接的交互,home_control为该线程的入口*函数。*/pthread_create(&th_a, NULL, home_control, &client_fd);else/若线程数达到最大值,则直接在主线程中进行新连接的交互home_control(&client_fd); Close();/退出程序前,进行一些资源释放和写文件操作close(sockfd);close(client_fd);return 0; 对于门、电饭锅、空调、湿度机等监控的实现比较简单,就是通过各个设备操作函数进行判断、计算和设备驱动等操作,逻辑性简单,所以就不详细介绍它们的实现了,以下给出机器管家和家庭视频监控的实现所需要的其它相关内容。3机器管家模块1) 数据结构struct fb_dev /framebuffer设备信息结构体int fb; /设备文件描述符void * fb_mem; /显存指针int fb_width; /屏幕宽度int fb_height; /屏幕高度int fb_line_len; /一行的长度int fb_size; /显存大小int fb_bpp; /像素位数;struct POINT /点(像素)坐标int x; /横坐标int y; /纵坐标;struct machine_info /机器人信息结构体POINT center; /中心点,即双箭头交叉中心点int direction; /机器人的面部方向int cx; /机器人的肩宽int cy; /机器人的身体厚度int step; /机器人的步进长度,即每次移动的长度int minX; /机器人面向左时中心点横坐标允许的最小取值int maxX; /机器人面向右时中心点横坐标允许的最大取值int minY; /机器人面向上时中心点纵坐标允许的最小取值int maxY; /机器人面向下时中心点纵坐标允许的最大取值;结构体machine_info中的center是模拟机器人的中心点坐标,direction是机器人当前的面部方向,cx和cy确定了机器人模拟图形的大小,在程序中固定不变。cx和cy不是机器人在屏幕上的横纵坐标的长度,要结合direction来确定横纵坐标长度,如面向上下时,横坐标长度为cx,而面向左右时,横坐标长度为cy。由于模拟机器人是对称结构,所以center、direction、cx、cy决定了模拟机器人在屏幕中的位置,根据它们就可以将模拟机器人在屏幕上绘制出来了。step决定了机器人一次移动的距离,该值在初始化时从配置文件中读取。minX、maxX、minY、maxY决定了机器人的移动范围,从而保证移动过程中不越界,这四个元素值在初始化时根据cy以及fb_dev结构体中的fb_height和fb_width计算获得,并在程序中固定不变。本系统将机器管家封装成一个类,由于用framebuffer模拟机器管家,所以该类中需要一个fb_dev结构体变量来保存对应的framebuffer信息,该结构体变量在设备初始化时进行赋值,另外machine_info结构体变量必不可少,控制机器人动作以及绘制机器人图形都是通过此结构体实现的,该类定义如下:class MachineMajordomopublic:MachineMajordomo(int x, int y, int direction, int step, bool bInit);virtual MachineMajordomo();bool init(int x, int y, int direction, int step);bool init_machine(int x, int y, int direction, int step);bool framebuffer_open();void framebuffer_close();bool draw_point(int x, int y, int color);bool draw_machine(struct machine_info * machine, int draw_mode);void ModifyCenter(int half_x, int half_y);bool Action(int action);char * getError();struct machine_info * machine_info;protected:struct fb_dev fbdev;char * error;2) 主要函数对应的设备操作函数:void Adjust(int device, int value, struct ResponseFormat * RestFormat);参数value指定了控制机器人动作的移动方向。模拟机器管家功能的主要函数就是类MachineMajordomo中的一些函数,说明如下:bool draw_point(int x, int y, int color);参数说明:x、y分别是像素的横、纵坐标。 color是像素的颜色值。返 回 值:画点成功返回true,否则返回false。功能说明:该函数根据传入的color修改指定像素的颜色值,即根据x、y计算出要修改的像素在帧缓冲中的位置,然后将该位置的值赋为color值,从而改变了液晶屏上一个像素的颜色值。对机器人图形的绘制最终都是通过绘制一个个点实现的。bool draw_machine(struct machine_info * machine, int draw_mode);参数说明:machine指向要绘制的机器人图形信息。 draw_mode表示绘制图形的模式,可取以下值: DRAW_COLOR,表示正常显示机器人图形; DRAW_CLEAR,表示擦除机器人图形,即置成屏幕的背景色。当控制机器人动作使得机器人位置发生变化时要重新绘制图形,而在此之前要清除掉之前的图形,以便实现位置的变化。所以以上两种模式是结合使用的。返 回 值:绘制成功返回true,否则返回false;功能说明:该函数根据传入的模式和机器人信息绘制机器人图形。bool Action(int action);参数说明:action指定当前机器人的移动方向。返 回 值:控制机器人动作成功返回true,否则返回false。功能说明:该函数根据输入的移动方向对机器人进行动作控制,它是机器管家功能中的核心函数,也是该类提供给用户的接口。由于设计的机器人图形是对称的,所以它的移动就是中心点的移动,即改变了中心点的坐标就可以定位机器人新的位置。是变换方向还是向前移动,是改变中心点的横坐标值还是纵坐标值,都需要根据机器人当前方向和action来判断。void ModifyCenter(int half_x, int half_y);参数说明:half_x是机器人图形相对于液晶屏的横向长度的一半。 Half_y是机器人图形相对于液晶屏的纵向长度的一半。功能说明:该函数进行转向动作的越界检查,故而它主要在转向操作时调用,以避免机器人因横纵向长度切换可能而引起的越界。3) 相关流程图当Web客户端通过调用服务方法RobotControl后,Web服务端将服务请求封装为Socket请求发送给开发板,开发板中根据请求信息结构体中的Device(机器人)和Value(控制动作的移动方向)两个元素值来调用Adjust函数进行机器人的动作处理,而在Adjust函数中调用了MachineMajordomo 对象的Action函数。处理流程如下图:图10-47 智能家居系统的机器人动作控制流程图一图10-48 智能家居系统的机器人动作控制流程图二注:上面二图是一个整体流程,由于流程图过大,才分成两个图。流程说明控制机器人动作即改变模拟图形在屏幕上显示的位置,所以主要是改变机器人的中心点位置和面部方向,若相同方向移动,则只需要根据步进长度改变中心点坐标即可,若不同方向移动即转向操作,则只需要改变面部方向,并根据越界检查按需要改变中心点坐标。改变机器人信息后通过重绘界面达到动作引起的位置变化,重绘时先清除上一个位置的图形而后再绘制当前位置的图形。由于篇幅限制,就不给出代码了,上面的流程图已经很详细了。4家庭视频监控控制1) 主要数据typedef struct video /视频描述信息结构体/设备文件描述符int video_fd; /视频采集相关结构体struct video_capability videocap; struct video_channel videochan; struct video_picture videopict; struct video_mbuf videombuf;struct video_mmap videommap; struct video_window videowin; /图像分辨率和帧格式相关int width; /宽度,单位:像素int height; /高度,单位:像素 int format; /帧格式 int framesize;/帧大小unsigned char * pFramebuffer; /图像内存指针int grabmethod;/截取图像的方式:mmap或者read/内存缓冲池相关unsigned char * mpegbufsVIDEOBUFS; /缓冲区数组,即缓冲池int mpegdatasizeVIDEOBUFS; /缓冲区实际数据大小bool mpegbuflockVIDEOBUFS; /缓冲区加锁标志int mpegbuf_cour; /当前要写入信息的缓冲区的索引VIDEO;该结构体包含了视频设备的相关信息、图像分辨率和帧格式、用于视频数据存储与传输的缓冲池等。图像分辨率和帧格式由程序指定,默认分辨率为320x240,格式为RGB24,在初始化时根据指定的图像格式和分辨率设置设备属性,同时将设置好的属性保存在结构体的设备信息相关元素中,内存缓冲池默认为4个大小为20kb的空间,初始化过程中进行空间分配并初始化结构体中的相关信息。本系统将视频封装成一个类,该类进行视频的初始化与采集工作,关于视频信息是必不可少的,所以此类中有一个video结构体变量,该变量是采集图像的关键信息。该类定义如下:class MyV4Lpublic: MyV4L:MyV4L(); MyV4L(int width, int height, int format, bool bInit); virtual MyV4L(); bool video_init(int width, int height, int format); bool V4L_init(); void V4L_close(); bool Capture(); bool Capture_mmap(); bool Capture_read(); int ConvertFrame(unsigned char *dst, unsigned char *src, int width,int height, int format, int qualite); int GetDepth(int format); char * getError(); bool isInit(); VIDEO video;protected: char * error; bool is_Init;该结构体中的成员变量error用于保存函数执行过程中由于发生错误而产生的错误消息,调用者可以根据getError函数获取到该错误消息,从而保证对客户端有请求处理失败的响应消息。以下三个全局变量用于控制线程结束。bool imageget,控制客户端接收视频数据线程的结束。bool video_capture,控制开发板采集视频数据线程的结束。bool video_send,控制开发板发送视频数据线程的结束。这三个变量的值为true时,表示继续执行,也表示当前正在进行视频传输,为false时表示跳出所在循环体从而结束线程,也表示当前没有视频传输,初始化为false。2) 主要函数对应的设备操作函数:void OpenDevice(int device, bool bstate, struct ResponseFormat * RestFormat);参数bstate用来指定打开或关闭视频传输。完成视频数据的采集与传输所涉及到的的主要函数如下:bool video_init(int width, int height, int format);参数说明:width为图像分辨率的宽度,单位:像素。 height为图像分辨率的高度,单位:像素。 Format为图像的格式。返 回 值:成功返回true,失败返回false,错误信息保存在变量error中。功能说明:该函数根据传入的图像属性对设备进行初始化操作,同时初始化video结构体,在此函数中调用了V4L_init函数,该函数用来获取和设置一些视频设备属性信息。bool Capture();返 回 值:成功返回true,失败返回false,错误信息保存在变量error中。功能说明:该函数通过视频设备来截取图像,根据截取图像的方式来调用Capture_mmap或Capture_read进行截取工作。无论哪种方式,在截取图像后都要调用ConvertFrame函数进行图像压缩,经过压缩后的图像数据存入到内存缓冲池中,即mpegbufs数组的mpegbuf_cour索引项。除了MyV4L类,还涉及到两个线程,这两个线程通过缓冲池分别进行视频采集与视频传输工作,这两个线程对应的开始函数在MyV4L类外定义,根据全局的MyV4L对象来执行,即一个线程根据MyV4L对象不断截取图像并存入缓冲池,另一个线程不断从MyV4L对象的缓冲池中获取压缩后的图像数据并进行传输,二者之间对缓冲池的同步访问是通过mpegbuflock数组实现的。这两个线程的开始函数定义如下:void * send_image(void * video); /传输视频线程函数void * capture_image(void * param);/采集视频线程函数在客户端涉及到的主要函数有:public void videoCapture(bool bCapture);参数说明:bCapture用来指定开始或停止视频传输。功能说明:该函数在响应用户界面操作时调用,用来向Web服务端发送视频服务请求,打开视频时还要在本地创建视频接收的线程。public void GetImage();功能说明:该函数就是客户端视频接收线程的开始函数,在此函数中进行视频数据的接收与显示。public void ShowImage(byte buf, long length, PictureBox pbx_image);参数说明:buf为图像数据缓冲。 Length为图像数据长度。 pbx_image为显示图像的控件。功能说明:该函数根据传入的图像数据进行界面显示。3) 相关流程图当Web客户端通过调用服务方法CollectVideo后,Web服务端将服务请求封装为Socket请求发送给开发板,开发板中根据请求信息结构体中的Device(视频设备)和State(打开或关闭)两个元素值来调用OpenDevice函数进行视频开关处理,State为true是,打开视频,否则,关闭视频。开发板(Socket服务端)视频模块流程图图10-49 智能家居系统的开发板视频采集与传输流程图流程说明开发板接收到打开视频请求后,若当前没有使用视频设备,则创建两个线程:视频采集线程和视频传输线程,分别进行视频数据的采集与传输。二者共享一个内存缓冲池,但二者不能同时访问缓冲池中的某个缓冲区,这要靠mpegbuflock加锁数组和mpegbuf_cour当前写缓冲区来控制,视频采集线程写入缓冲区前要根据mpegbuflock数组判断当前写缓冲区是否加锁,若加锁则等待,否则写入数据,然后将下一个缓冲区置为当前写缓冲区;视频传输线程读缓冲区前要根据mpegbuf_c
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 甘肃省金昌市金川区2024-2025学年高一上学期期末考试物理考试题目及答案
- 2025年国际贸易考试题及答案
- 2025年新危化企业安全员考试试题及答案
- 2025年甘肃公务员真题
- 2024年阳江市消防救援支队政府专职消防员招录真题
- 2025年精麻药品培训考试题库(含答案)
- 2025年通讯类安全员考试题(附答案)
- 2025年注册质量工程师考试质量理论题及答案
- 2025年科技公司考试试题及答案
- 2025年检验检测机构资质认定评审准则试题及答案
- FZ/T 13002-2014棉本色帆布
- 视频监控解码器dec6108用户手册
- CA-2100E(新机)可燃气体报警控制器使用说明书
- 2022环保检测作业指导书(HJ1237-2021机动车排放定期检验规范)
- 水泵技术规格书说明资料
- 苏科版三年级上册劳动第四课《橡皮泥塑》课件(定稿)
- 法理学-(第五版)完整版ppt全套教学教程课件(最新)
- 《峨日朵雪峰之侧》教案
- 全息经络刮痧疗法(内部培训)课件
- 火灾自动报警系统PPT课件
- 高压氧质控标准
评论
0/150
提交评论