// XDemo29: Reads information from text files(advance) // Compiler: BC++ 3.1 // Compile mode: large // Project: user.c // v7000.c // vModbus.c [after XS8_3002] // ..\LIB\8000E.Lib // ..\LIB\TCPIPL.Lib // ..\LIB\XS8_NNNN.Lib, with NNNN being the lib file's version. // // 19 [KeyName] [Type] // KeyName: the item that programs want to read out // its setting form a text file(config.dat) // You must position the KeyName after one * character. // Type:i --> for reading long integer(Dec) // s --> for reading string (20 bytes max.) // f --> for reading float value // h --> for reading unsigned long ingeger(Hex) // // 19 baudrate i --> reads baudrate from config.dat // 19 ID s --> reads ID from config.dat // 19 pi f --> read pi (3.141592654) from config.dat // 19 Hex_Value h --> read Hex_Value (12AF) from config.dat // 19 (any string) t --> read test string from config.dat // // In many application, users need one text file to record some information. // And the program can read it. // You can use GetProFileInt, GetProFileStr to get specific information // in text files. // // The format of the text file (config.ini) must follow the rules: // 1. The item information you want to read must be positioned after '*'. // 2. The comment cann't contain any '*'. // 3. KeyName and '=' must be seperated by least one space character. // 4. If the setting of KeyName is string type, you must add t // least one space character to the end of file(EOF). // For example: // ===================================== // config file sample for demo29 // ===================================== // * baudreate = 115200 ;integer type // * Debug = on ;string type // * slot0 = I8024 ;string type ID name // ===================================== // comment........... // // Hardware: 8000E // // Note: to run this demo, you must load one extra text file // (I wrote config29.ini for this demo) into 8000E. // // Refer 8000\843x883x\TCP\Doc\[Big5|Eng|Gb2312]\Vxcomm.htm // 8000\843x883x\TCP\Xserver\Xserver.htm // 8000\843x883x\TCP\Xserver\Function.htm // to get more information. // // [2/Feb/2002] by Kevin #include #include #include "..\lib\module.h" static FILE_DATA far *config; unsigned long FSeek(FILE_DATA far *file_pointer,char cMark,unsigned long lStart,int iTh); // search the cMark from lStart until reach the iTh(th) cMark, // and return the position next to the cMark. long GetProFileInt(FILE_DATA far *file_pointer,char* sKeyName,long lDefault); // Gets integer of sKeyName, the sKeyName in text file must be after one '*'. // If cannot find the sKeyName, return the lDefault. // If cannot find the value of the sKeyName, return the lDefault. int GetProFileStr(FILE_DATA far *file_pointer,char* sKeyName,char* sResult,char* sDefault); // Gets string of sKeyName, the sKeyName in text file must be after one '*'. // If cannot find the sKeyName, sResult=sDefault. // If cannot find the string of the sKeyName, sResult=sDefault. // Return value: length of sResult // I use GetProFileStr to replace GetProFileVal. //float GetProFileVal(FILE_DATA far *file_pointer,char* sKeyName,float fDefault); // Gets float value of sKeyName, the sKeyName in text file must be after one '*'. // If cannot find the sKeyName, return the fDefault. // If cannot find the value of the sKeyName, return the fDefault. void UserCount(void) { } void UserEnd(void) { Print("Call UserEnd().\r\n"); StopUserTimerFun(); } void UserInit(void) { /* In this function, user CAN: 1. initialize user's program. 2. set time interval for calling UserCount(). 3. set initial value of I/O or variables for UserLoopFun(). 4. set initial value of I/O or variables for another functions. 5. change the default TCP PORT 10000/9999/502 to others value. [after XS8_3004.lib] Syntax: Port10000=newport_10000; for calling UserCmd (user.c) Port9999=newport_9999; for calling VcomCmd7000 (v7000.c) Port502=newport_502; for calling VcomCmdModbus (vModbus.c) [after XS8_3002.lib] PortUser=newport_User; for calling VcomCmdUser (user.c) [after XS8_3005.lib] Default port value: Port10000=10000; Port9999=9999; Port502=502; PortUser=0; If the port value is 0, Xserver will not listen that port. That means the port will be disable. Please refer to XDemo09 & XDemo11 for example code */ InitLib(); // To use [MiniOS7 for 8000 new], you need call this function // at begin of c program. // XS8_nnnn.Lib has not add this function to it's kernel. // So, you need call that in UserInit. // To know what difference between original MiniOS7 and new MiniOS7, // please refer CD:\Napdos\MiniOS7\8000new\8000-new_eng.txt // 8000-new_big5.txt // 8000-new_gb2312.txt // [26,Oct,2002] by Kevin config=GetFileInfoByName("config29.ini"); //Opens one file by name. SetBaudrate(1, 115200); printCom1("File ize=%lu bytes\n\r",config->size); printCom1(" day=%02d\n\r",config->day); printCom1(" month=%02d\n\r",config->month); printCom1(" year=%02d\n\r",config->year+1980); printCom1(" hour=%02d\n\r",config->hour); printCom1(" minute=%02d\n\r",config->minute); printCom1(" second=%02d\n\r",config->sec*2); } void UserLoopFun(void) { } int UserCmd(unsigned char *Cmd,unsigned char *Response) { // user's command interpreter // Maximum length of Cmd is 1458 bytes. // Maximum length of Response is 1024 bytes. char sItem[20]; char cType; //i,I: long integer; //s,S: string; //f,F: float value; //h,H: hex value; //t,T: to get test string; float fValue; long lValue; char sString[40]; int iRet; if (Cmd[0]) /* Not Null command */ { sscanf(Cmd,"%s %c",&sItem,&cType); switch(cType) { //Gets integer value case 'i': case 'I': lValue=GetProFileInt(config,&sItem,1); // Default value=1 sprintf(Response,"%s=%ld",sItem,lValue); break; //Gets string case 's': case 'S': iRet=GetProFileStr(config,&sItem,&sString,"Error"); // Default string=Error sprintf(Response,"%s=%s",sItem,sString); break; //Gets float value case 'f': case 'F': iRet=GetProFileStr(config,&sItem,&sString,"1.23"); // Default string=1.23 sscanf(sString,"%f",&fValue); sprintf(Response,"%s=%f",sItem,fValue); break; //Gets hexadecimal integer value case 'h': case 'H': iRet=GetProFileStr(config,&sItem,&sString,"FFFF"); // Default string=FFFF sscanf(sString,"%lx",&lValue); sprintf(Response,"%s=%lx(Hex)",sItem,lValue); break; //Gets test string case 't': case 'T': iRet=GetProFileStr(config,"test",&sString,"Default");// Default string=Default sprintf(Response,"test=%s",sString); break; default: strcpy(Response,"Type error!"); break; } return 1; /* return OK */ } strcpy(Response,"Failed"); return 1; /* return OK */ } int VcomUserBinaryCmd(TCPREADDATA *p) { /* VXCOMM.EXE 2.6.12(09/04/2001) or later will support this function. TCP PORT 10000, command 23 will call this function. user can get the following message: p->ReadUartChar : the buffer store the command data(include "23") Maximum length of p->ReadUartChar is 32767 bytes. p->Length : the command data length(include the two byte "23") p->Socket : the socket number that receives the command, that is, when the user function wants to return a message to the client, just use the socket to send data. usage: VcomSendSocket(p->Socket,pdata,datalength); */ VcomSendSocket(p->Socket,"User-defined command(23)",24); // return 24 bytes. return 1; /* any value will be accept */ } int VcomCmdUser(TCPREADDATA *p) { /* VCOM3005 (Feb,22,2002) or later will call this function for PortUser. When packets received by TCP PORT PortUser(user defined) of 7188E/8000E, Xserver will call this function. user can get the following message: p->ReadUartChar : the buffer store the command data. Maximum length of p->ReadUartChar is 32767 bytes. p->Length : the command data length. p->Socket : the socket number that receive the command, that is when the user function wants return message to the client, just use the socket to send data. usage: VcomSendSocket(p->Socket,pdata,datalength); */ /* here just send back the command to the client. */ VcomSendSocket(p->Socket,p->ReadUartChar,p->Length); return 1; /* any value will be accept */ } unsigned long FSeek(FILE_DATA far *file_pointer,char cMark,unsigned long lStart,int iTh) { // This function seeks the mark letter from the start position // to the EOF(end of file). // cMark: find the position next to the cMark. // lStart: the start position to seek the cMark. // (0: start position of the file) // iTh: seek the iTh(th) cMark. // // Return value: // 0: cannot find the cMark // >0: the offset position next to the cMark /* typedef struct { unsigned mark; unsigned char fname[12]; unsigned char year; unsigned char month; unsigned char day; unsigned char hour; unsigned char minute; unsigned char sec; unsigned long size; char far *addr; unsigned CRC; unsigned CRC32; } FILE_DATA; */ char c; unsigned long i; int iOrder; i=lStart; iOrder=1; while(i<(file_pointer->size-1)) { c=file_pointer->addr[i]; if(c==cMark) if(iOrder==iTh) return ++i; // return the position next to the cMark. else iOrder++; i++; } return 0; } long GetProFileInt(FILE_DATA far *file_pointer,char* sKeyName,long lDefault) { // If cannot find the sKeyName, return the lDefault. // If cannot find the value of the sKeyName, return the lDefault. unsigned long lPointer=0; char sTemp[20]; long lValue; strlwr(sKeyName); //Find out the Item while(lPointersize) { lPointer=FSeek(file_pointer,'*',lPointer,1); // To find the 1st '*' from lPointer if(lPointer==0) // cannot find '*' return lDefault; sscanf(file_pointer->addr+lPointer,"%s",&sTemp); strlwr(sTemp); //Read the Value of the Item if(!strcmp(sKeyName,sTemp)) { lPointer=FSeek(file_pointer,'=',lPointer,1); // To find the 1st '=' from lPointer if(lPointer==0) // cannot find '=' return lDefault; sscanf(file_pointer->addr+lPointer,"%ld",&lValue); return lValue; } } // EOF return lDefault; } int GetProFileStr(FILE_DATA far *file_pointer,char* sKeyName,char* sResult,char* sDefault) { // If cannot find the sKeyName, sResult=sDefault. // If cannot find the string of the sKeyName, sResult=sDefault. // Return value: length of sResult unsigned long lPointer=0; char sTemp[20]; int i,iLen; strlwr(sKeyName); //Find out the Item while(lPointersize) { lPointer=FSeek(file_pointer,'*',lPointer,1); // To find the 1st '*' from lPointer if(lPointer==0) // cannot find '*' { strcpy(sResult,sDefault); return strlen(sDefault); } sscanf(file_pointer->addr+lPointer,"%s",&sTemp); strlwr(sTemp); //Read the String of the Item if(!strcmp(sKeyName,sTemp)) { lPointer=FSeek(file_pointer,'=',lPointer,1); // To find the 1st '*' from lPointer if(lPointer==0) // cannot find '=' { strcpy(sResult,sDefault); return strlen(sResult); } sscanf(file_pointer->addr+lPointer,"%s",&sTemp); if(strlen(sTemp)==0) // cannot find string strcpy(sResult,sDefault); else strcpy(sResult,sTemp); return strlen(sResult); } } // EOF strcpy(sResult,sDefault); return strlen(sResult); } // I use GetProFileStr to replace GetProFileVal. //float GetProFileVal(FILE_DATA far *file_pointer,char* sKeyName,float fDefault) //{ // unsigned long lPointer=0; // char sTemp[20]; // float fValue; // // strlwr(sKeyName); // //Find out the Item // while(lPointersize) // { // lPointer=FSeek(file_pointer,'*',lPointer,1); // To find the 1st '*' from lPointer // if(lPointer==0) // cannot find '*' // return fDefault; // sscanf(file_pointer->addr+lPointer,"%s",&sTemp); // strlwr(sTemp); // //Read the Value of the Item // if(!strcmp(sKeyName,sTemp)) // { // lPointer=FSeek(file_pointer,'=',lPointer,1); // To find the 1st '=' from lPointer // if(lPointer==0) // cannot find '=' // return fDefault; // sscanf(file_pointer->addr+lPointer,"%f",&fValue); // return fValue; // } // } // // EOF // return fDefault; //} void PortUserStart(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E via the user's defined port(PortUser), the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing } void Port9999Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 9999, the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing } void Port502Start(int skt) { /* XS8_3200.Lib Version 3.2.00 (20,Apr,2004) or later version supports this function. When a TCP/IP client connects to the 7188E/8000E TCP port 502, the Xserver calls the function once. You can use function VcomSendSocket to send a message to the client when a connection is established. For example: VcomSendSocket(skt,"Connection is established.",26); //return 26 bytes. skt: socket number assigned to the TCP/IP client. */ skt=skt; //do nothing }