⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disphistory.c

📁 采用MINIGUI开发的一套GUI界面
💻 C
📖 第 1 页 / 共 3 页
字号:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <pwd.h>
#include <math.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "common.h"
#include "fonts.h"
#include "disphistory.h"
void WriteHisIndex(int id );


unsigned char file_name[20];
/*
 历史数据处理 记录间隔分为1、2、5、10、30、60、120秒,共7种
 文件分为文件头+文件体,如果记录满了则清零重新开始
假设存储介质为128M的CF卡                    1  2800 0000
30个通道*3600秒*24小时*2字节每条记录*24天=  1  2441 6000 
每秒设置4个字节记录每秒的offset,256四次方 = 42 9496 7296
一天需要记录的offset为3600*24*4=345600字节
20天需要6912000   30天需要10368000字节 10M	   
文件头设置30天index的位置,最多存贮30天的数据,如果通道数目太多,
则根据容量存贮
文件头:年月日时分秒+10368000=10368006
文件体:从10368007开始 
每条数据先保存三个字节

*/
//公共区
//文件头: 当前时刻,当前记录在文件中的位置
//当前记录所属索引号(即总共的索引数目)
//区间:  0-10
//建立文件头
//不同的通道不同的文件
void  SetupHistoryFile(int id)
{	
union {
    int number;
    BYTE byte[4];
}data;

	BYTE buf[6];
	struct stat file;
	long interval;
int temp;
	unsigned char *name;
	unsigned char *p;
	FILE *fd;
time_t  now;
time(&now);
	   //得到通道信息
	   name=channel_conf[id].name;
	   name[4]='\0';

	 //根据通道名  本年月自动生成文件名    
	 sprintf(file_name,"data/%02d%02d%02d%d.dat",id+1,((year-1900)%100),mont,files_number);
	 file_name[18]='\0';	
	 if(stat(file_name,&file)<0)//假设不存在本文件则新建
	 	{
	 	system("mkdir data");
      	 	fd=fopen(file_name,"w+b");
		channel_hist[id].fd=fd;
if(id==1)printf("%d setup file time is %d ",id,now);
   
		data.number=now;
		//写入当前时间	
      		 fseek(fd,0,SEEK_SET); 	   
		memcpy(buf,data.byte,4);
             fwrite(buf,1,4,fd);    
			 
		//写入当前时间到第一个索引区
      		 fseek(fd,16,SEEK_SET); 	   
              fwrite(buf,1,4,fd);     
			 
             //写入刚开始记录的数据位置16700=0X 41 3C到公共区
             buf[0]=0X3C-3; //放数原则:高位放高位
		buf[1]=0X41;
		buf[2]=0;
		 fseek(fd,6,SEEK_SET); 
		fwrite(buf,1,3,fd);   
		temp=buf[2]*256*256+buf[1]*256+buf[0];
if(id==1)printf("record first addr=%d \n ",temp );	
		//写入新记录所在索引号(总共的索引数目)
		buf[0]=1; 	//放数原则:高位放高位
		buf[1]=0;	//
		buf[2]=0;
		 fseek(fd,9,SEEK_SET); 
		fwrite(buf,1,3,fd);   
	       //-----------------------首条索引建立完毕
		interval=channel_hist[id].interval;//秒为单位
if(id==1)printf("record first interval=%d \n ",interval );			
		buf[2]=(interval/256)/256;
		buf[1]=interval/256;
		buf[0]=interval%256;
      		 fseek(fd,16+4,SEEK_SET); 	   
             fwrite(buf,1,3,fd);    

		buf[0]=0;buf[1]=0;buf[2]=0;//记录条数=0
      		 fseek(fd,16+4+3,SEEK_SET); 	   
             fwrite(buf,1,3,fd);    

             buf[0]=0X3C; //放数原则:高位放高位
		buf[1]=0X41;
		buf[2]=0;
		 fseek(fd,16+4+3+3 ,SEEK_SET); 
		fwrite(buf,1,3,fd);   
		//-----------------------首条索引建立完毕
			 
              
	 	}	
	 else
	 	{
		//建立新索引
      	 	channel_hist[id].fd=fopen(file_name,"r+w+b");
		
		
		printf("f.");
		WriteHisIndex(id);
	 	}
		
	  //表示建立好
}
//写入历史数据索引从地址为16位置开始
//每当有新的通道要开始记录时,添加一条索引
//假设平均每小时添加一条则一个月索引总条数M0NT_INDEX_MAX为:34 BYTE*31*24=16650  BYTE
//当本月索引数需要超过M0NT_INDEX_MAX时候,则建立新文件
/*
//索引区
区间: 16-16650
组成:
记录条数=历史记录时间段总数     		3 BYTE	最大每2秒1段: 2678400/2= 31天*24*3600/2
本记录段开始的时间		6  BYTE	最大为:年月日时分秒
记录间隔						3  BYTE  最大为:一个月一次
记录条数						3  BYTE  最大为:2678400=31天*24*3600
本记录段第一条记录在文件中的位置 :3  BYTE   可以寻址到63M


*/
#define IX_FIR 16
#define IX_LEN 13
//当通道 启用与关闭时,时间间隔有改变时增加新索引
void WriteHisIndex(int id )
{
union {
    int number;
    BYTE byte[4];
}ndata;
union {
    int time;
    BYTE byte[4];
}data;
	FILE *fd;
	BYTE data_addr[3];
	int index_number;
	BYTE  buf[16];
	int index_addr;
	time_t  now;

time(&now);

if(id==1)printf("setup index time:%d  ",now);

	bzero(buf,sizeof(buf));

      	fd=channel_hist[id].fd;
	
	//得到索引号,刚开始时候是1
	fseek(fd,9,SEEK_SET); 	
	fread(buf,1,3,fd);
	index_number=buf[2]*256*256+buf[1]*256+buf[0];
if(id==1)printf("old index =%d  ",index_number);	
      ndata.number=index_number+1;
       memcpy(buf,ndata.byte,3);
       //更改文件头当前索引号
   	 fseek(fd,9,SEEK_SET); 
	fwrite(buf,1,3,fd);     

	 
	//得到当前记录地址
	fseek(fd,6,SEEK_SET); 	
	fread(ndata.byte,1,3,fd);
	 ndata.number=ndata.number+3; 	
if(id==1)printf("  addr= %d  ",ndata.number);	 
	 memcpy(buf+10,ndata.byte,3); //当前记录地址

	 data.time=now;
	 memcpy(buf,data.byte,4);
if(id==1)printf("  time= %d  ",data.time);	

	ndata.number=channel_hist[id].interval;
	 memcpy(buf+4,ndata.byte,3);
 	 
	 ndata.number=0; 			
	 memcpy(buf+7,ndata.byte,3); //记录条数
if(id==1)printf("record  number=%d  ",ndata.number );			
	 
       //开始写新索引
       index_addr=index_number*13+16;
if(id==1)printf(" index number= %d  \n",index_number+1);		   
   	 fseek(fd,index_addr,SEEK_SET); 
	fwrite(buf,1,13,fd);     



	   
	//fclose(fd);		
}


