controller设计说明文档.docx
《controller设计说明文档.docx》由会员分享,可在线阅读,更多相关《controller设计说明文档.docx(29页珍藏版)》请在冰豆网上搜索。
controller设计说明文档
Controller设计说明文档
文件状态:
[√]草稿
[]正式发布
[]正在修改
文件编码:
IQI_DD_Controller_V1.0
编撰:
吴青霞Sharon
编撰日期:
2011年6月21日
保密级别:
文档版本:
修订表
编号
生成版本
修订人
修订章节与内容
修订日期
1
1.0
吴青霞Sharon
初稿
2011-06-21
2
3
4
审批记录
版本
审批人
审批意见
审批日期
目录
Controller功能简介4
模块说明4
Controller流程图4
函数与结构体说明4
模块一4
模块二5
模块三7
模块四7
模块五8
模块六8
调试信息的说明8
Controller功能简介
Controller是作为服务器程序,它的功能有:
(1)对PC(PanelUI/TVUI)发出的控制命令运用网络通信的方式进行接收并对其解析处理,将指令结合硬件协议转化之后写入串口来控制相关设备;
(2)对WEBUI进过CGI发送过来的控制命令运用共享内存的方式进行接收,并结合硬件协议转化之后写入串口来控制相关设备;
(3)通过读取设备发过来的串口信息,对数据库进行更新设备状态;
(4)从数据库读取设备信息。
这里可以看到IGREEN软件系统架构图:
上面对Controller的功能用图形表现出来,更能够加深理解。
模块说明
根据以上的功能说明以及架构图,可以把Controller分为以下六个模块:
(1)从数据库读取设备信息;
(2)运用网络通信的方式对接收到的控制命令进行解析处理,来唤醒相应的线程;
(3)运用共享内存的方式接收控制指令,并根据它来唤醒相应的线程;
(4)通过读取设备发过来的串口信息,对数据库进行更新设备状态;
(5)将得到的控制指令结合硬件协议转化之后写入串口来控制相关设备;
(6)通过发射红外码控制电视、DVD、空调等电器。
Controller流程图
以下是Controller设计的流程图,主要是对Controller整个设计过程的纵览,可以对Controller整个设计的思想更好的把握。
点击图标打开Controller设计流程图:
函数与结构体说明
模块一、从数据库读取设备信息
(1)init_module_map()函数
函数被调用的位置:
该函数是在controller_main()中调用的。
函数意义:
读取数据库system表,对device_info[MOD_MAX]这个结构体数组进行初始化,在该函数中,运用了数据库查询语句"selectmodule_name,typefromsystem",得到表的两个属性module_name和type,并将其分别赋值给device_info[i].name和device_info[i].type。
(2)device_info[MOD_MAX]结构体数组
struct_module_map
{
charname[64];//DeviceName
inttype;//DeviceType
}device_info[MOD_MAX];
用于存放从数据库读取的DeviceName与DeviceType。
(3)_reset()函数
返回值:
返回的是一个int类型的,调用成功时返回0;
函数被调用的位置:
该函数是在igreen.c的igreen_main()中调用的。
函数意义:
对灯信息以及窗帘信息进行初始化设定。
首先,对灯具信息的初始化,运用数据库查询语句"selectlighting.id,netid,deviceid,node,level,typefromlighting,lighting_igreenwherelighting.id=lighting_igreen.idorderbydeviceid,node",查询lighting及lighting_igreen两个表,将其属性值分别赋值给结构体数组lighting_units[MAX_LIGHTING_NODE]的各成员变量;其次,对窗帘信息的初始化,运用数据库查询语句"selectcurtain.id,netid,deviceid,nodefromcurtain,curtain_igreenwherecurtain.id=curtain_igreen.idorderbydeviceid",查询curtain及curtain_igreen两个表,将其属性值分别赋值给结构体数组curtain_units[MAX_LIGHTING_NODE]的各成员变量;
(4)lighting_units[MAX_LIGHTING_NODE]和curtain_units[MAX_LIGHTING_NODE]
staticstruct_igreen_lighting
{
charid[CE_ID_LEN];//LightingID
intnet_id;//NetID
intdevice_id;//DeviceID
intnode_id;//ChannelID
intlevel;//LightingLevel
inttype;//LightingType
}lighting_units[MAX_LIGHTING_NODE];
用于存放从数据库读取的灯具信息;
staticstruct_igreen_curtain
{
charid[CE_ID_LEN];//CurtainID
inttype;//3Lines:
0,2Lines:
1
intnet_id;//NetID
intdevice_id;//DeviceID
intnode;//NodeID
}curtain_units[MAX_CURTAIN_NODE];
用于存放从数据库读取的窗帘信息。
模块二、运用网络通信的方式对接收到的控制命令进行解析处理,来唤醒相应的线程
(1)controller_main()函数
函数的位置:
该函数是在monitor.c中的main函数
函数的意义:
该函数主要就是运用网络通信的方式接收控制命令,然后对该命令进行解析,获得devicetype以期唤醒相应的设备线程。
(2)socket(AF_INET,SOCK_DGRAM,0)
返回值:
非负的描述字
函数的位置:
该函数是在monitor.c中的controller_main()函数中出现的
函数意义:
创建一个UDP套接口,AF_INET表示的是IPv4协议,SOCK_DGRAM表示的是UDP套接口,0表示参数protocol。
具体的介绍参考《Linux环境下的C编程指南》P327。
该函数在这里的实际作用是分别创建server套接口和hbt套接口。
bind(s,(structsockaddr*)&servaddr,sizeof(structsockaddr_in))
返回值:
返回值0表示成功
函数意义:
绑定套接口函数bind,它的功能是为套接口分配一个本地协议地址,也就是本地IP地址与本地套接口的组合。
具体的介绍参考《Linux环境下的C编程指南》P328。
sendto(hs,&hbt,sizeof(struct_ce_epack),0,(structsockaddr*)&hbtaddr,hlen);
返回值:
函数返回实际写的字节数,如果出错则返回-1
函数意义:
发送数据包,在这里的实际意义是发送心跳包到所有的用户。
具体的介绍参考《Linux环境下的C编程指南》P355。
recvfrom(s,hdr,sizeof(CEHEADER),MSG_PEEK,(structsockaddr*)&clntaddr,&socklen)
返回值:
函数返回实际读的字节数,如果出错则返回-1
函数意义:
接收数据包,在这里的实际意义是接收控制命令包,具体的介绍参考《Linux环境下的C编程指南》P355。
(3)pack_handle(s,hdr,&clntaddr)
函数位置:
该函数是在monitor.c中的controller_main()函数中调用的
函数意义:
对接收到的命令包进行解析并唤醒相应的线程。
将接受的指令包赋值给结构体ce_msg_tmsg。
(4)_update_client(ip)
函数位置:
该函数是在monitor.c中的pack_handle(s,hdr,&clntaddr)函数中调用的
函数意义:
更新客户的IP记录
_chk_client(ip)
函数意义:
检查客户的IP是否在记录当中
_add_client(ip,h->seq)
函数意义:
将客户的IP保存记录
(5)ce_msg_tmsg
typedefstruct_ce_msg
{
unsignedintsession;/*Especially,session=0whenthismessagecomesfromscenariothread.*/
unsignedcharseq;/*Iddo.*/
chardev_id[CE_ID_LEN];
charcmd[CE_CMD_LEN];
}ce_msg_t;
该结构体用于存放解析完成后的命令以及运用共享内存接收到的CGI的命令。
(6)get_queue(msg->dev_id)
函数位置:
该函数是在monitor.c中的pack_handle(s,hdr,&clntaddr)函数中调用的以及在gateway.c中的gateway_main()中被调用。
函数意义:
根据msg->dev_id获得devicetype,在这里将msg->dev_id与device_info[i].name进行比较,然后将device_info[i].type赋值给deviceType作为返回值返回。
(7)ce_put_msg(msg,q)
函数位置:
该函数是在monitor.c中的pack_handle(s,hdr,&clntaddr)函数中调用的以及在gateway.c中的gateway_main()中被调用。
函数意义:
根据获得的deviceType来唤醒相应的线程。
模块三、运用共享内存的方式接收控制指令,并根据它来唤醒相应的线程
(1)void*gateway_main(void*arg)
函数位置:
该函数是gateway.c的main函数
函数意义:
运用共、共享内存与CGI进行通信,接收命令指令存放在结构体ce_msg_tmsg中。
(2)semid=semget(key,3,IPC_CREAT|0666)创建信号量
semctl(semid,SERVER,SETVAL,sunion)设置信号量的初始值
shmid=shmget(key,SHMDATASIZE,IPC_CREAT|0666)创建共享内存
data=shmat(shmid,0,0)将该共享内存附加到进程的地址空间
以上函数都是Linux的系统函数,具体的介绍参考《Linux环境下的C编程指南》第11章进程间通信。
(3)get_queue(msg->dev_id)与ce_put_msg(msg,q)参见之前的介绍
模块四、通过读取设备发过来的串口信息,对数据库进行更新设备状态
(1)void*_update(void*args)
函数位置:
该函数是在igreen.c中的igreen_main()中被调用
函数意义:
读取串口信息并将其存放在结构体arg*threadArg中,然后对数据库进行设备状态的更新。
(2)readlen=tread(fd_igreen,buf,sizeof(buf),101,IGREEN)
函数位置:
该函数是在igreen.c中的_update()中被调用
函数意义:
从串口中读取数据存放在buf中。
在这里调用了read(fd,buf,nbytes)是Linux中用来读取文件的系统函数,具体的介绍参考《Linux环境下的C编程指南》P196。
(3)arg*threadArg
typedefstruct{
char*buf;
intlen;
}arg;
该结构体用于存放从串口读取数据内容和它的长度。
(4)void*parse(void*args)
传入参数:
(void*)threadArg,即从串口中读取的数据。
函数位置:
该函数是在igreen.c中的_update()中被调用
函数意义:
对得到的串口数据更新数据库,在该函数中,运用了数据库的更新语句sprintf(sql,"updatelightingsetlevel=%dwhereid=(selectidfromlighting_igreenwhere""netid=%danddeviceid=%dandnode=%d)",(buf[i+12]==0x01)?
(int)(((buf[i+13]<<8|buf[i+14]))/(MAX_LEVEL-BASE_LEVEL)*100:
0,buf[i+5],buf[i+6],buf[i+11])对dimmer的情况下的lighting表进行更新;运用了数据库的更新语句sprintf(sql,"updatelightingsetlevel=%d"whereid=(selectidfromlighting_igreenwherenetid=%danddeviceid=%dandnode=%d)",100*buf[i+12],buf[i+5],buf[i+6],buf[i+11])对relay的情况下的lighting表进行更新
模块五、将得到的控制指令结合硬件协议转化之后写入串口来控制相关设备。
(1)void_msg_handle(ce_msg_t*msg)
传入参数:
msg解析完成后的命令
函数位置:
该函数是在igreen.c中的igreen_main()中被调用
函数意义:
将得到的控制指令结合硬件协议转化打包成control_cmd[17]之后写入串口来控制相关设备。
(2)twrite(fd_igreen,control_cmd,17,IGREEN)
函数位置:
该函数是在igreen.c中的_msg_handle(ce_msg_t*msg)中被调用
函数意义:
将结合硬件协议转化打包好的control_cmd[17]指令写到串口当中去。
在这里调用了write(fd,buf,count)是Linux用来对文件进行写操作的系统函数,具体的介绍参考《Linux环境下的C编程指南》P194。
模块六、红外模块。
(在这里讲述控制电视的过程运用到的函数,DVD、空调类似)
(1)_msg_handle(msg)
函数位置:
该函数是在tv.c中的tv_main()中被调用的
函数意义:
当web等客户端发送控制电视命令的时候,命令的格式msg->dev_id=CE-TV-0;msg->cmd=channelup,然后通过ce_put_msg(msg,q)函数唤醒tv线程,这时候在_msg_handle(msg)中对该命令进行处理,运用SQL语句sprintf(sql,"selectcontrollerid,%sfromtv_irwhereid='%s'",msg->cmd,msg->dev_id);查询tv_ir表,得到相应的ir的id以及红外编码,将其写成命令格式为msg->dev_id=CE-TV-0;msg->cmd=send12,然后通过ce_put_msg(msg,q)函数唤醒ir线程。
(2)ir_igreen_main()
函数位置:
该函数是在ir_igreen.c中的main函数
函数意义:
当ir线程被唤醒时,就会进入该函数,处理与ir的整个模块。
(3)_msg_handle(msg)
函数位置:
该函数是在ir_igreen.c中的ir_igreen_main()中被调用的
函数意义:
处理ir编码的学习与发送。
对于ir编码的发送,根据传输过来的命令与设备ID来查询相应的数据库得到对于的ir编码,然后调用send函数将编码发送给相应的设备;对与ir编码的学习,负责将接收到的红外编码更新到数据库当中去。
调试信息的说明
1、controller启动的DEBUG
DEBUG,IQI:
InitingIQILigthingmodule...
解释:
正在初始化灯具模块;
DEBUG,IQI:
CannotloadIQIlightingmodule.
解释:
不能载入灯具模块
DEBUG,IQI:
LoadIQILightingmodulesuccess.
解释:
成功载入灯具模块
DEBUG,IQI:
InitingIQICurtainmodule...
解释:
正在初始化窗帘模块
DEBUG,IQI:
CannotloadIQICurtainmodule.
解释:
不能载入窗帘模块
DEBUG,IQI:
LoadIQICurtainmodulesuccess.
解释:
成功载入窗帘模块
DEBUG,IQI:
Lookuphaitransiswork?
解释:
查询第三方软件是否在运作
DEBUG,IQI:
haitransdoesn'twork
解释:
第三方软件没有在运作
DEBUG,IQI:
haitransdoeswork
解释:
第三方软件在运作
2、Panel控制过程产生的调试信息
DEBUG,Outofmemory:
can'tallocmemoryforprotocolheader!
解释:
内存溢出,不能为协议header分配内存
2011-06-2415:
21:
59|DEBUG,>>>>>>>>>>>>>>>>SeqNumber:
1
2011-06-2415:
21:
59|DEBUG,LNK_REQ
2011-06-2415:
21:
59|DEBUG,_add_client222222seq:
1
2011-06-2415:
21:
59|DEBUG,client192.168.1.111connected,session=0x4E0A342F解释:
如果出现以上的信息,就说明Panel已经连接上了,红色字体是连接的机子IP,在这里对于不同的PC会不一样的,需要注意。
2011-06-2415:
22:
20|DEBUG,>>>>>>>>>>>>>>>>SeqNumber:
2
2011-06-2415:
22:
20|DEBUG,LNK_ALV
2011-06-2415:
22:
23|DEBUG,>>>>>>>>>>>>>>>>SeqNumber:
2
2011-06-2415:
22:
23|DEBUG,LNK_ALV
解释:
如果Panel开始运行,就会每隔3s发出一个对心跳包反馈的请求,证明一直处于连接上的状态。
DEBUG,Clientsession0x4E0A342Flostconnection.
解释:
如果在30s之内没有收到用户LNK_ALV的反馈就会打印出该信息说明该PC断开连接了。
控灯调试信息:
1、对relay开
2011-06-2415:
25:
41|DEBUG,>>>>>>>>>>>>>>>>SeqNumber:
3
2011-06-2415:
25:
41|DEBUG,OPE_REQ
2011-06-2415:
25:
41|DEBUG,CMD:
level=100,DEV:
CE-LIGHTING-69SEQ:
3//对//指令进行解析
2011-06-2415:
25:
41|DEBUG,1111>>>>q:
22
2011-06-2415:
25:
41|DEBUG,msgsession1309291567,seq3,idCE-LIGHTING-69,cmdlevel=100
2011-06-2415:
25:
41|DEBUG,IQI:
_msg_handle//开始将指令写入串口
2011-06-2415:
25:
41|DEBUG,IQI:
_msg_handle----------------LIGHTING
2011-06-2415:
25:
41|DEBUG,id=CE-LIGHTING-69,cmd='level=100',netid=1,deviceid=5,node=6,level=100
**********>>>>>>>>>>>>ControlData************
ff55000105000008010500060100000000//串口信息
***************************
**********_updateAckData************//对数据进行更新
ff5500000001050820050506010000000000
***************************
2、对relay关
>>>>>>>>>>>>>>>>SeqNumber:
4
2011-06-2415:
34:
41|DEBUG,OPE_REQ
2011-06-2415:
34:
41|DEBUG,CMD:
level=0,DEV:
CE-LIGHTING-69SEQ:
4
2011-06-2415:
34:
41|DEBUG,1111>>>>q:
22//对指令进行解析controller_main()
2011-06-2415:
34:
41|DEBUG,msgsession1309291567,seq4,idCE-LIGHTING-69,cmdlevel=0
2011-06-2415:
34:
41|DEBUG,IQI:
_msg_handle
2011-06-2415:
34:
41|DEBUG,IQI:
_msg_handle----------------LIGHTING
2011-06-2415:
34:
41|DEBUG,id=CE-LIGHTING-69,cmd='level=0',netid=1,deviceid=5,node=6,level=0
**********>>>>>>>>>>>>ControlData************
ff55000105000008010500060200000000
****************