📄 disphistory.c
字号:
#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 + -