//根据索引写入数据,起始:DATA_FIRST_ADDR=16650+50
//从索引段后开始,空出50个字节即:16650+50处开始
//本数据段长度:与需要记录的通道总数有关,buffer
//记录由纯数据组成
//区间: 16700 BYTE -63M

void WriteHisData(int id )
{
union {
    int number;
    BYTE byte[4];
}ndata;

union {
    short ipv;
    BYTE byte[3];
}data;

BYTE buffer[100];
BYTE *p;
	FILE *fd;
	int last_record_addr;	
	int record_number;
	int index;
	BYTE  buf[3];
      int length;
	time_t  now;

time(&now);


	bzero(buffer,sizeof(buffer));

      	fd=channel_hist[id].fd;
	//读取索引号
	fseek(fd,9,SEEK_SET); 
	fread(buf,1,3,fd);
	index=buf[2]*256*256+buf[1]*256+	buf[0];
//if(id==1)printf(" index=%d ",index );	
	//读取索引的记录总条数
	fseek(fd,(index-1)*13+16+7,SEEK_SET); //索引号1对应地址23
	fread(buf,1,3,fd);
	record_number=buf[2]*256*256+buf[1]*256+	buf[0];

	//写入新的记录总数
	ndata.number=record_number+1;
//if(id==1)printf("record_num=%d  ",ndata.number );	
	if(record_number>0xfffffe)
//printf("%d record data overflow\n",id );	
	ndata.byte[3]=0;
	memcpy(buf,ndata.byte,3);
	fseek(fd,(index-1)*13+16+7,SEEK_SET); 	//index=1对应的地址为23 
      	fwrite(buf,1,3,fd); 
	//读出上次记录的地址		
	fseek(fd,6,SEEK_SET); 
	fread(buf,1,3,fd);
	last_record_addr=buf[2]*256*256+buf[1]*256+	buf[0];
	last_record_addr=last_record_addr+3;//计算出新数据地址
//if(id==1)printf("addr=%d    ",last_record_addr );	
 	data.ipv=channel_disp[id].ipv;
	data.byte[2]=channel_disp[id].dot;//小数点
//if(id==1)printf(" data=%d %d %d  \n",data.byte[2],data.byte[1],data.byte[0]);		

	memcpy(buffer,data.byte,3);
	//填写新数据
	fseek(fd,last_record_addr,SEEK_SET); 	//定位到当前	
      	fwrite(buffer,1,3,fd); 
	//更新文件头当前数据地址
	if(last_record_addr>0xfffffe){
		SetupHistoryFile(2);last_record_addr=0x00413c;
		}
	ndata.number=last_record_addr;
	memcpy(buf,ndata.byte,3);
	fseek(fd,6,SEEK_SET); 
	fwrite(buf,1,3,fd);   //写入3个字节	

}      

