主控后台服务程序
主控程序采用多线程架构:
1.设备更新线程:各个数据采集模块通过5V-3.3V模块连接开发板的GPIO口,该线程不断读取对应GPIO的输入值,动态更新当前设备链表,实现设备的动态更新。
2.进程间通讯线程:该进程申请一块sys_all类型大小的共享内存,以及一条和CGI服务程序通讯的消息队列,通过接收不同类型的消息,动态更新共享内存、g_dev变量、配置文件以及动态设备链表,实现Web界面与主控程序之间的同步。
3.设备状态更新线程:读取光感、声控模块的输出,对LED灯的开关切换进行控制。
deamoc.c
#include<pthread.h>
#include "config.h"
#include "link_pro.h"
#include "sys_ipc.h"
#include "dev_pro.h"
#include "sw_pro.h"
struct sys_all g_dev[1];
struct sys_dev* head_node = NULL;
struct dev_fd g_dev_fd;
unsigned char net_flag = 0;
unsigned char net_cmd;
int area_update_flag = 0;
int init_sys(void)
{
printf("init system...\n");
load_dev(g_dev);
head_node = stu_to_link(head_node);
dev_print(head_node);
return 0;
}
int main()
{
pthread_t pth_dev, pth_ipc, pth_sw;
init_sys();
pthread_create(&pth_dev,NULL,dev_pro,NULL);
pthread_create(&pth_ipc,NULL,ipcs_pro,NULL);
pthread_create(&pth_sw,NULL,sw_pro,NULL);
pthread_join(pth_dev,NULL);
pthread_join(pth_ipc,NULL);
pthread_join(pth_sw,NULL);
return 0;
}
系统数据结构
定义单个设备结构体,设备文件描述符结构体、系统设备组结构体、消息队列结构体、设备类型、设备结点结构体等等。
config.h
#ifndef __SL2000_H_
#define __SL2000_H_
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#define CONFIG_FILE "sl2000.cfg"
#define ON 1
#define OFF 0
#define TEMP_SMG_INDEX_BASE 10
#define WEB_SMG_INDEX 2
#define WEB_UPDATE_SMG_INDEX 3
#define UPDATE_TIME_SMG_INDEX 4
#define DEV_T_MAIN 1
#define DEV_T_SUB 2
#define DEV_T_RAY 3
#define DEV_T_PIR 4
#define DEV_T_MIC 5
#define DEV_T_LIGHT1 6
#define DEV_T_LIGHT2 7
#define DEV_T_LIG_NET 8
#define MAX_DEV 8
#define MAX_NET 2
#define J1_OFF 0x00
#define J1_ON 0x01
#define J2_OFF 0x10
#define J2_ON 0x11
#define LIGHT_DEV "/dev/project_2_light"
#define MIC_DEV "/dev/project_2_sound"
#define PIR_DEV "/dev/project_2_bodyinduction"
#define RELAY1_DEV "/dev/project_2_relay"
#define RELAY2_DEV "/dev/project_2_relay"
#define SEARCH_DEV "/dev/project_2_search"
#define ID_BASE 1;
struct node_info
{
int id;
char ip[16];
char type;
};
struct dev_fd
{
int relay1_fd;
int relay2_fd;
int pir_fd;
int mic_fd;
int light_fd;
int net_fd[MAX_NET];
};
struct sys_dev
{
char name[16];
struct node_info node;
char connect_sta;
char join_sta;
char sw_sta;
int delay;
char bind_dev;
struct sys_dev* next;
};
struct sys_area
{
char name[16];
char dev_id[MAX_DEV];
char sw_sta;
char enable_flag;
};
struct sys_all
{
struct sys_dev sys_dev[MAX_DEV];
struct sys_area sys_area[MAX_DEV];
int net_user[MAX_NET];
int count_dev;
};
struct st_sys_time
{
int year;
char month;
char day;
char hour;
char minute;
char second;
};
struct st_msg_req
{
long int index;
char req;
};
int make_default_config(struct sys_all* dev);
int save_dev(struct sys_all* dev);
int load_dev(struct sys_all* dev);
#endif
config.c
#include<stdio.h>
#include<stdlib.h>
#include "config.h"
int make_default_config(struct sys_all* dev)
{
int i;
printf("Make default configuration!\n");
memset(dev,0,sizeof(struct sys_all));
dev->count_dev = 1;
for(i = 0; i < MAX_DEV; i++)
{
strcpy(dev->sys_dev[i].name,"unknown dev");
dev->sys_dev[i].node.id = 0;
dev->sys_dev[i].node.type = 0;
dev->sys_dev[i].connect_sta = OFF;
dev->sys_dev[i].sw_sta = OFF;
dev->sys_dev[i].bind_dev = 0;
dev->sys_dev[i].delay = 0;
dev->sys_dev[i].next = NULL;
dev->sys_area[i].enable_flag = 0;
}
dev->sys_dev[0].connect_sta = ON;
strcpy(dev->sys_dev[0].name, "main con dev");
dev->sys_dev[0].join_sta = ON;
dev->sys_dev[0].node.id = ID_BASE;
dev->sys_dev[0].node.type = DEV_T_MAIN;
return save_dev(dev);
}
void print_all(struct sys_all* dev)
{
int i;
for(i = 0; i < dev->count_dev; i++)
{
printf("#%d#name=%s,id=%d,type=%d,connect_sta=%d,sw_sta=%d,bind_dev=%d,delay=%d\n",i+1,dev->sys_dev[i].name,dev->sys_dev[i].node.id,dev->sys_dev[i].node.type,dev->sys_dev[i].connect_sta,dev->sys_dev[i].sw_sta,dev->sys_dev[i].bind_dev,dev->sys_dev[i].delay);
}
for(i = 0; i < MAX_DEV; i++)
{
printf("#%d#name=%s,flag=%d,sw_sta=%d,dev_id=%d\n",i+1,dev->sys_area[i].name,dev->sys_area[i].enable_flag,dev->sys_area[i].sw_sta,dev->sys_area[i].dev_id[0]);
}
}
int save_dev(struct sys_all* dev)
{
FILE* fp;
if((fp = fopen(CONFIG_FILE,"wb")) == NULL)
{
printf("Config file open null...\n");
return -1;
}
printf("\nSave system data!\n");
fwrite(dev,sizeof(*dev),1,fp);
fclose(fp);
print_all(dev);
return 0;
}
int load_dev(struct sys_all* dev)
{
FILE* fp;
memset(dev,0,sizeof(*dev));
if((fp = fopen(CONFIG_FILE,"rb")) == NULL)
{
printf("[load_dev]fopen null...\n");
return make_default_config(dev);
}
if(sizeof(*dev) != fread(dev,1,sizeof(*dev),fp))
{
printf("[load_dev]sizeof error...\n");
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
设备链表
建立设备链表,方便进行动态的设备插入与删除。主要包括设备链表的创建、删除、插入、打印结点、更新到g_dev结构体、结构体更新到链表、查找设备等操作
link_pro.h
#ifndef __SL2000_LINK_H
#define __SL2000_LINK_H
struct sys_dev *Create(struct sys_dev main_dev);
struct sys_dev *Delete(struct sys_dev* head, int type);
struct sys_dev *Insert(struct sys_dev* head, struct sys_dev new_dev);
void dev_print(struct sys_dev* head);
struct sys_dev *stu_to_link(struct sys_dev* head);
void link_to_stu(struct sys_dev* head);
int find_id(char id, struct sys_dev* head, struct sys_dev* dev);
struct sys_dev* get_dev_id(char id, struct sys_dev* head);
#endif
link_pro.c
#include "config.h"
#include "link_pro.h"
extern struct sys_all g_dev[1];
struct sys_dev *Create(struct sys_dev main_dev)
{
struct sys_dev* pNew = NULL;
pNew = (struct sys_dev*)malloc(sizeof(struct sys_dev));
if(pNew == NULL)
{
printf("create malloc error...\n");
}
pNew->connect_sta = main_dev.connect_sta;
strcpy(pNew->name, main_dev.name);
pNew->join_sta = main_dev.join_sta;
pNew->node.id = main_dev.node.id;
pNew->node.type = main_dev.node.type;
pNew->sw_sta = main_dev.sw_sta;
pNew->bind_dev = main_dev.bind_dev;
pNew->next = NULL;
printf("plink create ok...\n");
return pNew;
}
struct sys_dev *Insert(struct sys_dev* head, struct sys_dev new_dev)
{
struct sys_dev* pNew;
struct sys_dev* pFind;
pNew = (struct sys_dev*)malloc(sizeof(struct sys_dev));
if(pNew == NULL)
{
printf("create malloc err...\n");
}
pNew->connect_sta = new_dev.connect_sta;
strcpy(pNew->name, new_dev.name);
pNew->join_sta = new_dev.join_sta;
pNew->node.id = new_dev.node.id;
pNew->node.type = new_dev.node.type;
pNew->sw_sta = new_dev.sw_sta;
pNew->bind_dev = new_dev.bind_dev;
pNew->next = NULL;
if(NULL == head)
{
return pNew;
}
else
{
pFind = head;
while(pFind->next != NULL)
{
pFind = pFind->next;
}
pFind->next = pNew;
}
printf("plink insert ok...\n");
return head;
}
struct sys_dev *Delete(struct sys_dev* head, int type)
{
struct sys_dev* pFind;
struct sys_dev* pPrev;
pFind = head;
if(pFind == NULL)
{
printf("empty device list!\n");
return head;
}
while(pFind->node.type != type && pFind->next != NULL)
{
pPrev = pFind;
pFind = pFind->next;
}
if(pFind->node.type == type)
{
if(head == pFind)
{
head = pFind->next;
}
else
{
pPrev->next = pFind->next;
}
free(pFind);
printf("devide node deleted!\n");
}
else
{
printf("no device to delete!\n");
}
return head;
}
void dev_print(struct sys_dev* head)
{
struct sys_dev* p;
p = head;
if(head == NULL)
{
printf("empty list!\n");
}
else
{
printf("%d devices connected\n",g_dev->count_dev);
while(p != NULL)
{
printf("type:%d name:%s\n",p->node.type,p->name);
p = p->next;
}
}
}
struct sys_dev* stu_to_link(struct sys_dev* head)
{
int i;
for(i = 0; i < g_dev->count_dev; i++)
{
if(0 == i)
{
head = Create(g_dev->sys_dev[i]);
}
else
{
head = Insert(head,g_dev->sys_dev[i]);
}
}
return head;
}
void link_to_stu(struct sys_dev* head)
{
struct sys_dev* p;
int i = 0;
int max = g_dev->count_dev;
p = head;
if(head == NULL)
{
printf("empty list!\n");
}
else
{
while(p != NULL)
{
g_dev->sys_dev[i].connect_sta = p->connect_sta;
strcpy(g_dev->sys_dev[i].name,p->name);
g_dev->sys_dev[i].join_sta = p->join_sta;
g_dev->sys_dev[i].node.id = p->node.id;
g_dev->sys_dev[i].node.type = p->node.type;
g_dev->sys_dev[i].sw_sta = p->sw_sta;
g_dev->sys_dev[i].bind_dev = p->bind_dev;
p = p->next;
if(i <= max)
{
i++;
}
}
}
}
int find_id(char id, struct sys_dev* head, struct sys_dev* dev)
{
struct sys_dev* p;
p = head;
if(p == NULL)
{
printf("empty list!\n");
return 0;
}
else
{
while(p != NULL)
{
if(p->node.type == id)
{
if(dev != NULL)
{
memcpy(dev, p, sizeof(struct sys_dev));
}
return 1;
}
p = p->next;
}
}
return 0;
}
struct sys_dev* get_dev_id(char id, struct sys_dev* head)
{
struct sys_dev* p;
p = head;
if(p == NULL)
{
printf("empty list\n");
return NULL;
}
else
{
while(p != NULL)
{
if(p->node.type == id)
{
return p;
}
p = p->next;
}
}
return NULL;
}
进程间通讯
通过消息队列机制与CGI网页程序进行通讯,以共享内存作为媒介,当接收到类型1的消息时,调用stu_to_shm()更新网页;当接收到类型为2的消息时,调用shm_to_stu(),save_dev()、stu_to_link()更新全局变量g_dev、配置文件以及设备链表,以保存网页端所作的修改。
sys_ipc.h
#ifndef _SL2000_SYS_IPC_H
#define _SL2000_SYS_IPC_H
#include "config.h"
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/msg.h>
void* ipcs_pro(void* arg);
int get_msgid_web(void);
int msg_recv_webreq(int msgid);
void* set_web_shm(void);
int shm_to_stu(struct sys_all* shm_dev);
int stu_to_shm(struct sys_all* shm_dev);
#endif
sys_ipc.c
#include "sys_ipc.h"
#include "config.h"
#include "link_pro.h"
extern struct sys_all g_dev[1];
extern struct sys_dev* head_node;
int area_update_flag;
void* ipcs_pro(void* arg)
{
int msgid_web;
struct sys_all* shm_dev = NULL;
int i, cmd;
printf("ipcs pthread start...\n");
if((msgid_web = get_msgid_web()) < 0)
{
printf("msg_web error\n");
exit(1);
}
if((shm_dev = (struct sys_all*)set_web_shm()) == NULL)
{
printf("shm_web error\n");
exit(1);
}
stu_to_shm(shm_dev);
while(1)
{
cmd = msg_recv_webreq(msgid_web);
switch(cmd)
{
case 1:
stu_to_shm(shm_dev);
break;
case 2:
shm_to_stu(shm_dev);
save_dev(g_dev);
head_node = stu_to_link(head_node);
area_update_flag = 1;
break;
default:
break;
}
sleep(2);
}
}
int get_msgid_web(void)
{
int id = -1;
id = msgget((key_t)1234,0666|IPC_CREAT);
if(id == -1)
{
printf("msgget error\n");
exit(1);
}
return id;
}
int msg_recv_webreq(int msgid)
{
int i, ret;
long int msg_type;
struct st_msg_req cmd;
msg_type = WEB_UPDATE_SMG_INDEX;
if(msgrcv(msgid, (void*)&cmd,1,msg_type,IPC_NOWAIT) == -1)
{
return -1;
}
else
{
ret = cmd.req;
printf("receive %d cmd...\n",ret);
return ret;
}
return 0;
}
void* set_web_shm(void)
{
int shmid;
void* shmaddr = (void*)0;
if((shmid = shmget((key_t)1122,sizeof(struct sys_all),IPC_CREAT|0666)) < 0)
{
return NULL;
}
else
{
if((shmaddr = shmat(shmid, (void*)0, 0)) == (char*)-1)
{
return NULL;
}
}
printf("set shm ok...\n");
return shmaddr;
}
int stu_to_shm(struct sys_all* shm_dev)
{
int i;
if(shm_dev == NULL)
{
return -1;
}
memcpy(shm_dev, g_dev, sizeof(struct sys_all));
return 0;
}
int shm_to_stu(struct sys_all* shm_dev)
{
int i;
if(shm_dev == NULL)
{
return -1;
}
memcpy(g_dev, shm_dev, sizeof(struct sys_all));
return 0;
}
设备状态更新
读取光感、声控等传感器的输出值,更新传感器所绑定的LED设备的sw_sta字段,接着调用dev_sw_update()去更新LED灯的开关状态。
sw_pro.h
#ifndef _SL2000_SW_IPC_H
#define _SL2000_SW_IPC_H
void* sw_pro(void* arg);
void area_sw_update(void);
int dev_sw_update(struct sys_dev *head);
#endif
sw_pro.c
#include "config.h"
#include "sw_pro.h"
#include "link_pro.h"
extern struct sys_all g_dev[1];
extern struct sys_dev *head_node;
extern struct dev_fd g_dev_fd;
extern int area_update_flag;
extern unsigned char net_cmd;
void* sw_pro(void* arg)
{
char light_da[2];
struct sys_dev* new_dev;
struct sys_dev* find_dev;
light_da[0] = 0;
new_dev = (struct sys_dev *)malloc(sizeof(struct sys_dev));
while(1){
if(find_id(DEV_T_RAY,head_node,new_dev)==1){
if(g_dev_fd.light_fd>0){
read(g_dev_fd.light_fd,light_da,1);
}
if(new_dev->bind_dev>0 && new_dev->bind_dev<10)
if((find_dev = get_dev_id(new_dev->bind_dev,head_node)) != NULL)
find_dev->sw_sta=light_da[0];
}
if(area_update_flag ==1)
area_sw_update();
dev_sw_update(head_node);
sleep(1);
}
}
int dev_sw_update(struct sys_dev *head)
{
struct sys_dev * p;
p=head;
char da[8];
if(NULL==head){
printf("empty list!\n");
return -1;
}
while(p!=NULL){
switch(p->node.type)
{
case DEV_T_LIGHT1:
if(p->sw_sta == 1){
da[0] = J1_ON;
}else{
da[0] = J1_OFF;
}
write(g_dev_fd.relay1_fd,da,1);
break;
case DEV_T_LIGHT2:
if(p->sw_sta == 1){
da[0] = J2_ON;
}else{
da[0] = J2_OFF;
}
write(g_dev_fd.relay2_fd,da,1);
break;
case DEV_T_LIG_NET:
if(p->sw_sta == 1){
net_cmd =0x31;
}else{
net_cmd = 0x32;
}
break;
default:
break;
}
p=p->next;
}
return 0;
}
//区域处理,可以使用信号
void area_sw_update(void)
{
int area_loop,dev_loop;
struct sys_area area_val;
struct sys_dev* find_dev;
for(area_loop=0;area_loop<MAX_DEV;area_loop++){
memcpy(&area_val,&(g_dev->sys_area[area_loop]),sizeof(struct sys_area));
if(area_val.enable_flag == 1)
if(area_val.sw_sta == 1){
for(dev_loop=0;dev_loop<MAX_DEV;dev_loop++){
if((find_dev = get_dev_id(area_val.dev_id[dev_loop],
head_node)) != NULL)
find_dev->sw_sta=ON;
}
}else{
for(dev_loop=0;dev_loop<MAX_DEV;dev_loop++){
if((find_dev = get_dev_id(area_val.dev_id[dev_loop],
head_node)) != NULL)
find_dev->sw_sta=OFF;
}
}
}
area_update_flag = 0;
}
Web界面CGI程序
CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。
在开发板上搭建好boa服务器后,通过gcc将.c文件编译成cgi文件,再将相应的cgi文件以及index.html添加到boa服务器的cgi-bin目录下。
html.h
#include<stdio.h>
#define ERR_SHM 1
#define ERR_MSG 2
#define ERR_REG 3
void html_head()
{
printf("Content-type:text/html\r\n\r\n");
printf("<html>");
printf("<head><title>SL1200 intelligent light con system</title>");
printf("<meta charset=\"utf-8\" />");
//printf("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">");
printf("<style> #wrapper{width: 1000px;margin-right: auto;margin-left: auto;}");
printf(".navbar_header{float: left;}");
printf(".sidebar-collapse{width: 200px;height:600px;float: left;background: rgb(228,238,249);}");
printf("a:hover{background: yellow;}");
printf("#page-wrapper li {float: left;display: block;width:90px;height:50px;}");
printf("#page-inner{float: left;width:800px;}</style>");
}
void html_refresh(char *second, char * url)
{
printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"%s;URL=%s\">",second,url);
}
void html_title()
{
printf("</head><body><div id=\"wrapper\">");
printf("<nav class=\"navbar navbar-default top-navbar\" role=\"navigation\">");
printf("<div class=\"navbar-header\">");
printf("<button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".sidebar-collapse\"> <span class=\"sr-only\">Toggle navigation</span><span class=\"icon-bar\"></span></button>");
printf("<a href=\"#\" class=\"navbar-brand\"><strong><i class=\"icon fa fa-plane\"></i>intelligent light con system</strong></a>");
printf("<div id=\"sideNAV\"><i class=\"fa fa-bars icon\"></i></div></div></nav>");
}
void html_nav()
{
printf("<!-- NAV TOP -->");
printf("<nav class=\"navbar-default navbar-side\" role=\"navigation\">");
printf("<div class=\"sidebar-collapse\">");
printf("<ul class=\"nav\">");
printf("<li><a href=\"sys_show.cgi\"><i class=\"fa fa-dashboard\"></i>system status</a></li>");
printf("<li><a href=\"#\"><i class=\"fa fa-edit\"></i>set dev<span class=\"fa arrow\"></span></a>");
printf("<ul class=\"nav nav-second-level\">");
printf("<li><a href=\"dev_add.cgi\">add dev</a></li>");
printf("<li><a href=\"dev_con.cgi\">manage dev</a></li>");
printf("</ul></li>");
printf("<li><a href=\"#\"><i class=\"fa fa-sitemap\"></i>set area<span class=\"fa arrow\"></span></a>");
printf("<ul class=\"nav nav-second-level\">");
printf("<li><a href=\"area_add.cgi\">add area</a></li>");
printf("<li><a href=\"area_con.cgi\">manage area</a></li>");
printf("</ul></li>");
printf("<li><a href=\"#\"><i class=\"fa fa-table\"></i>set scene<span class=\"fa arrow\"></span></a>");
printf("<ul class=\"nav nav-second-level\">");
printf("<li><a href=\"#\">add scene</a></li>");
printf("<li><a href=\"#\">manage scene</a></li>");
printf("</ul></li>");
printf("<li><a href=\"./sys_info.cgi\"><i class=\"fa fa-fw fa-file\"></i>system info</a>");
printf("</li></ul></div></nav><!-- NAV SIDE -->");
}
void html_table_title(char * title,char *title1,char * title2)
{
printf("<div id=\"page-wrapper\">");
printf("<div class=\"header\">");
printf("<h1 class=\"page-header\">%s<small></small></h1>",title);
printf("<ol class=\"breadcrumb\">");
printf("<li><a href=\"index.html\">main page</a></li>");
printf("<li><a href=\"#\">%s</a></li>",title1);
printf("<li class=\"active\">%s</li>",title2);
printf("</ol></div>");
}
void html_table_head(int len,char argv[][16],char *title)
{
printf("<div id=\"page-inner\">");
//printf("<form method=\"get\" action=\"/cgi-bin/dev_add_post.cgi\">");
printf("<div class=\"row\">");
printf("<div class=\"col-md-12\">");
printf("<!-- Advanced Tables -->");
printf("<div class=\"panel panel-default\">");
printf("<div class=\"panel-heading\">%s</div>",title);
printf("<div class=\"panel-body\">");
printf("<div class=\"table-responsive\">");
printf("<table class=\"table table-striped table-bordered table hover\" id=\"dataTables-example\">");
printf("<thead>");
printf("<tr>");
printf("<th>%s</th>",argv[0]);
printf("<th>%s</th>",argv[1]);
printf("<th>%s</th>",argv[2]);
printf("<th>%s</th>",argv[3]);
printf("<th>%s</th>",argv[4]);
printf("</tr>");
printf("</thead>");
}
void html_table_end()
{
printf("</tbody></table></div></div></div><!-- End Advanced Tables --></div></div>");
printf("</from>");
}
void html_end()
{
printf("<footer>");
printf("<p>Copyright 2017 cumtzd<a target=\"_blank\" href=\"http://127.0.0.1\">Yumin Zhao</a></p>");
printf("</footer>");
printf("</footer>");
printf("</div>");
printf("<!-- PAGE INNER -->");
printf("</div>");
printf("<!-- PAGE WRAPPER -->");
printf("</div>");
printf("<script src=\"../empty files/jquery-1.10.2.js\"></script>");
printf("<script src=\"../empty files/bootstrap.min.js\"></script>");
printf("<script src=\"../empty files/jquery.metisMenu.js\"></script>");
printf("</body>");
printf("</html>");
}
void html_return_info(char* info)
{
printf("<div class=\"row\"><div class=\"col-md-12\">");
printf("<div class=\"panel panel-default\"><div class=\"panel-heading\">");
printf("setting result</div><div class=\"panel-body\"><div class=\"alert alert-success\">");
printf("<strong>%s</strong>",info);
printf("</div></div></div></div></div>");
}
void html_return_show(int ret)
{
if(ret==0){
html_return_info("ok will go back");
}else{
switch(ret){
case ERR_SHM:
html_return_info("shm err");
break;
case ERR_MSG:
html_return_info("get msg err");
break;
case ERR_REG:
html_return_info("area record full");
break;
default:
html_return_info("unknwon err");
break;
}
}
}
ipc.h
注意与主控的进程间通讯头文件进行区分,这个头文件包含的是是网页端程序进行进程间通讯是所调用的函数代码。
#ifndef __IPC_H_
#define __IPC_H_
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#define CMD_GET 1
#define CMD_SET 2
int get_msgid(void)
{
int id = -1;
id = msgget((key_t)1234,0666|IPC_CREAT);
return id;
}
void* set_web_shm(void)
{
int shmid;
void* shmaddr=(void*)0;
if((shmid=shmget((key_t)1122,sizeof(struct sys_all),0666|IPC_CREAT))<0){
return NULL;
}else{
if((shmaddr=shmat(shmid,(void*)0,0))==(char *)-1){
return NULL;
}
}
return shmaddr;
}
int msg_send(int msgid,int cmd_da)
{
struct st_msg_req cmd;
cmd.index = WEB_UPDATE_SMG_INDEX;
cmd.req = cmd_da;
if(msgsnd(msgid,(void*)&cmd,1,0)==-1)
return -1;
return 0;
}
#endif
设备添加页面程序dev_add.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "html.h"
#include "config.h"
#include "ipc.h"
void table_tr(char* name,char type,int checked)
{
char type_id[2]="0";
type_id[0] = type + '0';
printf("<tr ><td><input type=\"text\" name=\"name_%s\" value=\"%s\"> </td>",type_id,name);
//show id
printf("<td><input type=\"text\" name=\"%s\" value=\"SL_M_%s\"></td><td>",type_id,type_id);
switch(type)
{
case 1:
printf("main con");
break;
case 2:
printf("sec con");
break;
case 3:
printf("ray");
break;
case 4:
printf("body");
break;
case 5:
printf("sound");
break;
case 6:
case 7:
printf("light");
break;
case 8:
printf("net");
break;
default:
break;
}
if(checked==1)
{
printf("</td><td class=\"center\"><input type=\"radio\" name=\"join_sta%s\" value=\"1\" checked=\"checked\">connected<input type=\"radio\" name=\"join_sta%s\" value=\"0\">disconnected</td>",type_id,type_id);
}else{
printf("</td><td class=\"center\"><input type=\"radio\" name=\"join_sta%s\" value=\"1\" >connected<input type=\"radio\" name=\"join_sta%s\" value=\"0\" checked=\"checked\">disconnected</td>",type_id,type_id);
}
printf("<td class=\"center\"><button type=\"submit\" >set</button> </td></tr>");
}
int main(int argc, char *argv[])
{
int ret = 0;
int i,msgid;
struct sys_all* shm_dev;
char item_name[5][16];
if((msgid=get_msgid()) < 0){
ret = ERR_MSG;
}
if(msg_send(msgid,CMD_GET)==0){
if((shm_dev=(struct sys_all*)set_web_shm())==NULL){
ret = ERR_SHM;
}
}
html_head();
html_title();
html_nav();
html_table_title("add dev" , "set dev" , "add dev" );
if(ret != 0){
html_return_show(ret);
html_end();
return 0;
}
printf("<form method=\"get\" action=\"/cgi-bin/dev_add_post.cgi\">");
strcpy(item_name[0],"dev name");
strcpy(item_name[1],"node info");
strcpy(item_name[2],"dev type");
strcpy(item_name[3],"conn state");
strcpy(item_name[4],"send op");
html_table_head(5,item_name,"dev list");
for(i=0;i<shm_dev->count_dev;i++){
table_tr(shm_dev->sys_dev[i].name,shm_dev->sys_dev[i].node.type,
shm_dev->sys_dev[i].join_sta);
}
html_table_end();
printf("</form>");
html_end();
return 0;
}
页面处理程序dev_add_post.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "getvalue.h"
#include "html.h"
#include "config.h"
#include "ipc.h"
int main(int argc, char *argv[])
{
int ret = 0;
char *val = NULL;
char val_name[16];
char type_id[2]="0";
int i,msgid;
struct sys_all* shm_dev;
set_env(getenv("REQUEST_METHOD"),
getenv("CONTENT_LENGTH"),
getenv("QUERY_STRING"));
html_head();
html_refresh("3","/cgi-bin/dev_add.cgi");
html_title();
html_nav();
html_table_title("设备添加" , "设备设置" , "设备添加" );
if((shm_dev=(struct sys_all*)set_web_shm())==NULL){
ret = ERR_SHM;
}else{
for(i=0;i<shm_dev->count_dev;i++){
//根据配置文件实时数据,动态读取变量名join_sta+id
type_id[0] = shm_dev->sys_dev[i].node.type + '0';
strcpy(val_name,"join_sta");
strcat(val_name,type_id);
val = get_value(val_name);
shm_dev->sys_dev[i].join_sta = val[0]-'0';
strcpy(val_name,"name_");
strcat(val_name,type_id);
val = get_value(val_name);
strcpy(shm_dev->sys_dev[i].name,val);
}
}
if(ret == 0){
if((msgid=get_msgid()) < 0){
ret = ERR_MSG;
}
if(msg_send(msgid,CMD_SET) < 0)
ret = ERR_MSG;
}
html_return_show(ret);
html_end();
return 0;
}
设备控制页面程序 dev_con.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "html.h"
#include "config.h"
#include "ipc.h"
void light_tr(char* name,int join,int sw,char type)
{
char type_id[2]="0";
type_id[0] = type + '0';
printf("<tr><td>%s</td>",name);
if(join==1)
printf("<td>on line</td>");
else
printf("<td>off line</td>");
if(sw==1){
printf("<td class=\"center\"><input type=\"radio\" checked=\"checked\" value=\"1\" name=\"sw_sta%s\"> open<input type=\"radio\" value=\"0\" name=\"sw_sta%s\">close</td>",type_id,type_id);
}else{
printf("<td class=\"center\"><input type=\"radio\" value=\"1\" name=\"sw_sta%s\"> open<input type=\"radio\" value=\"0\" name=\"sw_sta%s\" checked=\"checked\">close</td>",type_id,type_id);
}
printf("<td class=\"center\"><button type=\"submit\" >set</button></td></tr>");
}
void sensor_tr(char* name,int join,int bind,char type,struct sys_all* shm_dev)
{
int i;
char selected[32] = "";
char type_id[2]="0";
type_id[0] = type + '0';
printf("<tr><td>%s</td>",name);
if(join==1)
printf("<td>online</td>");
else
printf("<td>offline</td>");
if(bind == 0)
strcpy(selected,"selected=selected");
printf("<td><select name=\"bind%s\"><option value=\"0\" %s >release attach</option>",type_id,selected);
for(i=0;i<shm_dev->count_dev;i++){
strcpy(selected,"");
if(bind == shm_dev->sys_dev[i].node.type)
strcpy(selected,"selected=selected");
if(shm_dev->sys_dev[i].node.type==DEV_T_LIGHT1 || shm_dev->sys_dev[i].node.type==DEV_T_LIGHT2 || shm_dev->sys_dev[i].node.type==DEV_T_LIG_NET)
printf("<option value=\"%d\" %s >%s</option>",shm_dev->sys_dev[i].node.type,selected,shm_dev->sys_dev[i].name);
}
printf("</select></td>");
printf("<td class=\"center\"><button type=\"submit\" >set</button></td></tr>");
}
int main(int argc, char *argv[])
{
int ret = 0;
int i,msgid;
struct sys_all* shm_dev;
char item_name[5][16];
if((msgid=get_msgid()) < 0){
ret = ERR_MSG;
}
if(msg_send(msgid,CMD_GET)==0){
if((shm_dev=(struct sys_all*)set_web_shm())==NULL){
ret = ERR_SHM;
}
}
html_head();
html_title();
html_nav();
html_table_title("manage dev" , "set dev" , "manage dev" );
if(ret != 0){
html_return_show(ret);
html_end();
return 0;
}
printf("<form method=\"get\" action=\"/cgi-bin/dev_con_post.cgi\">");
strcpy(item_name[0],"dev name");
strcpy(item_name[1],"on/off line");
strcpy(item_name[2],"switch");
strcpy(item_name[3],"hand op");
html_table_head(4,item_name,"light dev");
for(i=0;i<shm_dev->count_dev;i++){
if(shm_dev->sys_dev[i].node.type==DEV_T_LIGHT1 || shm_dev->sys_dev[i].node.type==DEV_T_LIGHT2 || shm_dev->sys_dev[i].node.type==DEV_T_LIG_NET)
light_tr(shm_dev->sys_dev[i].name,shm_dev->sys_dev[i].join_sta,
shm_dev->sys_dev[i].sw_sta,shm_dev->sys_dev[i].node.type);
}
html_table_end();
strcpy(item_name[0],"dev name");
strcpy(item_name[1],"on/off line");
strcpy(item_name[2],"attach dev");
strcpy(item_name[3],"hand op");
html_table_head(4,item_name,"detectint dev");
for(i=0;i<shm_dev->count_dev;i++){
if(shm_dev->sys_dev[i].node.type==DEV_T_RAY)
sensor_tr(shm_dev->sys_dev[i].name,shm_dev->sys_dev[i].join_sta,
shm_dev->sys_dev[i].bind_dev,shm_dev->sys_dev[i].node.type,shm_dev);
}
html_table_end();
printf("</form>");
html_end();
return 0;
}
设备管理页面处理程序 dev_con_post.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "getvalue.h"
#include "html.h"
#include "config.h"
#include "ipc.h"
int main(int argc, char *argv[])
{
int ret = 0;
char *val = NULL;
char val_name[16];
char type_id[2]="0";
int i,msgid;
struct sys_all* shm_dev;
set_env(getenv("REQUEST_METHOD"),
getenv("CONTENT_LENGTH"),
getenv("QUERY_STRING"));
html_head();
html_refresh("3","/cgi-bin/dev_con.cgi");
html_title();
html_nav();
html_table_title("manage dev" , "set dev" , "manage dev" );
if((shm_dev=(struct sys_all*)set_web_shm())==NULL){
ret = ERR_SHM;
}else{
for(i=0;i<shm_dev->count_dev;i++){
type_id[0] = shm_dev->sys_dev[i].node.type + '0';
strcpy(val_name,"sw_sta");
strcat(val_name,type_id);
val = get_value(val_name);
if(val != NULL)
shm_dev->sys_dev[i].sw_sta = val[0]-'0';
strcpy(val_name,"bind");
strcat(val_name,type_id);
val = get_value(val_name);
if(val != NULL)
shm_dev->sys_dev[i].bind_dev = val[0]-'0';
}
}
if(ret == 0){
if((msgid=get_msgid()) < 0){
ret = ERR_MSG;
}
if(msg_send(msgid,CMD_SET) < 0)
ret = ERR_MSG;
}
html_return_show(ret);
html_end();
return 0;
}
cgi处理头文件getvalue.h
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define FIELD_LEN 60 /*how long each name or value can be*/
#define NV_PAIRS 15 /*how many name=value pairs can process*/
typedef struct name_value_st{
char name[FIELD_LEN + 1];
char value[FIELD_LEN + 1];
}name_value;
name_value name_val_pairs[NV_PAIRS];
int num_pairs = 0;/*pairs number*/
const char *M = NULL;
const char *L = NULL;
const char *S = NULL;
static int iread = 0;
void unescape_url(char *url);
void set_env(const char *r_mth, const char *c_len,const char *q_str);
char* get_value(const char *name);
int get_input(void);
void send_error(char *error_test);
char x2c(char *what);
void load_nv_pair(char *tmp_buffer, int nv_entry_number_to_load);
void set_env(const char *r_mth, const char *c_len,const char *q_str)
{
M = r_mth;
L = c_len;
S = q_str;
}
char* get_value(const char *name)
{
int nv_entry_number = 0;
int i = 0;
char* val = NULL;
char *tname = NULL;
if(iread == 0)
{
if ( !get_input()){
return "error";
exit(EXIT_FAILURE);
}
}
for(i = 0; i < num_pairs; i++ )
{
val = name_val_pairs[nv_entry_number].value;
tname = name_val_pairs[nv_entry_number].name;
nv_entry_number++;
if( strcmp(tname,name) == 0 )
{ break;}
else
{ val = NULL;
tname = NULL;
}
}
// printf("\r\n");
iread++;//read value times
return val;
exit(EXIT_SUCCESS);
}
int get_input(void)
{
int nv_entry_number = 0;
int got_data = 0;
char *ip_data = NULL;
int ip_length = 0;
char tmp_buffer[(FIELD_LEN * 2) + 2];
int tmp_offset = 0;
char *tmp_char_ptr = NULL;
int chars_processed = 0;
/*如果是POST方法提交,数据导入ip_data*/
// tmp_char_ptr = getenv("REQUEST_METHOD");
tmp_char_ptr = (char*)M;
if ( tmp_char_ptr)
{
if(strcmp(tmp_char_ptr, "POST") == 0)
{
// tmp_char_ptr = getenv("CONTENT_LENGTH");
tmp_char_ptr = (char*)L;
if (tmp_char_ptr){
ip_length = atoi(tmp_char_ptr);
ip_data = malloc(ip_length + 1);
if (fread(ip_data, 1, ip_length, stdin) != ip_length)
{
send_error("Bad read from stdin");
return(0);
}
ip_data[ip_length] = '\0';
got_data = 1;
}
}
}
/*如果是GET方法提交,数据导入ip_data*/
// tmp_char_ptr = getenv("REQUEST_METHOD");
tmp_char_ptr = (char*)M;
if ( tmp_char_ptr)
{
if(strcmp(tmp_char_ptr, "GET") == 0)
{
// tmp_char_ptr = getenv("QUERY_STRING");
tmp_char_ptr = (char*)S;
if (tmp_char_ptr)
{
// ip_length = atoi(tmp_char_ptr);
ip_length = strlen(tmp_char_ptr);
ip_data = malloc(ip_length + 1);
// strcpy(ip_data, getenv("QUERY_STRING"));
strcpy(ip_data, (char*)S);
ip_data[ip_length] = '\0';
got_data = 1;
}
}
}
if (!got_data){
send_error("No data received");
}
if (ip_length <= 0){
send_error("Input length <= 0");
return(0);
}
memset(name_val_pairs, '\0', sizeof(name_val_pairs));
tmp_char_ptr = ip_data;
while (chars_processed <= ip_length && nv_entry_number < NV_PAIRS)
{
tmp_offset = 0;
while (*tmp_char_ptr && *tmp_char_ptr != '&' && tmp_offset < FIELD_LEN)
{
tmp_buffer[tmp_offset] = *tmp_char_ptr;
tmp_offset++;
tmp_char_ptr++;
chars_processed++;
}
tmp_buffer[tmp_offset] = '\0';
/*decode and load the pair*/
load_nv_pair(tmp_buffer, nv_entry_number);
/*move on to the next name=value pair*/
tmp_char_ptr++;
nv_entry_number++;
}
free(ip_data);
ip_data = NULL;
return(1);
}
void send_error(char *error_text)
{
printf("Content-Type: text/html\r\n");
printf("\r\n");
printf("Woops:- %s\r\n",error_text);
}
void load_nv_pair(char *tmp_buffer, int nv_entry)
{
int chars_processed = 0;
char *src_char_ptr = NULL;
char *dest_char_ptr = NULL;
/*get the part before the '=' sign*/
src_char_ptr = tmp_buffer;
dest_char_ptr = name_val_pairs[nv_entry].name;
while (*src_char_ptr && *src_char_ptr != '=' && chars_processed < FIELD_LEN)
{
/*chang a '+' to a ' ' */
if (*src_char_ptr == '+')
{
*dest_char_ptr = ' ';
}else{
*dest_char_ptr = *src_char_ptr;
}
dest_char_ptr++;
src_char_ptr++;
chars_processed++;
}
/*skip the '=' character*/
if (*src_char_ptr == '=')
{
num_pairs++;
/*get the part after the '=' sign*/
src_char_ptr++;
dest_char_ptr = name_val_pairs[nv_entry].value;
chars_processed = 0;
while (*src_char_ptr && *src_char_ptr != '=' && chars_processed < FIELD_LEN)
{
/*chang a '+' to a ' ' */
if (*src_char_ptr == '+')
{
*dest_char_ptr = ' ';
}else{
*dest_char_ptr = *src_char_ptr;
}
dest_char_ptr++;
src_char_ptr++;
chars_processed++;
}
}
unescape_url(name_val_pairs[nv_entry].name);
unescape_url(name_val_pairs[nv_entry].value);
}
void unescape_url(char *url)
{
int x,y;
for (x=0,y=0; url[y]; ++x,++y ){
if ( (url[x] = url[y]) == '%'){
url[x] = x2c(&url[y+1]);
y += 2;
}
}
url[x] = '\0';
}
/* %xx:用其十六进制ASCII码值表示的特殊字符。根据值xx将其转换成相应的ASCII字符*/
char x2c(char *what)
{
register char digit;
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
digit *= 16;
digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
return(digit);
}