主程序包含了全局数据结构定义、系统配置文件生成或加载、建立四个独立线程并运行。
一、全局数据结构类型
封装每个设备的属性形成设备结构体类型(包含了:设备名、设备号、连接状态、开关状态、指向的下一个设备指针等)
封装每个区域的属性形成区域结构体类型(包含了:区域名、组成区域的设备号数组、区域开关状态等)
总数据结构类型:将上面两个类型数组化,从而开辟了可包含多个设备及区域的内存空间
同时将各个硬件设备及网络设备的文件描述符(网络设备为accept后的套接字)集合起来形成设备描述符结构类型
定义数据结构类型的config.h文件如下:
#ifndef __SL2000_H_
#define __SL2000_H_
#include <stdlib.h>
#include <stdio.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_AREA 4//系统最大区域容量
#define MAX_NET 2//系统最大连接的网络客户端
#define J1_OFF 0x00
#define J1_ON 0X01
#define J2_OFF 0X00
#define J2_ON 0X01
#define LIGHT_DEV "/dev/4418_light" //光线感应设备
#define MIC_DEV "/dev/4418_mic" //声音感应设备
#define PIR_DEV "/dev/4418_hongwai" //红外感应设备
#define RELAY1_DEV "/dev/4418_relay1" //延迟开关1
#define RELAY2_DEV "/dev/4418_relay2"
#define SEARCH_DEV "/dev/4418_search" //5-3.3v电压转换设备
#define ID_BASE 1
struct node_info{
int id; //设备编号,由于本项目设备较少,一类设备也就只有一个,
//故直接用设备类型来操作各个设备了
char ip[16]; //设备ip,暂且没用到
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];//存储accept后的套接字
};
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_AREA];//区域列表
int net_user[MAX_NET];//网络节点
int count_dev;//连接设备计数
};
//消息队列用到的消息结构体类型
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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.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,"Non named device");
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 device");//初始化主控设备连接
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,connect_sta=%d,sw_sta=%d,bind_dev=%d,delay=%d",
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(NULL==(fp=fopen(CONFIG_FILE,"wb"))){
printf("Config file open null....\n");
return -1;
}
printf("\nSave system data!\n");
fwrite(dev,sizeof(*dev),1,fp);
fclose(fp);
return 0;
}
int load_dev(struct sys_all * dev)
{
FILE * fp;
memset(dev,0,sizeof(*dev));
if(NULL==(fp=fopen(CONFIG_FILE,"rb"))){
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;
}
三、主程序(daemon.c)
就是建立全局变量、生产或打开配置文件用于初始化全局变量、建立四个线程并运行之
#include <pthread.h>
#include "config.h"
#include "sys_ipc.h"
#include "link_pro.h"
#include "dev_pro.h"
#include "net_pro.h"
#include "sw_pro.h"
//全局数据
struct sys_all g_dev[1]; //系统配置结构体全局变量
struct sys_dev *head_node =NULL; //系统设备动态链表头指针
struct dev_fd g_dev_fd; //系统设备文件描述符
int area_update_flag=0;
//系统初始化函数
int init_sys(void)
{
int i;
printf("init system...\n");
load_dev(g_dev);//初始化g_dev
head_node=stu_to_link(head_node);//创建设备结构链表头结点
dev_print(head_node);//打印设备链表中的设备属性
return 0;
}
//main 函数
int main()
{
pthread_t pth_ipc,pth_dev,pth_sw,pth_net;
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_create(&pth_net,NULL,net_pro,NULL);
pthread_join(pth_dev,NULL);
pthread_join(pth_ipc,NULL);
pthread_join(pth_sw,NULL);
pthread_join(pth_net,NULL);
return 0;
}