//根据通道开启情况建立历史文件
		//根据记录方法与时间间隔记录
		
void Record(int id)
{
int type;//记录方式
int interval;
BOOL open ;
static long oldtime=0;

		 //进行历史记录
	       //历史文件的建立在确认通讯注册后
		//根据记录方法得到需要记录的值
	type=channel_hist[id].record_type;	 //0:close 1:实时,2:平均,3:最小,4:最大

	interval=channel_hist[id].interval;	 //0  1秒  1:5秒    2:10 秒   3:30秒    4 :60 秒 5:120秒 
interval=2;
      if(nowseconds>=oldtime+interval)
      	{
//if(id==1)printf(" interval=%d ",interval );	      	
 WriteHisData(1 );//写入20个数据
	oldtime=nowseconds;
      	}

}


//当前时间对应的历史索引
//
int  ReadHisIndex( int point_time )
{
	FILE *fd;
	int index;	
	BYTE  buf[3];
	
     // 	fd=fopen(file_name,"r+b");	
	//从 文件头7-9字节读出上一次记录位置
	fread(buf,sizeof(buf[0]),6,fd);
	index=buf[2]*256*256+buf[1]*256+buf[0];
	
//	printf("last_record_addr=%d",index);
	//fclose(fd);
return index;
}
//根据时间点寻找记录  (秒数)
//根据索引,读N个数据
//
//  first:本索引开始的第几条记录
// length:要读的记录总条数
//,
//firsttime一定要在最初的时间以后
//lasttime-fisrttime不能超过1屏幕显示的数据点个数640
int  	ReadHisData(int id,long  firsttime,long lasttime )
{
union {
    short ipv;
    BYTE byte[3];
}data;
int dot;
union {
    long time;
    BYTE byte[4];
}timedata;
int i;
int validindex=0;// 有数据的索引号总数
int index;		//	索引号
BYTE buf2[2000];
long temp_time=0;
long first_t,last_t;	//	本索引对应的起始终止时间
int interval;		//记录间隔
short number;	//	本索引的记录的总条数
unsigned short seconds;   //要读出的时间段秒数
	FILE *fd;
	BYTE  buf[4];   //  3字节运算用
	BYTE  buffer[10];   //  3字节运算用
	int totalindex;       //总索引数
	int index_addr;		//索引的地址
	int data_firstaddr;	//	数据首址
	int data_length;	//	数据首址
	int length;    //读数据用
	bzero(buf2,sizeof(buf2));
bzero(buffer,sizeof(buffer));
for(id=0;id<2;id++)
{
validindex=0;
      	fd=channel_hist[id].fd;
	//读出总的索引号	
	fseek(fd,9,SEEK_SET); 
	fread(buf,1,3,fd);
	totalindex=buf[2]*256*256+buf[1]*256+	buf[0];
//	printf("totalindex=%d\n",totalindex);
//	if(index>totalindex)return 0;
	//根据总索引数计算出总的记录条数
	length=0;
	data_length=0;
//printf("firsttime=%d lasttime=%d\n ",firsttime,lasttime);	
temp_time=firsttime;
//一次读取历史数据绘制点不可超过640个
//  假设每个存储的数据时间间隔为interval秒,
//假设有M=totalindex段数据时间间隔分别为interval[index]
//那么包括数据空白区,时间分为:interval[index*2-1]
//  需要显示的数据最大所占的时间为640*interval秒
//if(totalindex>10)	record=(STRURECORD*)realloc(record,(totalindex)*sizeof(STRURECORD ));

//取最近的时间的数据
if((lasttime-firsttime)>640*interval)firsttime=lasttime-1280;
for(index=1;index<=totalindex;index++)
	{

	 seconds=3;
	//定位索引位置
	index_addr=(index-1)*13+16;  //索引位置第一个为16
	//本索引的开始时间
	fseek(fd,index_addr,SEEK_SET); 	
	fread(buffer,1,13,fd);//读索引
	memcpy(timedata.byte,buffer,4);
	first_t=timedata.time;

	interval=buffer[6]*256*256+buffer[5]*256+buffer[4];
	
	number=buffer[9]*256*256+buffer[8]*256+buffer[7];
	
	data_firstaddr=buffer[12]*256*256+buffer[11]*256+buffer[10];

last_t=interval*number+first_t;
//printf("first_t=%d last_t=%d\n ",first_t,last_t);
	
		
	if(first_t>=lasttime)
		{
//		printf("flag 0\n");
		index=totalindex+1;//跳出FOR 循环
		}
	else{
		if(first_t>=firsttime)
		{		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -