From a64e2ca42c34364e3e5727430b956b2fda221d89 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 14 Nov 2023 17:47:25 +0800 Subject: [PATCH] cac --- ClearThread.cpp | 31 + ClearThread.h | 24 + DSFileSystem.cpp | 1502 +++++ DSFileSystem.h | 366 ++ DlgDevListImpl.cpp | 78 + DlgDevListImpl.h | 33 + Header.h | 11605 +++++++++++++++++++++++++++++++++ Inifile.cpp | 788 +++ Profile_Hash.cpp | 1869 ++++++ Profile_Hash.h | 514 ++ _confrw.h | 13 + baohua.h | 77 + basefunc.cpp | 922 +++ basefunc.h | 46 + basetype.h | 85 + buban103.cpp | 13336 ++++++++++++++++++++++++++++++++++++++ buban103.h | 2255 +++++++ buban104.cpp | 4881 ++++++++++++++ buban104.h | 291 + chainlist.cpp | 174 + chainlist.h | 49 + common.h | 1221 ++++ commport.cpp | 4286 ++++++++++++ commport.h | 134 + conf_close.cpp | 42 + conf_open.cpp | 47 + conf_read_key.cpp | 111 + conf_write_key.cpp | 96 + config.ini | 44 + confrw.h | 177 + confrw_errno.h | 69 + display.cpp | 625 ++ display.h | 55 + filelist.txt | 11 + global_errno.h | 803 +++ harximoban.h | 1021 +++ inifile.h | 56 + list_entry.cpp | 103 + list_entry.h | 107 + netport.cpp | 871 +++ netport.h | 36 + os_heap.cpp | 397 ++ os_heap.h | 110 + platform_def.h | 162 + portconfig.ini | 246 + scadaprotect.cpp | 2405 +++++++ scadaprotect.h | 516 ++ tcphost.cpp | 3218 +++++++++ tcphost.h | 299 + typedef.h | 372 ++ udpcomm.cpp | 962 +++ udpcomm.h | 38 + udpping.cpp | 1027 +++ udpping.h | 109 + widgets.cpp | 153 + widgets.vcxproj | 211 + widgets.vcxproj.filters | 168 + widgets.vcxproj.user | 4 + 58 files changed, 59251 insertions(+) create mode 100644 ClearThread.cpp create mode 100644 ClearThread.h create mode 100644 DSFileSystem.cpp create mode 100644 DSFileSystem.h create mode 100644 DlgDevListImpl.cpp create mode 100644 DlgDevListImpl.h create mode 100644 Header.h create mode 100644 Inifile.cpp create mode 100644 Profile_Hash.cpp create mode 100644 Profile_Hash.h create mode 100644 _confrw.h create mode 100644 baohua.h create mode 100644 basefunc.cpp create mode 100644 basefunc.h create mode 100644 basetype.h create mode 100644 buban103.cpp create mode 100644 buban103.h create mode 100644 buban104.cpp create mode 100644 buban104.h create mode 100644 chainlist.cpp create mode 100644 chainlist.h create mode 100644 common.h create mode 100644 commport.cpp create mode 100644 commport.h create mode 100644 conf_close.cpp create mode 100644 conf_open.cpp create mode 100644 conf_read_key.cpp create mode 100644 conf_write_key.cpp create mode 100644 config.ini create mode 100644 confrw.h create mode 100644 confrw_errno.h create mode 100644 display.cpp create mode 100644 display.h create mode 100644 filelist.txt create mode 100644 global_errno.h create mode 100644 harximoban.h create mode 100644 inifile.h create mode 100644 list_entry.cpp create mode 100644 list_entry.h create mode 100644 netport.cpp create mode 100644 netport.h create mode 100644 os_heap.cpp create mode 100644 os_heap.h create mode 100644 platform_def.h create mode 100644 portconfig.ini create mode 100644 scadaprotect.cpp create mode 100644 scadaprotect.h create mode 100644 tcphost.cpp create mode 100644 tcphost.h create mode 100644 typedef.h create mode 100644 udpcomm.cpp create mode 100644 udpcomm.h create mode 100644 udpping.cpp create mode 100644 udpping.h create mode 100644 widgets.cpp create mode 100644 widgets.vcxproj create mode 100644 widgets.vcxproj.filters create mode 100644 widgets.vcxproj.user diff --git a/ClearThread.cpp b/ClearThread.cpp new file mode 100644 index 0000000..463df5d --- /dev/null +++ b/ClearThread.cpp @@ -0,0 +1,31 @@ +// ClearThread.cpp: implementation of the CClearThread class. +// +////////////////////////////////////////////////////////////////////// + +#include "ClearThread.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CClearThread::CClearThread(QTextEdit *pEdit) +{ + m_pEditWidget = pEdit; +} + +CClearThread::~CClearThread() +{ + +} + +void CClearThread::run() +{ + qDebug("clear thread start... ..."); + + if(m_pEditWidget) + { + m_pEditWidget->clear(); + } + + qDebug("clear thread finished"); +} diff --git a/ClearThread.h b/ClearThread.h new file mode 100644 index 0000000..7f8f01b --- /dev/null +++ b/ClearThread.h @@ -0,0 +1,24 @@ +// ClearThread.h: interface for the CClearThread class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CLEARTHREAD_H__17C9FD37_21E1_4FC2_83D4_942D1DE68D4B__INCLUDED_) +#define AFX_CLEARTHREAD_H__17C9FD37_21E1_4FC2_83D4_942D1DE68D4B__INCLUDED_ + +#include +#include + +class CClearThread : public QThread +{ +public: + CClearThread(QTextEdit *pEdit); + virtual ~CClearThread(); + +private: + QTextEdit *m_pEditWidget; + +protected: + virtual void run(); +}; + +#endif // !defined(AFX_CLEARTHREAD_H__17C9FD37_21E1_4FC2_83D4_942D1DE68D4B__INCLUDED_) diff --git a/DSFileSystem.cpp b/DSFileSystem.cpp new file mode 100644 index 0000000..53cc4bd --- /dev/null +++ b/DSFileSystem.cpp @@ -0,0 +1,1502 @@ +/***************************************************************************** + * FileName : DSFileSystem.c * + * Programmer : AAAwen * + * Writen at : 2005.05.10 * + * Version : 1.0 * + * Description: 定义文件系统用来管理存储在flash中的文件 * + * Last modify: 2005.05.10 * + *****************************************************************************/ +#ifdef OS_WINDOWS +#include +#include +#endif +#include "DSFileSystem.h" +#include "basefunc.h" +#include "common.h" +#include "os_heap.h" +#include "basetype.h" +#include + +extern char IniFilePath[256]; + +long LoadFile(const char *szFileName, char **ppDestMem) +{ + FILE *fp; + size_t uReadLen, uContentLen; + char szDbg[128]; + long lContentLen; + + *ppDestMem = NULL; + if(NULL == szFileName) + { + sprintf(szDbg, "szFileName is NULL.\n"); + DebugPrint(szDbg); + return 0; + } + + fp = fopen(szFileName, "rb"); + if(NULL == fp) + { + sprintf(szDbg, "<%s>: open is Error.\n", szFileName); + DebugPrint(szDbg); + return 0; + } + + if(fseek(fp, 0, SEEK_END) != 0) + { + fclose(fp); + sprintf(szDbg, "<%s>: SeekEnd is Error.\n", szFileName); + DebugPrint(szDbg); + return 0; + } + + lContentLen = ftell(fp); + if(lContentLen <= 0) + { + fclose(fp); + sprintf(szDbg, "<%s>: Content is Error.\n", szFileName); + DebugPrint(szDbg); + return 0; + } + + *ppDestMem = (char *)HEAP_MALLOC(lContentLen); + uContentLen = (size_t)lContentLen; + + fseek(fp, 0, SEEK_SET); + uReadLen = fread(*ppDestMem, sizeof(char), uContentLen, fp); + fclose(fp); + if(uReadLen != uContentLen) + { + sprintf(szDbg, "<%s>: ReadLen=%d don't equal ContentLen=%d.\n", + szFileName, uReadLen, uContentLen); + DebugPrint(szDbg); + + if(feof(fp) != 0) + { + HEAP_FREE(*ppDestMem); + *ppDestMem = NULL; + return 0; + } + else + { + lContentLen = uReadLen; + } + } + + return lContentLen; +} + +long LoadFileInDSFS(const char *szFileName, char **ppDestMem, BYTE *pFSAddr) +{ + int i; + char szDbg[128]; + long lContentLen; + BYTE *pMoveBuf; + DSFILEHEAD *pFileHead; + DSFILESYSTEMHEAD *pFileSystemHead; + + *ppDestMem = NULL; + pFileHead = NULL; + if(NULL == szFileName) + { + sprintf(szDbg, "szFileName is NULL.\n"); + DebugPrint(szDbg); + return 0; + } + + if(NULL == pFSAddr) + { + sprintf(szDbg, "FileSystem Addr is NULL.\n"); + DebugPrint(szDbg); + return 0; + } + + pFileSystemHead = (DSFILESYSTEMHEAD *)pFSAddr; + + pMoveBuf = pFSAddr+pFileSystemHead->m_iOffset; + for(i=0; im_iFiles; i++) + { + pFileHead = (DSFILEHEAD *)pMoveBuf; + + if(CmpString2(&pFileHead->m_FileName[0], szFileName)) + { + break; + } + + pMoveBuf += pFileHead->m_iFileSize + sizeof(DSFILEHEAD) - 1; + } + + if(i >= pFileSystemHead->m_iFiles) + { + return 0; + } + + lContentLen = pFileHead->m_iFileSize-pFileHead->m_iFileNameLen; + if(lContentLen <= 0) + { + return 0; + } + + *ppDestMem = (char *)HEAP_MALLOC(lContentLen); + if(*ppDestMem == NULL) + { + return 0; + } + + memcpy(*ppDestMem, pMoveBuf+pFileHead->m_iOffset, lContentLen); + + return lContentLen; +} + +int DS_Seek(FILECONTENT *stream, long offset, int origin) +{ + int iRetval; + + iRetval = 0; + + switch(origin) + { + case SEEK_CUR: + if((stream->m_lOffset + offset) < stream->m_lContentLen) + { + stream->m_lOffset += offset; + } + else + { + iRetval = -1; + } + break; + case SEEK_END: + if(stream->m_lContentLen > 0) + { + stream->m_lOffset = stream->m_lContentLen - 1; + } + else + { + iRetval = -1; + } + break; + case SEEK_SET: + if((offset < stream->m_lContentLen) + && (offset >= 0)) + { + stream->m_lOffset = offset; + } + else + { + iRetval = -1; + } + break; + default: + iRetval = -1; + break; + } + + return iRetval; +} + +char *DS_Gets(char *pDest, int iDestMax, FILECONTENT *stream) +{ + int i, j; + BOOL bExit; + + if(stream == NULL) + { + return NULL; + } + + bExit = FALSE; + pDest[0] = 0; + for(j=0, i=stream->m_lOffset; i<(stream->m_lContentLen-1); i++) + { + if(TRUE == bExit) + { + break; + } + + if(stream->m_pContent[i] == 0) + { + bExit = TRUE; + continue; + } + + if(stream->m_pContent[i] == '\r') + { + if(i < (stream->m_lContentLen-2)) + { + if(stream->m_pContent[i+1] == '\n') + { + i++; + bExit = TRUE; + continue; + } + } + } + + if(stream->m_pContent[i] == '\n') + { + bExit = TRUE; + continue; + } + + pDest[j++] = stream->m_pContent[i]; + if(j >= (iDestMax-1)) + { + bExit = TRUE; + } + } + + stream->m_lOffset = i; + + if(j > 0) + { + pDest[j] = 0; + } + else + { + return NULL; + } + + return pDest; +} + +int GetFileLen(FILE *fp) +{ + int iLen; + + fseek(fp, 0, SEEK_END); + iLen = ftell(fp); + + return iLen; +} + +HDSFILE DSOpenFile(const char *szFileName) +{ + HDSFILE hFile; + char szDbg[128]; + BYTE *pFSAddr; + + if(NULL == szFileName) + { + sprintf(szDbg, "szFileName is NULL.\n"); + DebugPrint(szDbg); + return NULL; + } + + hFile = (HDSFILE)HEAP_MALLOC(sizeof(DSFILE)); + memset(hFile, 0, sizeof(DSFILE)); +#ifdef OS_LINUX + // 首4个字节文文件系统的长度 + pFSAddr = (BYTE *)(MCF5272_FRAMBAR + DS_FILESYSTEM_ADDR+4); + hFile->m_lContentLen = LoadFileInDSFS(szFileName, &hFile->m_pContent, pFSAddr); +#else + //hFile->m_lContentLen = LoadFile(szFileName, &hFile->m_pContent); + // wen 2005.06.15 test + pFSAddr = FsReadCombinFile("DSFileSystem.dfs"); + if(NULL != pFSAddr) + { + //getcwd(szCurDir, sizeof(szCurDir)); + const char *ptr = szFileName+strlen(IniFilePath)+1; + hFile->m_lContentLen = LoadFileInDSFS(ptr, &hFile->m_pContent, pFSAddr); + HEAP_FREE(pFSAddr); + } +#endif + if(hFile->m_lContentLen <= 0) + { + HEAP_FREE(hFile); + hFile = NULL; + } + + return hFile; +} + +HDSFILE DSOpenFileEx(const char *szFileName) +{ + FILE *fp; + HDSFILE hFile; + //char szDbg[128]; + + hFile = (HDSFILE)HEAP_MALLOC(sizeof(DSFILE)); + memset(hFile, 0, sizeof(DSFILE)); + + fp = fopen(szFileName, "rb"); + if(!fp) + { + return NULL; + } + + fseek(fp, 0, SEEK_END); + hFile->m_lContentLen = ftell(fp); + hFile->m_pContent = (char *)HEAP_MALLOC(hFile->m_lContentLen); + fseek(fp, 0, SEEK_SET); + fread(hFile->m_pContent, 1, hFile->m_lContentLen, fp); + fclose(fp); + + if(hFile->m_lContentLen <= 0) + { + HEAP_FREE(hFile); + hFile = NULL; + } + + return hFile; +} + + +HDSFILE DSOpenFileEx3(const char *szRootDir, const char *szFileName) +{ + HDSFILE hFile; + char szDbg[128]; + BYTE *pFSAddr; +#ifndef OS_LINUX + char szFileSystem[512]; +#endif + + if(NULL == szFileName) + { + sprintf(szDbg, "szFileName is NULL.\n"); + DebugPrint(szDbg); + return NULL; + } + + hFile = (HDSFILE)HEAP_MALLOC(sizeof(DSFILE)); + memset(hFile, 0, sizeof(DSFILE)); +#ifdef OS_LINUX + // 首4个字节文文件系统的长度 + pFSAddr = (BYTE *)(MCF5272_FRAMBAR + DS_FILESYSTEM_ADDR+4); + hFile->m_lContentLen = LoadFileInDSFS(szFileName, &hFile->m_pContent, pFSAddr); +#else + sprintf(szFileSystem, "%s/DSFileSystem.dfs", szRootDir); + pFSAddr = FsReadCombinFileEx(szFileSystem); + if(NULL != pFSAddr) + { + hFile->m_lContentLen = LoadFileInDSFS(szFileName, &hFile->m_pContent, pFSAddr); + HEAP_FREE(pFSAddr); + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +#endif + if(hFile->m_lContentLen <= 0) + { + HEAP_FREE(hFile); + hFile = NULL; + } + + return hFile; +} + +HDSFILE DSOpenFileEx2(const char *szRootDir, const char *szFSName, const char *szFileName) +{ + HDSFILE hFile; + char szDbg[128]; + BYTE *pFSAddr; +#ifndef OS_LINUX + char szFileSystem[512]; +#endif + + if(NULL == szFileName) + { + sprintf(szDbg, "szFileName is NULL.\n"); + DebugPrint(szDbg); + return NULL; + } + + hFile = (HDSFILE)HEAP_MALLOC(sizeof(DSFILE)); + memset(hFile, 0, sizeof(DSFILE)); +#ifdef OS_LINUX + // 首4个字节文文件系统的长度 + pFSAddr = (BYTE *)(MCF5272_FRAMBAR + DS_FILESYSTEM_ADDR+4); + hFile->m_lContentLen = LoadFileInDSFS(szFileName, &hFile->m_pContent, pFSAddr); +#else + sprintf(szFileSystem, "%s/%s", szRootDir, szFSName); + pFSAddr = FsReadCombinFileEx(szFileSystem); + if(NULL != pFSAddr) + { + hFile->m_lContentLen = LoadFileInDSFS(szFileName, &hFile->m_pContent, pFSAddr); + HEAP_FREE(pFSAddr); + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +#endif + if(hFile->m_lContentLen <= 0) + { + HEAP_FREE(hFile); + hFile = NULL; + } + + return hFile; +} + +BOOL DSCloseFile(HDSFILE hFile) +{ + if(hFile->m_pContent != NULL) + { + HEAP_FREE(hFile->m_pContent); + hFile->m_pContent = NULL; + } + + HEAP_FREE(hFile); + return TRUE; +} + +size_t DSfread(void *buffer, size_t size, size_t count, HDSFILE hFile) +{ + size_t RealBytes, RemainLen; + + if(hFile == NULL) + { + return 0; + } + if(hFile->m_lContentLen <= 0) + { + return 0; + } + + RealBytes = size*count; + if(RealBytes <= 0) + { + return 0; + } + + if(DSfeof(hFile) == 0) + { + return 0; + } + + RemainLen = hFile->m_lContentLen - hFile->m_lOffset; + if(RealBytes > RemainLen) + { + RealBytes = RemainLen / size; + if(RealBytes <= 0) + { + return 0; + } + } + + memcpy(buffer, hFile->m_pContent+hFile->m_lOffset, RealBytes*size); + + hFile->m_lOffset += RealBytes*size; + + return RealBytes; +} + +char *DSfgets(char *string, int iMaxSize, HDSFILE hFile) +{ + int i, j; + BOOL bExit; +#if 0 + FILE *fp; + char szfilename[128]; + +#ifdef OS_LINUX + strcpy(szfilename, "/log/dsdebug.txt"); +#else + strcpy(szfilename, "dsdebug.txt"); +#endif +#endif + + if(hFile == NULL) + { + return NULL; + } + if(hFile->m_lContentLen <= 0) + { + return NULL; + } + + bExit = FALSE; + string[0] = 0; + for(j=0, i=hFile->m_lOffset; im_lContentLen; i++) + { + if(TRUE == bExit) + { + break; + } + + if(hFile->m_pContent[i] == 0) + { + bExit = TRUE; + continue; + } + + if(hFile->m_pContent[i] == '\r') + { + if(i < (hFile->m_lContentLen-2)) + { + if(hFile->m_pContent[i+1] == '\n') + { + i++; + bExit = TRUE; + continue; + } + } + } + + if(hFile->m_pContent[i] == '\n') + { + bExit = TRUE; + continue; + } + + string[j++] = hFile->m_pContent[i]; + if(j >= (iMaxSize-1)) + { + bExit = TRUE; + } + } + + hFile->m_lReadCount += i - hFile->m_lOffset; + hFile->m_lOffset = i; + + if(j > 0) + { + string[j] = 0; + } + else + { + if(i >= hFile->m_lContentLen) + { + return NULL; + } + else + { + string[0] = 0; + } + } + +#if 0 + fp = fopen(szfilename, "ab"); + fwrite(string, 1, strlen(string), fp); + fwrite("\r\n", 1, strlen("\r\n"), fp); + fclose(fp); +#endif + + return string; +} + +char *DSfgetsEx(char *string, int iMaxSize, HDSFILE hFile) +{ + int i, j; + BOOL bExit; +#if 0 + FILE *fp; + char szfilename[128]; + +#ifdef OS_LINUX + strcpy(szfilename, "/log/dsdebug.txt"); +#else + strcpy(szfilename, "dsdebug.txt"); +#endif +#endif + + if(hFile == NULL) + { + return NULL; + } + if(hFile->m_lContentLen <= 0) + { + return NULL; + } + + bExit = FALSE; + string[0] = 0; + i=hFile->m_lOffset+hFile->m_lReadCount; + for(j=0; im_lContentLen; i++) + { + if(TRUE == bExit) + { + break; + } + + if(hFile->m_pContent[i] == 0) + { + bExit = TRUE; + continue; + } + + if(hFile->m_pContent[i] == '\r') + { + if(i < (hFile->m_lContentLen-2)) + { + if(hFile->m_pContent[i+1] == '\n') + { + i++; + bExit = TRUE; + continue; + } + } + } + + if(hFile->m_pContent[i] == '\n') + { + bExit = TRUE; + continue; + } + + string[j++] = hFile->m_pContent[i]; + if(j >= (iMaxSize-1)) + { + bExit = TRUE; + } + } + + hFile->m_lReadCount = i - hFile->m_lOffset; + + if(j > 0) + { + string[j] = 0; + } + else + { + if(i >= hFile->m_lContentLen) + { + return NULL; + } + else + { + string[0] = 0; + } + } + +#if 0 + fp = fopen(szfilename, "ab"); + fwrite(string, 1, strlen(string), fp); + fwrite("\r\n", 1, strlen("\r\n"), fp); + fclose(fp); +#endif + + return string; +} + +int DSfgetreadcount(HDSFILE hFile) +{ + return hFile->m_lReadCount; +} + +int DSfseek(HDSFILE hFile, long offset, int origin) +{ + int iRetval; + + iRetval = 0; + + switch(origin) + { + case SEEK_CUR: + if((hFile->m_lOffset + offset) < 0) + { + iRetval = -1; + break; + } + + hFile->m_lOffset += offset; + break; + case SEEK_CUR_EX: + if((hFile->m_lReadCount - offset) < 0) + { + iRetval = -1; + break; + } + + if(offset != 0) + { + if((hFile->m_lOffset + offset) < 0) + { + iRetval = -1; + break; + } + + hFile->m_lOffset += offset; + hFile->m_lReadCount -= offset; + } + else + { + hFile->m_lOffset += hFile->m_lReadCount; + hFile->m_lReadCount = 0; + } + break; + case SEEK_END: + if(hFile->m_lContentLen > 0) + { + hFile->m_lOffset = hFile->m_lContentLen; + } + else + { + iRetval = -1; + } + break; + case SEEK_SET: + if(offset < 0) + { + iRetval = -1; + break; + } + + if(offset > hFile->m_lContentLen) + { + iRetval = -1; + } + else + { + hFile->m_lOffset = offset; + } + break; + case SEEK_CLR_RCNT: + hFile->m_lReadCount = 0; + break; + default: + iRetval = -1; + break; + } + + return iRetval; +} + +int DSfeof(HDSFILE hFile) +{ + if(hFile->m_lOffset >= hFile->m_lContentLen) + { + return 0; + } + else + { + return 1; + } +} + +int DSfeofEx(HDSFILE hFile) +{ + if((hFile->m_lOffset+hFile->m_lReadCount) >= hFile->m_lContentLen) + { + return 0; + } + else + { + return 1; + } +} + +int DSfeob(HDSFILE hFile) +{ + if(hFile->m_lReadCount >= hFile->m_lContentLen) + { + return 0; + } + else + { + return hFile->m_lReadCount; + } +} + +int DSftell(HDSFILE hFile) +{ + return hFile->m_lOffset; +} + +int DSHaveSection(char *pSection, HDSFILE hFile) +{ + int iSrcLen, iMaxLen; + + if(strstr(hFile->m_szSection, pSection)) + { + return hFile->m_lSectionOk; + } + else + { + iSrcLen = strlen(pSection); + iMaxLen = sizeof(hFile->m_szSection)-1; + if(iSrcLen > iMaxLen) + { + hFile->m_szSection[0] = 0; + hFile->m_lSectionOk = DS_SECTION_NOEXIST; + return DS_SECTION_OUT; + } + else + { + strcpy(hFile->m_szSection, pSection); + hFile->m_lSectionOk = DS_SECTION_NOEXIST; + hFile->m_lSectionOffset = hFile->m_lOffset; + hFile->m_lSectionLines = 0; + hFile->m_lSectionLinesAddFlag = 1; + } + } + + return DS_SECTION_SEARCH; +} + +int DSSaveSectionOffset(HDSFILE hFile) +{ + hFile->m_lSectionOffset = hFile->m_lOffset; + hFile->m_lSectionLines = 0; + hFile->m_lSectionLinesAddFlag = 1; + hFile->m_lSectionOk = DS_SECTION_EXIST; + + return 1; +} + +int DSRestoreSectionOffset(HDSFILE hFile) +{ + hFile->m_lOffset = hFile->m_lSectionOffset; + + return hFile->m_lOffset; +} + +int DSAddSectionLines(int iLines, HDSFILE hFile) +{ + if(hFile->m_lSectionLinesAddFlag > 0) + { + hFile->m_lSectionLines += iLines; + } + + return hFile->m_lSectionLines; +} + +int DSSubSectionLines(int iLines, HDSFILE hFile) +{ + if(hFile->m_lSectionLinesAddFlag > 0) + { + hFile->m_lSectionLines -= iLines; + if(hFile->m_lSectionLines < 0) + { + hFile->m_lSectionLines = 0; + } + } + + return hFile->m_lSectionLines; +} + +int DSSetSectionLinesAddFlag(int iFlag, HDSFILE hFile) +{ + hFile->m_lSectionLinesAddFlag = iFlag; + return iFlag; +} + +int DSSectionisOver(int iReadLines, HDSFILE hFile) +{ + if(hFile->m_lSectionLinesAddFlag) + { + return 0; + } + else if(hFile->m_lSectionLines <= iReadLines) + { + //DSRestoreSectionOffset(hFile); + return 1; + } + + return 0; +} + +BOOL FsCombinAllFile(const char *szListFileName, const char *szDestFileName, const char *szDestDir) +{ + BOOL bReturn, bNetSequence; + int iLen, iFileLen, iRealLen, iOffset; + int iWriteLen, iFileOffset, iBufLen; + FILE *fp, *fp_dest, *fp_file; + char szDbg[512], szFileName[256], szList[128], *ptr; + BYTE *pBuf; + DSFILEHEAD sFileHead; + DSFILESYSTEMHEAD sFileSystemHead; + + if(NULL == szListFileName) + { + sprintf(szDbg, "szListFileName is NULL.\n"); + DebugPrint(szDbg); + return FALSE; + } + + sprintf(szFileName, "%s\\%s", szDestDir, szListFileName); + fp = fopen(szFileName, "rb"); + if(NULL == fp) + { + return FALSE; + } + +#ifdef OS_WINDOWS + sprintf(szFileName, "%s\\%s", szDestDir, szDestFileName); +#else + strcpy(szFileName, szDestFileName); +#endif + fp_dest = fopen(szFileName, "wb"); + if(NULL == fp_dest) + { + fclose(fp); + return FALSE; + } + + bNetSequence = IsNetSequence(); + + sFileSystemHead.m_iFiles = 0; + sFileSystemHead.m_iOffset = sizeof(DSFILESYSTEMHEAD); + fseek(fp_dest, sFileSystemHead.m_iOffset, SEEK_SET); + + bReturn = TRUE; + iBufLen = sizeof(szList)-1; + while(fgets(szList, iBufLen, fp) != NULL) + { + szList[iBufLen] = 0; + //ptr = strstr(szList, "\r"); + ptr = strchr(szList, '\r'); + if(ptr != NULL) + { + *ptr = 0; + } + //ptr = strstr(szList, "\n"); + ptr = strchr(szList, '\n'); + if(ptr != NULL) + { + *ptr = 0; + } + + iLen = strlen(szDestDir)+strlen(szList)+2; + if(iLen > sizeof(szFileName)) + { + sprintf(szDbg, "文件名称长度(%d > %d)过长", iLen, sizeof(szFileName)); + DebugPrint(szDbg); + bReturn = FALSE; + continue; + } + + sprintf(szFileName, "%s\\%s", szDestDir, szList); + fp_file = fopen(szFileName, "rb"); + if(NULL == fp_file) + { + sprintf(szDbg, "文件<%s>不存在或者打开错误.", szFileName); + DebugPrint(szDbg); + bReturn = FALSE; + continue; + } + + // 写文件出错后,恢复的位置 + iFileOffset = ftell(fp_dest); + + // 文件的头结构 + iFileLen = GetFileLen(fp_file); + fseek(fp_file, 0, SEEK_SET); + pBuf = (BYTE *)HEAP_MALLOC(iFileLen); + iRealLen = fread(pBuf, sizeof(BYTE), iFileLen, fp_file); + sFileHead.m_iFileNameLen = strlen(szList)+1; + sFileHead.m_iFileSize = sFileHead.m_iFileNameLen+iRealLen; + sFileHead.m_iOffset = sizeof(DSFILEHEAD)-1+sFileHead.m_iFileNameLen; + + if(bNetSequence == FALSE) + { + SequenceHostToNet((char *)&sFileHead.m_iFileNameLen, sizeof(int)); + SequenceHostToNet((char *)&sFileHead.m_iFileSize, sizeof(int)); + SequenceHostToNet((char *)&sFileHead.m_iOffset, sizeof(int)); + } + + iWriteLen = fwrite((void *)&sFileHead, sizeof(BYTE), sizeof(DSFILEHEAD)-1, fp_dest); + if(iWriteLen < sizeof(DSFILEHEAD)-1) + { + iWriteLen = 0; + } + if(iWriteLen > 0) + { + iWriteLen = fwrite(szList, sizeof(char), strlen(szList)+1, fp_dest); + if(iWriteLen < (int)(strlen(szList)+1)) + { + iWriteLen = 0; + } + } + if(iWriteLen > 0) + { + iWriteLen = fwrite(pBuf, sizeof(BYTE), iRealLen, fp_dest); + if(iWriteLen < iRealLen) + { + iWriteLen = 0; + } + } + if(iWriteLen > 0) + { + sFileSystemHead.m_iFiles++; + } + else + { + fseek(fp_dest, iFileOffset, SEEK_SET); + } + + HEAP_FREE(pBuf); + fclose(fp_file); + } + + // 文件系统的头结构 + fseek(fp_dest, 0, SEEK_SET); + iOffset = sFileSystemHead.m_iOffset; + if(bNetSequence == FALSE) + { + SequenceHostToNet((char *)&sFileSystemHead.m_iFiles, sizeof(int)); + SequenceHostToNet((char *)&sFileSystemHead.m_iOffset, sizeof(int)); + } + fwrite((void *)&sFileSystemHead, sizeof(BYTE), iOffset, fp_dest); + + fclose(fp); + fclose(fp_dest); + + return bReturn; +} + +BOOL FsSplitAllFile(const char *szCombinFile, const char *szDestDir) +{ + BOOL bReturn, bNetSequence; + int i, iLen, iFileLen, iRealLen; + FILE *fp, *fp_dest; + char szDbg[512], szFileName[256]; + BYTE *pBuf, *pMoveBuf; + DSFILEHEAD *pFileHead; + DSFILESYSTEMHEAD *pFileSystemHead; + + if(NULL == szCombinFile) + { + sprintf(szDbg, "szCombinFile is NULL.\n"); + DebugPrint(szDbg); + return FALSE; + } + + strcpy(szFileName, szCombinFile); + fp = fopen(szFileName, "rb"); + if(NULL == fp) + { + return FALSE; + } + iFileLen = GetFileLen(fp); + pBuf = (BYTE *)HEAP_MALLOC(iFileLen); + if(NULL == pBuf) + { + sprintf(szDbg, "malloc(%d) Error", iFileLen); + DebugPrint(szDbg); + fclose(fp); + return FALSE; + } + memset(pBuf, 0, iFileLen); + + fseek(fp, 0, SEEK_SET); + iRealLen = fread(pBuf, sizeof(BYTE), iFileLen, fp); + + bReturn = TRUE; + pFileSystemHead = (DSFILESYSTEMHEAD *)pBuf; + + bNetSequence = IsNetSequence(); + if(bNetSequence == FALSE) + { + SequenceNetToHost((char *)&pFileSystemHead->m_iFiles, sizeof(int)); + SequenceNetToHost((char *)&pFileSystemHead->m_iOffset, sizeof(int)); + } + + pMoveBuf = pBuf+pFileSystemHead->m_iOffset; + for(i=0; im_iFiles; i++) + { + pFileHead = (DSFILEHEAD *)pMoveBuf; + + if(bNetSequence == FALSE) + { + SequenceNetToHost((char *)&pFileHead->m_iFileNameLen, sizeof(int)); + SequenceNetToHost((char *)&pFileHead->m_iFileSize, sizeof(int)); + SequenceNetToHost((char *)&pFileHead->m_iOffset, sizeof(int)); + } + + iLen = pFileHead->m_iFileNameLen+strlen(szDestDir)+2; + if(iLen > sizeof(szFileName)) + { + sprintf(szDbg, "文件名称长度(%d > %d)过长", iLen, sizeof(szFileName)); + DebugPrint(szDbg); + bReturn = FALSE; + break; + } + sprintf(szFileName, "%s\\%s", szDestDir, pFileHead->m_FileName); + fp_dest = fopen(szFileName, "wb"); + if(fp_dest == NULL) + { + sprintf(szDbg, "文件<%s>打开错误.", szFileName); + DebugPrint(szDbg); + bReturn = FALSE; + break; + } + + iFileLen = pFileHead->m_iFileSize - pFileHead->m_iFileNameLen; + fwrite(pMoveBuf+pFileHead->m_iOffset, sizeof(BYTE), iFileLen, fp_dest); + pMoveBuf += pFileHead->m_iFileSize+sizeof(DSFILEHEAD)-1; + fclose(fp_dest); + } + HEAP_FREE(pBuf); + fclose(fp); + + return bReturn; +} + +BYTE *FsReadCombinFile(const char *szCombinFile) +{ + int iFileLen, iRealLen; + FILE *fp; + char szDbg[512], szFileName[256], filename[256]; + BYTE *pBuf; + + if(NULL == szCombinFile) + { + sprintf(szDbg, "szCombinFile is NULL.\n"); + DebugPrint(szDbg); + return NULL; + } +#ifdef OS_LINUX + getcwd(filename, sizeof(filename)); +#else + strcpy(filename, IniFilePath); +#endif //OS_LINUX + + sprintf(szFileName, "%s/%s", filename, szCombinFile); + fp = fopen(szFileName, "rb"); + if(NULL == fp) + { + return NULL; + } + + iFileLen = GetFileLen(fp); + fseek(fp, 0, SEEK_SET); + pBuf = (BYTE *)HEAP_MALLOC(iFileLen); + if(NULL == pBuf) + { + sprintf(szDbg, "malloc(%d) Error", iFileLen); + DebugPrint(szDbg); + fclose(fp); + return NULL; + } + memset(pBuf, 0, iFileLen); + + iRealLen = fread(pBuf, sizeof(BYTE), iFileLen, fp); + + fclose(fp); + + // 将文件系统转换为主机字节格式 + FsNetToHost(pBuf); + + return pBuf; +} + +BYTE *FsReadCombinFileEx(const char *szCombinFile) +{ + int iFileLen, iRealLen; + FILE *fp; + char szDbg[512]; + BYTE *pBuf; + + if(NULL == szCombinFile) + { + sprintf(szDbg, "szCombinFile is NULL.\n"); + DebugPrint(szDbg); + return NULL; + } + + fp = fopen(szCombinFile, "rb"); + if(NULL == fp) + { + return NULL; + } + + iFileLen = GetFileLen(fp); + fseek(fp, 0, SEEK_SET); + pBuf = (BYTE *)HEAP_MALLOC(iFileLen); + if(NULL == pBuf) + { + sprintf(szDbg, "malloc(%d) Error", iFileLen); + DebugPrint(szDbg); + fclose(fp); + return NULL; + } + memset(pBuf, 0, iFileLen); + + iRealLen = fread(pBuf, sizeof(BYTE), iFileLen, fp); + + fclose(fp); + + // 将文件系统转换为主机字节格式 + FsNetToHost(pBuf); + + return pBuf; +} + +BOOL FsLoadFileSystem(const char *szFileSystem, BYTE **ppDestBuf) +{ + FILE *fp; + int iFileLen; + +//#ifdef OS_WINDOWS + if(NULL == szFileSystem) + { + return FALSE; + } + fp = fopen(szFileSystem, "rb"); + if(NULL == fp) + { + return FALSE; + } + + iFileLen = GetFileLen(fp); + *ppDestBuf = (BYTE *)HEAP_MALLOC(iFileLen); + fseek(fp, 0, SEEK_SET); + if(*ppDestBuf != NULL) + { + fread(*ppDestBuf, sizeof(BYTE), iFileLen, fp); + } + fclose(fp); + if(*ppDestBuf == NULL) + { + return FALSE; + } +/*#else + *ppDestBuf = (BYTE *)(MCF5272_FRAMBAR + DS_FILESYSTEM_ADDR+4); +#endif*/ + + // 将文件系统转换为主机字节格式 + FsNetToHost(*ppDestBuf); + + return TRUE; +} + +BOOL FsUnLoadFileSystem(BYTE **ppDestBuf) +{ +#ifdef OS_WINDOWS + if(*ppDestBuf != NULL) + { + HEAP_FREE(*ppDestBuf); + } +#endif + *ppDestBuf = NULL; + + return TRUE; +} + +BOOL FsDirFileName(const char *szPath, const char *szFileSystem) +{ + int i; + DSFILEHEAD *pFileHead=NULL; + DSFILESYSTEMHEAD *pFileSystemHead = NULL; + BYTE *pBuf = NULL, *pMoveBuf = NULL; + BOOL bDisAll; + + pMoveBuf = NULL; + if(FsLoadFileSystem(szFileSystem, &pBuf) == FALSE) + { + return FALSE; + } + + pMoveBuf = pBuf; + + if(strcmp(szPath, "/") == 0) + { + bDisAll = TRUE; + } + else + { + bDisAll = FALSE; + } + pFileSystemHead = (DSFILESYSTEMHEAD *)pMoveBuf; + +#ifdef OS_LINUX + printf("DFS: Files=%d\n", pFileSystemHead->m_iFiles); +#endif + + for(i=0; im_iFiles; i++) + { + if(i == 0) + { + pMoveBuf += pFileSystemHead->m_iOffset; + } + else + { + pMoveBuf += pFileHead->m_iFileSize+sizeof(DSFILEHEAD)-1; + } + + pFileHead = (DSFILEHEAD *)pMoveBuf; + + if((strstr(pFileHead->m_FileName, szPath) != NULL) + || (bDisAll == TRUE)) + { +#ifdef OS_WINDOWS + OutputDebugString((LPCWSTR)&pFileHead->m_FileName[0]); + OutputDebugString((LPCWSTR)"\n"); +#else + printf("[at: 0x%08x]\t%s\n", pMoveBuf, &pFileHead->m_FileName[0]); +#endif + } + } + + FsUnLoadFileSystem(&pBuf); + return TRUE; +} + +void FsDispHead(const char *szName, const char *szFileSystem) +{ + int i; + char szDisp[128]; + DSFILEHEAD *pFileHead=NULL; + DSFILESYSTEMHEAD *pFileSystemHead; + BYTE *pBuf, *pMoveBuf; + BOOL bDispAll; + + if(FsLoadFileSystem(szFileSystem, &pBuf) == FALSE) + { + return; + } + + pMoveBuf = pBuf; + + pFileSystemHead = (DSFILESYSTEMHEAD *)pMoveBuf; + if(strcmp(szName, "fs") == 0) + { + printf("ds\\/>fs\n Files=%d\n offset=%d\n\n",\ + pFileSystemHead->m_iFiles,\ + pFileSystemHead->m_iOffset); + return; + } + + if(strcmp(szName, "allfile") == 0) + { + bDispAll = TRUE; + } + else + { + bDispAll = FALSE; + } + + pFileHead = (DSFILEHEAD *)pMoveBuf; + for(i=0; im_iFiles; i++) + { + if(i == 0) + { + pMoveBuf += pFileSystemHead->m_iOffset; + } + else + { + pMoveBuf += pFileHead->m_iFileSize+sizeof(DSFILEHEAD)-1; + } + + pFileHead = (DSFILEHEAD *)pMoveBuf; + if(bDispAll == FALSE) + { + if(strcmp(&pFileHead->m_FileName[0], szName)) + { + continue; + } + } + +#ifdef OS_WINDOWS + sprintf(szDisp, "ds\\/>%s\n filenamelen=%d\n filesize=%d\n offset=%d\n\n",\ + &pFileHead->m_FileName[0], \ + pFileHead->m_iFileNameLen, \ + pFileHead->m_iFileSize, \ + pFileHead->m_iOffset); + OutputDebugString((LPCWSTR)szDisp); +#else + printf("ds\\/>%s\n filenamelen=%d\n filesize=%d\n offset=%d\n\n",\ + &pFileHead->m_FileName[0], \ + pFileHead->m_iFileNameLen, \ + pFileHead->m_iFileSize, \ + pFileHead->m_iOffset); +#endif + if(bDispAll == FALSE) + { + break; + } + } + + FsUnLoadFileSystem(&pBuf); + return; +} + +BOOL FsNetToHost(BYTE *pFSBuf) +{ + int i; + BYTE *pMoveBuf; + DSFILEHEAD *pFileHead=NULL; + DSFILESYSTEMHEAD *pFileSystemHead; + + if(IsNetSequence() == TRUE) + { + return TRUE; + } + + pMoveBuf = pFSBuf; + pFileSystemHead = (DSFILESYSTEMHEAD *)pMoveBuf; + + SequenceNetToHost((char *)&pFileSystemHead->m_iFiles, sizeof(int)); + SequenceNetToHost((char *)&pFileSystemHead->m_iOffset, sizeof(int)); + + pFileHead = (DSFILEHEAD *)pMoveBuf; + for(i=0; im_iFiles; i++) + { + if(i == 0) + { + pMoveBuf += pFileSystemHead->m_iOffset; + } + else + { + pMoveBuf += pFileHead->m_iFileSize+sizeof(DSFILEHEAD)-1; + } + + pFileHead = (DSFILEHEAD *)pMoveBuf; + SequenceNetToHost((char *)&pFileHead->m_iFileNameLen, sizeof(int)); + SequenceNetToHost((char *)&pFileHead->m_iFileSize, sizeof(int)); + SequenceNetToHost((char *)&pFileHead->m_iOffset, sizeof(int)); + } + + return TRUE; +} + +BOOL FsHostToNet(BYTE *pFSBuf) +{ + int i; + BYTE *pMoveBuf; + DSFILEHEAD *pFileHead=NULL; + DSFILESYSTEMHEAD *pFileSystemHead; + + if(IsNetSequence() == TRUE) + { + return TRUE; + } + + pMoveBuf = pFSBuf; + pFileSystemHead = (DSFILESYSTEMHEAD *)pMoveBuf; + + SequenceHostToNet((char *)&pFileSystemHead->m_iFiles, sizeof(int)); + SequenceHostToNet((char *)&pFileSystemHead->m_iOffset, sizeof(int)); + + pFileHead = (DSFILEHEAD *)pMoveBuf; + for(i=0; im_iFiles; i++) + { + if(i == 0) + { + pMoveBuf += pFileSystemHead->m_iOffset; + } + else + { + pMoveBuf += pFileHead->m_iFileSize+sizeof(DSFILEHEAD)-1; + } + + pFileHead = (DSFILEHEAD *)pMoveBuf; + SequenceHostToNet((char *)&pFileHead->m_iFileNameLen, sizeof(int)); + SequenceHostToNet((char *)&pFileHead->m_iFileSize, sizeof(int)); + SequenceHostToNet((char *)&pFileHead->m_iOffset, sizeof(int)); + } + + return TRUE; +} + +void DispMemoryData(const BYTE *pu8Addr, int iLen, int iNumofLine) +{ + int i, j, iDispLen; + BOOL bOver; + + bOver = FALSE; + iDispLen = iNumofLine; + for(i=0; i iLen) + { + iDispLen = iLen - i; + } + + printf("0x%08x:", pu8Addr+i); + for(j=0; j + +//typedef char* HDSFILE; +/*! + 清除数据流已经被读取的字节数 +*/ +#define SEEK_CLR_RCNT SEEK_END+10 +#define SEEK_CUR_EX SEEK_END+11 + +// 修改DS中的配置文件系统 +#define DS_FILESYSTEM_ADDR 0x3b0000 +#define DS_FILESYSTEM_LEN (0x50000-4) + +#define DS_SECTION_OUT -1 // 段名称长度越限 +#define DS_SECTION_NOEXIST 0 // 段名称不存在 +#define DS_SECTION_EXIST 1 // 段名称存在 +#define DS_SECTION_SEARCH 2 // 段名称查找 + +typedef struct tsgDSFILE +{ + /*! + 文件内容长度 + */ + long m_lContentLen; + /*! + 文件读取的当前位置 + */ + long m_lOffset; + /*! + 文件读取的字节数量 + */ + long m_lReadCount; + + // 增加优化配置文件读取项 + /*! + 段名称是否存在 + */ + long m_lSectionOk; + /*! + 段名称行数 + */ + long m_lSectionLines; + /*! + 段名称行数增加标识 + */ + long m_lSectionLinesAddFlag; + /*! + 段在文件中的偏移位置 + */ + long m_lSectionOffset; + /*! + 段名称 + */ + char m_szSection[64]; + /*! + 文件正文 + */ + char *m_pContent; +}DSFILE, *HDSFILE; + +#ifdef OS_WINDOWS +#pragma pack (push,1) +typedef struct tagDSFILESYSTEMHEAD +{ + /*! + 文件系统中文件数量 + */ + int m_iFiles; + /*! + 文件系统中首文件偏移 + \note + 第一个文件=this+m_iOffset + */ + int m_iOffset; +}DSFILESYSTEMHEAD; + +typedef struct tagDSFILEHEAD +{ + /*! + 文件长度(文件内容+文件头) + */ + int m_iFileSize; + /*! + 文件内容偏移 + */ + int m_iOffset; + /*! + 文件名长度 + */ + int m_iFileNameLen; + /*! + 文件名称 + */ + char m_FileName[1]; +}DSFILEHEAD, *pDSFILEHEAD; + +typedef struct tagFILECONTENT +{ + long m_lContentLen; + long m_lOffset; + char m_pContent[1]; +}FILECONTENT, *pFILECONTENT; +#pragma pack (pop) +#else +typedef struct tagDSFILESYSTEMHEAD +{ + /*! + 文件系统中文件数量 + */ + int m_iFiles ; + /*! + 文件系统中首文件偏移 + \note + 第一个文件=this+m_iOffset + */ + int m_iOffset ; +}DSFILESYSTEMHEAD; + +typedef struct tagDSFILEHEAD +{ + /*! + 文件长度(文件内容+文件头) + */ + int m_iFileSize ; + /*! + 文件内容偏移 + */ + int m_iOffset ; + /*! + 文件名长度 + */ + int m_iFileNameLen ; + /*! + 文件名称 + */ + char m_FileName[1] ; +}DSFILEHEAD, *pDSFILEHEAD; + +typedef struct tagFILECONTENT +{ + long m_lContentLen ; + long m_lOffset ; + char m_pContent[1] ; +}FILECONTENT, *pFILECONTENT; +#endif + + + +/*! + \brief 将指定文件载入目的内存 + \param szFileName -- 要载入的文件名 + \param ppDestMem -- 目的内存指针的指针 + \retval -- 返回分配内存长度 + \note + 如果内存分配失败或者文件为空返回0\n + pDestMem必须在使用后有调用者释放 + */ +long LoadFile(const char *szFileName, char **ppDestMem); + +/*! + \brief 将指定文件载入目的内存 + \param szFileName -- 要载入的文件名 + \param ppDestMem -- 目的内存指针的指针 + \param pFSAddr -- 文件系统首地址指针 + \retval -- 返回分配内存长度 + \note + 如果内存分配失败或者文件为空返回0\n + pDestMem必须在使用后有调用者释放 + */ +long LoadFileInDSFS(const char *szFileName, char **ppDestMem, BYTE *pFSAddr); + +/*! + \brief 设置数据流偏移量 + \param stream -- 数据流指针 + \param offset -- 与origin的偏移值 + \param origin -- 初始位置 + \retval -- 成功返回0 + */ +DSLIB_API int DS_Seek(FILECONTENT *stream, long offset, int origin); +DSLIB_API char *DS_Gets(char *pDest, int iDestMax, FILECONTENT *stream); + +/*! + \brief 获取文件长度 + \param fp -- 已经打开的文件指针 + \retval -- 返回文件长度 + */ +DSLIB_API int GetFileLen(FILE *fp); + +/*! + \brief 将指定文件载入目的内存 + \param szFileName -- 要载入的文件名 + \retval -- 返回文件句柄 + \note + 如果内存分配失败或者文件为空返回0\n + pDestMem必须在使用后有调用者释放 + */ +DSLIB_API HDSFILE DSOpenFile(const char *szFileName); +DSLIB_API HDSFILE DSOpenFileEx(const char *szFileName); +/*! + \brief 将指定文件载入目的内存 + \param szRootDir -- 文件系统的根路径 + \param szFileName -- 要载入的文件名 + \retval -- 返回文件句柄 + \note + 如果内存分配失败或者文件为空返回0\n + pDestMem必须在使用后有调用者释放 + 该函数仅适合于pc系统,用来浏览文件系统信息 + 在嵌入式系统中,参数1无意义 + + */ +DSLIB_API HDSFILE DSOpenFileEx3(const char *szRootDir, const char *szFileName); +DSLIB_API HDSFILE DSOpenFileEx2(const char *szRootDir, const char *szFSName, const char *szFileName); + +/*! + \brief 关闭打开的文件 + \param hFile -- 打开的文件句柄 + \note + 如果内存分配失败或者文件为空返回0\n + pDestMem必须在使用后有调用者释放 + */ +DSLIB_API BOOL DSCloseFile(HDSFILE hFile); + +/*! + \brief 从数据流中获取数据 + \param buffer -- 获取数据缓冲区指针 + \param size -- 获取数据单元的长度 + \param count -- 获取数据单元的数量 + \param hFile -- 数据流指针 + \retval -- 成功返回实际的读取数据单元数量 + */ +DSLIB_API size_t DSfread(void *buffer, size_t size, size_t count, HDSFILE hFile); +/*! + \brief 获取数据流一个字符串(以回车和换行结束) + \param string -- 获取字符串的缓冲区指针 + \param origin -- 缓冲区长度 + \param hFile -- 数据流指针 + \retval -- 成功返回读取的字符串指针 + */ +DSLIB_API char *DSfgets(char *string, int iMaxSize, HDSFILE hFile); +/*! + \brief 获取数据流一个字符串(以回车和换行结束) + \param string -- 获取字符串的缓冲区指针 + \param origin -- 缓冲区长度 + \param hFile -- 数据流指针 + \param ioffset -- 当前位置读取偏移 + \retval -- 成功返回读取的字符串指针 + \note + 读取指针不移动,需要用户干预 + */ +DSLIB_API char *DSfgetsEx(char *string, int iMaxSize, HDSFILE hFile); +/*! + \brief 读取文件已经读取的数据量 + \param hFile -- 数据流指针 + \retval -- 实际读取的数据量 + */ +DSLIB_API int DSfgetreadcount(HDSFILE hFile); +/*! + \brief 设置数据流偏移量 + \param hFile -- 数据流指针 + \param offset -- 与origin的偏移值 + \param origin -- 初始位置 + \retval -- 成功返回0 + */ +DSLIB_API int DSfseek(HDSFILE hFile, long offset, int origin); +/*! + \brief 是否到数据流底部 + \param hFile -- 数据流指针 + \retval -- 成功返回0 + */ +DSLIB_API int DSfeof(HDSFILE hFile); +/*! + \brief 是否到数据流底部 + \param hFile -- 数据流指针 + \retval -- 成功返回0 + */ +DSLIB_API int DSfeofEx(HDSFILE hFile); +/*! + \brief 是否数据流全部浏览完毕 + \param hFile -- 数据流指针 + \retval -- 成功返回0,否则为浏览过的字节数 + */ +DSLIB_API int DSfeob(HDSFILE hFile); +/*! + \brief 数据流的偏移量 + \param hFile -- 数据流指针 + \retval -- 返回偏移量 + */ +DSLIB_API int DSftell(HDSFILE hFile); +DSLIB_API int DSHaveSection(char *pSection, HDSFILE hFile); +DSLIB_API int DSSaveSectionOffset(HDSFILE hFile); +DSLIB_API int DSRestoreSectionOffset(HDSFILE hFile); +DSLIB_API int DSAddSectionLines(int iLines, HDSFILE hFile); +DSLIB_API int DSSubSectionLines(int iLines, HDSFILE hFile); +DSLIB_API int DSSetSectionLinesAddFlag(int iFlag, HDSFILE hFile); +DSLIB_API int DSSectionisOver(int iReadLines, HDSFILE hFile); + +/*! + \brief 合并所有文件 + \param szListFileName -- 要合并的文件列表文件名称 + \param szDestFileName -- 合并的目的文件 + \param szDestDir -- 文件路径 + \retval -- 成功返回TRUE + \note + 合并后的文件必须是偶字节对齐 + */ +DSLIB_API BOOL FsCombinAllFile(const char *szListFileName, const char *szDestFileName, const char *szDestDir); + +/*! + \brief 文件分离 + \param szCombinFile -- 合并的文件名称 + \param szDestDir -- 要分离的文件目录 + \retval -- 成功返回TRUE + */ +DSLIB_API BOOL FsSplitAllFile(const char *szCombinFile, const char *szDestDir); + +//测试用 +/*! + \brief 读取合并的文件(文件系统) + \param szCombinFile -- 合并的文件名称 + \retval -- 成功返回TRUE + */ +DSLIB_API BYTE *FsReadCombinFile(const char *szCombinFile); +DSLIB_API BYTE *FsReadCombinFileEx(const char *szCombinFile); + +/*! + \brief 装载文件系统 + \param szFileSystem -- 文件系统名称 + \param ppDestBuf -- 文件系统的目的缓冲区 + \retval -- 成功返回TRUE + */ +DSLIB_API BOOL FsLoadFileSystem(const char *szFileSystem, BYTE **ppDestBuf); + +/*! + \brief 卸载文件系统 + \param ppDestBuf -- 文件系统的目的缓冲区 + \retval -- 成功返回TRUE + */ +DSLIB_API BOOL FsUnLoadFileSystem(BYTE **ppDestBuf); + +/*! + \brief 显示指定文件系统路径的文件名称 + \param szPath -- 要显示的文件系统路径 + \param szFileSystem -- 指定的文件系统 + \retval -- 成功返回TRUE + */ +DSLIB_API BOOL FsDirFileName(const char *szPath, const char *szFileSystem); + +DSLIB_API void FsDispHead(const char *szName, const char *szFileSystem); + +BOOL FsNetToHost(BYTE *pFSBuf); +BOOL FsHostToNet(BYTE *pFSBuf); + +void DispMemoryData(const BYTE *pu8Addr, int iLen, int iNumofLine); +#endif \ No newline at end of file diff --git a/DlgDevListImpl.cpp b/DlgDevListImpl.cpp new file mode 100644 index 0000000..a824be9 --- /dev/null +++ b/DlgDevListImpl.cpp @@ -0,0 +1,78 @@ +// DlgDevListImpl.cpp: implementation of the CDlgDevListImpl class. +// +////////////////////////////////////////////////////////////////////// + +#include "DlgDevListImpl.h" +#include +#include +#include +#include +#include +#include + +#include "qt_public.h" +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +const char* gColumnName[MAX_NET_NUM+1] = {"序号","IP地址1","IP地址2","IP地址3"}; + +CDlgDevListImpl::CDlgDevListImpl(DEV_DEF *pDevParam, int iDevNum, int iCurSel, QWidget* parent, const char* name, bool modal, WFlags fl) + : DevList(parent, name, modal, fl) +{ + int i, j; + char sztmp[128]; + + m_iCurSelect = 0; + languageChange(); + + m_CTableDevList->setNumRows(iDevNum); + m_CTableDevList->setNumCols(MAX_NET_NUM+1); + + QHeader *pHorHeader = m_CTableDevList->horizontalHeader(); + for(i=0; i<(MAX_NET_NUM+1); i++) + { + pHorHeader->setLabel(i, CHS(gColumnName[i])); + } + + for(i=0; isetText(i, 0, CHS(sztmp)); + + for(j=0; j>24)&0xFF), + ((pDevParam[i].IpAddr[j]>>16)&0xFF), + ((pDevParam[i].IpAddr[j]>>8)&0xFF), + (pDevParam[i].IpAddr[j]&0xFF)); + m_CTableDevList->setText(i, j+1, CHS(sztmp)); + } + } + + for(i=0; i<(MAX_NET_NUM+1); i++) + { + m_CTableDevList->adjustColumn( i ); + } + + m_CTableDevList->selectRow(iCurSel); +} + +CDlgDevListImpl::~CDlgDevListImpl() +{ + +} + + +void CDlgDevListImpl::languageChange() +{ + setCaption(CHS("设备列表")); + m_BtnChange->setText(CHS("选择")); + m_BtnCancel->setText(CHS("取消")); +} + +void CDlgDevListImpl::ChangeSelectSlot() +{ + m_iCurSelect = m_CTableDevList->currentRow(); +} \ No newline at end of file diff --git a/DlgDevListImpl.h b/DlgDevListImpl.h new file mode 100644 index 0000000..dfe9660 --- /dev/null +++ b/DlgDevListImpl.h @@ -0,0 +1,33 @@ +// DlgDevListImpl.h: interface for the CDlgDevListImpl class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_DLGDEVLISTIMPL_H__DD481030_4A5E_4260_8D3E_A28E986FDDCF__INCLUDED_) +#define AFX_DLGDEVLISTIMPL_H__DD481030_4A5E_4260_8D3E_A28E986FDDCF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "devlist.h" +#include "common.h" + +class CDlgDevListImpl : public DevList +{ + Q_OBJECT +public: + CDlgDevListImpl(DEV_DEF *pDevParam, int iDevNum, int iCurSel, QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0); + virtual ~CDlgDevListImpl(); + + int m_iCurSelect; + int GetCurSelect(){return m_iCurSelect;}; + + +public slots: + virtual void ChangeSelectSlot(); + +protected slots: + virtual void languageChange(); +}; + +#endif // !defined(AFX_DLGDEVLISTIMPL_H__DD481030_4A5E_4260_8D3E_A28E986FDDCF__INCLUDED_) diff --git a/Header.h b/Header.h new file mode 100644 index 0000000..15fccf2 --- /dev/null +++ b/Header.h @@ -0,0 +1,11605 @@ +#ifndef _HEADER_H +#define _HEADER_H + +#ifdef OS_UNIX + #include + #include + #include + #include + #include + #include + #include +#endif //OS_UNIX +#ifdef OS_WINDOWS + #include +#endif //OS_WINDOWS + +#include +#include + +static const char* const image_protect_data[] = { +"16 15 6 1", +"# c #000000", +"a c #008000", +"c c #00ff00", +"d c #808080", +". c #ff0000", +"b c #ffffff", +".......#.......#", +".aaaaaa#.aaaaaa#", +".a.aa.a#.a.aa.a#", +".aaaaaa#.aaaaaa#", +".abbbba#.abbbba#", +".acccba#.acccba#", +".adccba#.adccba#", +".acdcba#.acdcba#", +".acdcba#.acdcba#", +".accdba#.accdba#", +".acccba#.acccba#", +".acccba#.acccba#", +".aaaaaa#.aaaaaa#", +".aaaaaa#.aaaaaa#", +".#######.#######"}; + +static const char* const image_protectclose_data[] = { +"16 15 5 1", +"# c #000000", +"c c #808080", +"a c #c0c0c0", +". c #ff0000", +"b c #ffffff", +".......#.......#", +".aaaaaa#.aaaaaa#", +".a.aa.a#.a.aa.a#", +".aaaaaa#.aaaaaa#", +".abbbba#.abbbba#", +".a###ba#.a###ba#", +".ac##ba#.ac##ba#", +".a#c#ba#.a#c#ba#", +".a#c#ba#.a#c#ba#", +".a##cba#.a##cba#", +".a###ba#.a###ba#", +".a###ba#.a###ba#", +".aaaaaa#.aaaaaa#", +".aaaaaa#.aaaaaa#", +".#######.#######"}; + +static const char* const image_open_data[] = { +"16 15 5 1", +"# c #040404", +"c c #808000", +"a c #808080", +". c #c0c0c0", +"b c #ffff00", +".......#a###....", +".......##...#...", +".......###...#..", +".###.........#..", +"#.b.#######..#..", +"#b.b.b.b.b#.....", +"#.b.b.b.b.#.....", +"#b.b.##########.", +"#.b.#ccccccccc#.", +"#b.#ccccccccc#..", +"#.#ccccccccc#...", +"##ccccccccc#....", +"###########.....", +"................", +"................"}; + +static const char* const image_print_data[] = { +"16 15 5 1", +"# c #040404", +"b c #808080", +". c #c0c0c0", +"c c #ffff00", +"a c #ffffff", +".....#########..", +"....#aaaaaaaa#..", +"....#a#####a#...", +"...#aaaaaaaa#...", +"...#a#####a####.", +"..#aaaaaaaa#.#.#", +".##########.#.##", +"#..........#.#.#", +"#############..#", +"#......bbb..#.#.", +"#......ccc..###.", +"#############.#.", +".#.........#.#..", +"..###########...", +"................"}; + +static const char* const image_start_data[] = { +"16 15 7 1", +"d c #000000", +"e c #00ff00", +"# c #800000", +"a c #808080", +". c #c0c0c0", +"c c #ff0000", +"b c #ffff00", +".....######.....", +"...##aaaaaa##...", +"..#aabbbcccccd..", +".#abbcccccccc#d.", +".#abcccccccceed.", +"#abbccccccceee#d", +"#abccccccceeec#d", +"#abceeccceeecc#d", +"#abceeeceeeccc#d", +"#accceeeeeccc##d", +".#accceeecccc#d.", +".#accccecccc##d.", +"..daaccccc###d..", +"...dd######dd...", +".....dddddd....."}; + +static const char* const image_stop_data[] = { +"16 15 6 1", +"d c #000000", +"# c #800000", +"a c #808080", +". c #c0c0c0", +"c c #ff0000", +"b c #ffff00", +".....######.....", +"...##aaaaaa##...", +"..#aabbbcccccd..", +".#abbcccccccc#d.", +".#ab...ccc...cd.", +"#abbc...c...cc#d", +"#abccc.....ccc#d", +"#abcccc...cccc#d", +"#abccc.....ccc#d", +"#accc...c...c##d", +".#ac...ccc...#d.", +".#accccccccc##d.", +"..dacccccc###d..", +"...ad######dd...", +".....dddddd....."}; + +static const char* const image_bird_data[] = { +"16 15 15 1", +"# c #040404", +"d c #222222", +"k c #333300", +"f c #333333", +"b c #393939", +"g c #424242", +"i c #555555", +"h c #666666", +"l c #808000", +"a c #808080", +"e c #969696", +". c #c0c0c0", +"m c #cccc00", +"j c #cccc33", +"c c #ffffff", +"...###..........", +"..#aa.b...#####.", +".#c.ab#..#dde##.", +".#.fag#..dd.e##.", +".#hehg##ggee##..", +".#.eig##h##h#...", +"..#hf#ddh#####..", +"...feh#dhb.c.jk.", +"...#eehg#bcca#k.", +"...########b....", +"..#f###ff##.....", +"ffhhfhh###......", +"feh##.klk.......", +"#f#..##ml###....", +"..#...###lk....."}; + +static const char* const image_bookclose_data[] = { +"16 15 5 1", +"# c #040404", +"a c #800080", +"b c #808080", +". c #c0c0c0", +"c c #ffffff", +".......##.......", +".....##aa#......", +"...##aaaaa#.....", +".##aaaaaaaa#....", +"#.aaaaaaaaaa#...", +"#a.aaaaaaaaaa#..", +"#aa.aaaaaaaaaa#.", +"#aaa.aaaaaaaaa##", +"#aaaa.aaaaaa###.", +".#aaaa.aaa##bc#.", +"..#aaaa.##b.c.##", +"...#aaa#bc.c.##.", +"....#aa#c.c##...", +".....#a#b##.....", +"......###......."}; + +static const char* const image_bookopen_data[] = { +"16 15 6 1", +"# c #040404", +"a c #800080", +"d c #808080", +". c #c0c0c0", +"c c #ffff00", +"b c #ffffff", +"..#.............", +".#.#............", +"#ab.#....###....", +"#abb#..##bb#....", +"#abb.##bbbcd##..", +"#abbb#.bcbbdba#.", +"#abbb#.bbbcdba#.", +"#abbb#.bcbbdba##", +"#abbb#.bbbcdba#.", +"#abbb#.bcbbdba#.", +"#aabb#.bbbd.ba##", +".#aab#.bdd.bba#.", +"..#ab#dd.bbbba#.", +"...#aaaaaaaaaa#.", +"....###########."}; + +static const char* const image_computer_data[] = { +"16 15 7 1", +"d c #0000ff", +"e c #008000", +"c c #008080", +"# c #040404", +"b c #808080", +"a c #c0c0c0", +". c #ffffff", +"....###########.", +"...#aaaaaaaaaa##", +"...#.........bb#", +"...#.#######abb#", +"...#.#cbbbdcabb#", +"...#.#caaabcabb#", +"...#.#cbbbbcabb#", +"...#.#ccccccabb#", +"...#.aaaaaaaab##", +"...#aaaaaaeea#b#", +"...#bbbbbbbbbba#", +"...#aaaaaaaaaab#", +"..##b#b#b#b#bbb#", +".##a#a#a#a#a#b#.", +"##############.."}; + +static const char* const image_computeropen_data[] = { +"16 15 7 1", +"d c #0000ff", +"e c #00ff00", +"c c #00ffff", +"# c #040404", +"b c #808080", +"a c #c0c0c0", +". c #ffffff", +"....###########.", +"...#aaaaaaaaaa##", +"...#.........bb#", +"...#.#######abb#", +"...#.#cbbbdcabb#", +"...#.#caaabcabb#", +"...#.#cbbbbcabb#", +"...#.#ccccccabb#", +"...#.aaaaaaaab##", +"...#aaaaaaeea#b#", +"...#bbbbbbbbbba#", +"...#aaaaaaaaaab#", +"..##b#b#b#b#bbb#", +".##a#a#a#a#a#b#.", +"##############.."}; + +static const char* const image_exit_data[] = { +"16 15 7 1", +"b c #000080", +"d c #008000", +"a c #008080", +"e c #00ffff", +"# c #040404", +". c #c0c0c0", +"c c #ffff00", +"....##########..", +"....#aaaaaaab#..", +"....#aaaaaabb#..", +"....#caaaabbd#..", +"....#ccaaabdd#..", +".cccccccaabdd#..", +".eeeeeeccabdd#..", +".cccccccaab#d#..", +"....#ccaaab#d#..", +"....#caaaabdd#..", +"....#aaaaabdd#..", +"....#.....bdd#..", +"#####.....bdb###", +"..........bb....", +"..........b....."}; + +static const char* const image_eventblock_data[] = { +"16 15 6 1", +"# c #000000", +"a c #000080", +"c c #0000ff", +"d c #808080", +". c #ff0000", +"b c #ffffff", +".......#.......#", +".aaaaaa#.aaaaaa#", +".a.aa.a#.a.aa.a#", +".aaaaaa#.aaaaaa#", +".abbbba#.abbbba#", +".acccba#.acccba#", +".adccba#.adccba#", +".acdcba#.acdcba#", +".acdcba#.acdcba#", +".accdba#.accdba#", +".acccba#.acccba#", +".acccba#.acccba#", +".aaaaaa#.aaaaaa#", +".aaaaaa#.aaaaaa#", +".#######.#######"}; + +static const char* const image_delevents_enable_data[] = { +"15 15 5 1", +"c c #800000", +"# c #808080", +". c #c0c0c0", +"a c #ff0000", +"b c #ffff00", +"...............", +".#a#.........a.", +".abac......ac..", +"..aaac....ac...", +"....aac..ac....", +".....aacac.....", +"......aac......", +".....aacac.....", +"....aac..ac....", +"...aac....ac...", +"..aaa......a...", +".abac.......a..", +".aac...........", +"..c..........a.", +"..............."}; + +static const char* const image_delevents_disable_data[] = { +"15 15 4 1", +"b c #000000", +"# c #808080", +". c #c0c0c0", +"a c #ffffff", +"...............", +".###.........#.", +".#a.b......#b..", +"..##.b....#b...", +"....#.b..#b....", +".....##b#b.....", +"......##b......", +".....##b#b.....", +"....##b..#b....", +"...#.b....#b...", +"..#.b......#...", +".#a#b.......#..", +".##b...........", +"..b..........#.", +"..............."}; + +static const char* const image_fixsetting_data[] = { +"16 16 11 1", +"a c #000000", +"b c #000080", +"d c #0000ff", +"i c #008080", +"e c #00ff00", +"h c #00ffff", +"f c #808000", +"# c #808080", +". c #c0c0c0", +"g c #ffff00", +"c c #ffffff", +"................", +"############a...", +"#bbbbbbbbbbba...", +"############a...", +"#.cccccccccca...", +"#.cdecffc##ca...", +"#.cebcfga#caafa.", +"#.ccccafg#cafga.", +"#.cdhaaca#caafaa", +"#.cihafgcaaacgfa", +"#.cccafagcgcgafa", +"#.....agfacffga.", +"aaaaaaffaagfafga", +"......aa.afa.aa.", +".........aaa....", +"................"}; + +static const char* const image_login_data[] = { +"16 16 22 1", +"# c #000000", +"t c #000080", +"p c #0000ff", +"o c #0099ff", +"a c #040404", +"r c #330000", +"h c #333300", +"j c #666600", +"m c #800000", +"f c #808080", +"i c #996600", +"b c #ada990", +"e c #c0c0c0", +". c #cbcbcb", +"s c #cc9900", +"c c #cc9933", +"q c #cccc33", +"g c #eaeaea", +"n c #ff0000", +"d c #ffcc66", +"l c #ffff00", +"k c #ffff99", +"...########.....", +".########a##....", +"######a#bc##....", +"#####de#cd#.....", +"###aded#b##.....", +"##eded##cbcf....", +"##dedgdbhd#.....", +".##dedb#cb#ij#i.", +"..#eced###ikkl#i", +".#ecf###..jkj#l#", +"###ec#mmn.illil#", +"#op#####m#lhql#j", +"#poppppphkrsr#j.", +"..#oott#krqrj...", +".......#qsrj....", +"........#rj....."}; + +static const char* const image_suo256_data[] = { +"16 16 60 1", +"3 c #5f5b52", +"d c #676663", +"s c #707070", +"4 c #746538", +"5 c #777777", +"l c #9c7f46", +"k c #ad883a", +"f c #ae9855", +"n c #b69244", +"v c #bfb176", +"M c #c7ac58", +"B c #c89603", +"r c #cc9900", +"m c #cd9a03", +"1 c #d3a00f", +"Z c #d4a10f", +"o c #d4a110", +"i c #d5a212", +"# c #d6ac1d", +"h c #d6ac30", +"t c #dcb53c", +"g c #dcbc5a", +"T c #dfac25", +"0 c #e1ba46", +"N c #e2c56b", +"G c #e3cc7a", +"u c #e5bd50", +"P c #e6b333", +"S c #e8d479", +"w c #e9d28f", +"e c #ebcf55", +"q c #ebd899", +"a c #ecd960", +"p c #edba42", +"J c #f2c250", +"X c #f2cb58", +"c c #f2de6a", +". c #f2e4b5", +"H c #f2e686", +"b c #f5ec7c", +"y c #f8efd1", +"j c #f9d46d", +"Y c #f9d86c", +"x c #f9e0a7", +"K c #fcf3c3", +"A c #fcf5cb", +"Q c #fef5ae", +"D c #fefae0", +"C c #ffd771", +"2 c #ffd872", +"V c #ffe17b", +"W c #ffe37e", +"R c #ffee88", +"L c #fff993", +"O c #fffc96", +"F c #fffcac", +"z c #fffdd9", +"I c #ffff9c", +"U c #ffffa6", +"E c #ffffb3", +".......###......", +"......#aba#.....", +".....#cddef.....", +".....#d..gf#....", +".....#d..ghf....", +".....#ijjklm....", +"....#nkoipqrs...", +"...tuvwxyzABs...", +"...tCDEFGHIrs...", +"...tJKLLMNOrs...", +"...tPQRRnSRrs...", +"...tTUVWXYZ0s...", +"...t1K22iik3....", +"....1iii43s.....", +".....5555.......", +"................"}; + +static const char* const image_key256_data[] = { +"16 16 170 2", +"az c #ae6c00", +"aB c #ae6d0f", +"aM c #af6e00", +"aE c #b0741a", +"aC c #b17216", +"aD c #b1741a", +".B c #b37519", +"aF c #b37618", +"aG c #b37717", +".O c #b5781e", +"aH c #b67a13", +".1 c #b67b23", +"#n c #b77c21", +"#b c #b77c23", +"an c #b87602", +"aK c #b87a07", +"#x c #b87d1d", +"#H c #b97e18", +"aL c #ba7902", +"ac c #ba7b05", +"aJ c #ba7c0a", +"aI c #ba7c0d", +"#2 c #bb7d0b", +"#Q c #bb7f12", +"ao c #cb8011", +"aN c #ceaf7f", +".m c #cf8a23", +"ay c #d08e01", +".A c #d3922f", +"ad c #d58a19", +".N c #d59635", +"#3 c #d78e22", +"at c #d79d24", +"as c #d89f38", +"aA c #d8b685", +"#R c #d9942c", +".l c #d99631", +"am c #d99b04", +"ax c #d99b05", +"#P c #d9a018", +"aw c #d9a10d", +"#k c #da9624", +"#I c #da9835", +"ab c #daa008", +"#1 c #daa10f", +"au c #daa11c", +"av c #daa215", +"ar c #daa248", +".n c #daba8a", +"#h c #db9a36", +".8 c #db9a3a", +".k c #dc9b3b", +".W c #dc9b3e", +".j c #dc9d3f", +"## c #dc9e3b", +"#u c #dd9d24", +"#t c #dd9e2c", +".V c #dd9e45", +"#s c #dd9f36", +"#G c #dda839", +".z c #dea045", +".i c #dea146", +"#5 c #dea248", +".g c #dea24a", +"#v c #dea32e", +"#B c #dea341", +".h c #dea34b", +"#g c #dfa44e", +"#V c #dfa546", +"#L c #dfa549", +"#U c #dfa54c", +".f c #dfa54f", +".X c #dfa651", +"#i c #e0a546", +".2 c #e0a753", +".e c #e0a754", +"#y c #e0a956", +"#p c #e1a857", +"#e c #e1a959", +".7 c #e1aa5a", +".d c #e1aa5b", +"#o c #e1aa5c", +".5 c #e1ab5e", +"al c #e2ac0a", +".P c #e2ac5e", +"#0 c #e2ad14", +"ai c #e2ad24", +"#d c #e2ad61", +"#D c #e2ae41", +"#r c #e2af5e", +".R c #e3ae63", +"#c c #e3af63", +".S c #e3af66", +"aa c #e3b00e", +"ak c #e3b013", +"aj c #e3b01c", +".G c #e3b167", +".0 c #e3b775", +"#Z c #e4b11b", +"#9 c #e4b12b", +".c c #e4b167", +".Y c #e4b267", +".4 c #e4b268", +".t c #e4b26a", +"a. c #e4b321", +"#j c #e4b362", +"ae c #e4b36b", +"ah c #e4b54c", +"a# c #e5b418", +"#C c #e5b45b", +".C c #e5b46b", +".3 c #e5b46c", +".F c #e5b66f", +".s c #e5b670", +"aq c #e5bf85", +"#S c #e6b874", +"#E c #e6b955", +".b c #e6b976", +"#f c #e7b97a", +"#O c #e7ba43", +".o c #e7ba77", +".r c #e7bb79", +".Q c #e7bc7a", +".6 c #e8bd80", +".E c #e8bf80", +"#J c #e9bf83", +"#z c #e9c186", +".u c #e9c187", +"#w c #e9c98c", +"#Y c #eac252", +"#X c #eac564", +".q c #eac58c", +".D c #eac58d", +"#6 c #ebc68e", +".H c #ebc691", +"af c #ebc891", +"#q c #ebc894", +"#M c #ebc98b", +".y c #ecc893", +".K c #ecc996", +".p c #eecd9d", +".9 c #eece9e", +"#4 c #eed0a3", +"#l c #efd2a1", +"#A c #f0d4aa", +".L c #f0d5ae", +"Qt c #f0dab7", +"#K c #f1d7b0", +".M c #f1d7b1", +".a c #f1d7b2", +"#T c #f1d9b4", +"#a c #f2d9b2", +"#m c #f2dfbf", +"#7 c #f3ddb8", +".U c #f3dfc1", +".v c #f4e0c3", +"ap c #f6e8d4", +"#8 c #f7e7c5", +".x c #f7e9d4", +"#W c #f8eace", +"#N c #f8ecca", +".J c #f9eddd", +"ag c #faf1df", +".T c #faf1e4", +"#F c #fbf3e3", +".w c #fbf5eb", +"#. c #fefcf8", +".I c #fefcf9", +".Z c #fffefd", +".# c #ffffff", +"Qt.#.#.#.#.#.#.#.#.#.#.#.#.#.#Qt", +".#.a.b.c.d.e.f.g.h.i.j.k.l.m.n.#", +".#.o.p.q.r.s.t.u.v.w.x.y.z.A.B.#", +".#.C.D.E.F.G.H.I.J.K.L.#.M.N.O.#", +".#.P.Q.s.R.S.T.U.V.W.X.Y.Z.0.1.#", +".#.2.3.4.5.6.#.7.8.9#.###aQt#b.#", +".#.f#c#d#e#f.##g#h#i#j#k#l#m#n.#", +".#.z.7#o#p#q.##r#s#t#u#v.##w#x.#", +".#.j.2#y#z.##A#B#C#D#E.##F#G#H.#", +".##I.h#J.##K#L#M#..#.##N#O#P#Q.#", +".##R#S.##T#U#V.##W#X#Y#Z#0#1#2.#", +".##3.##4#5#6#7.##8#9a.a#aaabac.#", +".#ad.#aeaf.#.#agahaiajakalaman.#", +".#aoap.#.#aqarasatauavawaxayaz.#", +".#aAaBaCaDaEaFaGaHaIaJaKaLaMaN.#", +"Qt.#.#.#.#.#.#.#.#.#.#.#.#.#.#Qt"}; + +static const char* const image_power256_data[] = { +"16 16 245 2", +"bF c #7b431e", +"bE c #7e4623", +"ay c #82401e", +"bJ c #843318", +"#P c #854426", +"aO c #893217", +"bA c #8b3a29", +"bz c #8b4636", +"bw c #8c4527", +".R c #8d4838", +"bK c #8e4729", +"bG c #904e2c", +"bD c #915032", +"ai c #915934", +"bg c #934227", +"#4 c #935b38", +"#3 c #965b39", +"bB c #983c2d", +"#z c #98412d", +"bI c #993d24", +"bH c #9b4429", +"a3 c #9e4229", +"bv c #9f3f27", +"bC c #9f4834", +"ah c #9f6540", +".w c #9f735a", +"#k c #a14536", +".A c #a15346", +"bj c #a25f4f", +".B c #a36050", +"al c #a36b54", +"#K c #a56343", +"bq c #a56b46", +".v c #a67c63", +"bk c #a84a42", +"a5 c #a85a4d", +"#Z c #a8734b", +"bp c #a96e4c", +"#T c #a97b61", +"#7 c #a97d64", +"aB c #aa5b4c", +"br c #aa5e3e", +"bo c #aa5e44", +"#8 c #ab7c62", +".6 c #ac5a4c", +"bf c #ad3a28", +"#C c #ad7d67", +"ad c #af784f", +"#W c #af7d5a", +"#S c #af856c", +"at c #b16d48", +".r c #b2776f", +"bs c #b44531", +"au c #b45539", +".y c #b56659", +"aq c #b67454", +"aR c #b76056", +"#m c #b9756a", +".5 c #ba4943", +"bn c #ba4c3f", +"#L c #ba5b45", +"ax c #ba6e4e", +"#H c #bb7e61", +"aa c #bb8762", +".u c #bc8c76", +"a2 c #bd4232", +"am c #bd7966", +".x c #bf8770", +".K c #bf9177", +"be c #c03e31", +"#y c #c05245", +".t c #c07c71", +".s c #c17b73", +"#O c #c2765c", +".z c #c36c62", +".M c #c37f6a", +"bL c #c38667", +"bu c #c4513f", +"aN c #c45541", +".L c #c4957b", +".Q c #c5675f", +"ap c #c66b56", +".E c #c6978d", +"a6 c #c75753", +"#t c #c76353", +"#0 c #c85f4a", +"#u c #c86d58", +"a1 c #c94e3e", +"#i c #c94f4a", +".q c #c99a90", +"#D c #ca8d7a", +".T c #ca8f87", +"ae c #cb624c", +"bt c #cc5141", +"aC c #cc635d", +"#s c #cc6b5a", +"aJ c #cc6d51", +"#r c #cc7562", +"#G c #cc7763", +"bm c #cd524d", +"aG c #ce6f59", +"a7 c #cf4f4e", +".J c #cf927f", +"bd c #d05545", +".4 c #d15150", +".C c #d19684", +".9 c #d28c84", +"bl c #d5645e", +"aT c #d65f59", +"aI c #d66d57", +"#j c #d75c57", +"aS c #d75f5e", +"#V c #d77665", +".P c #d96965", +".N c #d9706a", +".3 c #db645e", +"#v c #db9176", +"aH c #dc735d", +"a# c #dc7966", +"a8 c #dd635e", +".I c #de817c", +"Qt c #e4c8bc", +"#n c #e68984", +"#e c #e77d70", +".O c #e97170", +".W c #e97f7f", +".p c #eac8bc", +"#d c #eb8376", +"aK c #eb9f7d", +"## c #ec8483", +"#q c #edad94", +".U c #ef9394", +"#1 c #f07f6d", +"#U c #f0887d", +".F c #f1a7a4", +"aX c #f2826e", +"af c #f68672", +"aM c #f68974", +".V c #f6898c", +"bN c #f6c1af", +"#. c #f78f90", +"aF c #f7ad92", +"#x c #f98d80", +"a. c #f98f82", +".2 c #fa9287", +"#o c #fb9e96", +".n c #fbc6b4", +".H c #fd9596", +"bY c #fec8a6", +"a9 c #ff9386", +"bc c #ff947f", +"aD c #ff9e93", +"#f c #ffa898", +".G c #ffa8a9", +".X c #ffaaa2", +"#h c #ffab97", +"ao c #ffb1a1", +"#c c #ffb3a5", +"#M c #ffb4a0", +"a0 c #ffb597", +"aY c #ffb79e", +"av c #ffbba2", +"aW c #ffbca8", +"#F c #ffbcae", +"aU c #ffbda9", +"#a c #ffbdaf", +"bb c #ffcdb1", +"aw c #ffceb2", +"b. c #ffd1bb", +".Y c #ffd3c2", +"#N c #ffd5bf", +"aE c #ffd8c1", +"#p c #ffdac7", +"#w c #ffddc3", +"#E c #ffdecd", +"#b c #ffdfcc", +".1 c #ffe0cd", +"ag c #ffe1c1", +"aZ c #ffe2c1", +"aV c #ffe3c9", +"aL c #ffe5c4", +"bU c #ffe5c6", +"an c #ffe5d2", +".m c #ffe6d4", +"#A c #ffe7ce", +".7 c #ffe7d3", +"#2 c #ffe8ca", +"bi c #ffe8d4", +"a4 c #ffe8d6", +"aQ c #ffe8d9", +"#g c #ffe9d2", +"bQ c #ffead1", +"bx c #ffebc8", +"b# c #ffebcd", +".e c #ffebd6", +"#l c #ffebdc", +"#I c #ffecc7", +"bT c #ffecc8", +"ba c #ffeccc", +"aP c #ffeccd", +"bP c #ffecd6", +".S c #ffecd8", +".i c #ffecdb", +".j c #ffecdc", +".8 c #ffece0", +"bh c #ffedcd", +"#9 c #ffedd6", +".h c #ffedd7", +".0 c #ffedd8", +"aA c #ffeddc", +".Z c #ffeed8", +"bW c #ffefcc", +"bX c #ffefce", +"bV c #ffefcf", +"bO c #ffefdb", +".k c #ffefdd", +".D c #ffefe2", +"#5 c #fff0cc", +"#Q c #fff0d1", +"bR c #fff0d3", +".c c #fff0e4", +"as c #fff1ca", +"az c #fff1cd", +"#R c #fff1d8", +".l c #fff1dd", +"by c #fff1df", +".d c #fff1e1", +"#6 c #fff2d9", +"ak c #fff2dc", +".a c #fff2e5", +"aj c #fff3cd", +"bS c #fff3cf", +"bM c #fff3d1", +"ar c #fff4cc", +"#J c #fff4cf", +"#B c #fff4df", +".g c #fff5dc", +".b c #fff5e6", +".f c #fff6dd", +".o c #fff7ec", +"ab c #fff8c9", +".# c #fff8ea", +"ac c #fffaca", +"#Y c #fffacb", +"#X c #fffccd", +"Qt.#.a.b.c.d.e.f.g.h.i.j.k.l.m.n", +".o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.l", +".D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S", +".b.T.U.V.W.X.Y.Z.0.1.2.3.4.5.6.7", +".8.9#.###a#b#c#d#e#f#g#h#i#j#k.e", +"#l#m#n#o#p#q#r#s#t#u#v#w#x#y#z#A", +"#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q", +"#R#S#T.Z#U#V#W#X#Y#Z#0#1#2#3#4#5", +"#6#7#8#9a.a#aaabacadaeafagahaiaj", +"akalamanaoapaqarasatauavawaxayaz", +"aAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaP", +"aQaRaSaTaUaVaW#1aXaYaZa0a1a2a3aP", +"a4a5a6a7a8a9b.b#babbbcbdbebfbgbh", +"bibjbkblbmbnbobpbqbrbsbtbubvbwbx", +"by.CbzbAbBbCbDbEbFbGbHbIbJbKbLbM", +"bNbObObP.ebQbRbSbSbTaPbUbVbWbXbY"}; + +static const char* const image_carton24b_data[] = { +"80 100 7721 3", +"#SU c #000013", +"#HL c #000219", +"#HM c #00021b", +"#Ff c #000c29", +"#Fe c #001139", +"#Gk c #002458", +".#m c #010f67", +"#I1 c #012245", +"#Ry c #01266c", +".az c #030e7a", +"#ww c #03215f", +"#QQ c #032d2b", +".#n c #041368", +"#I2 c #042649", +".gk c #05168a", +"#ST c #051a4f", +"#ug c #051d59", +"#J2 c #052a61", +"#QP c #052d2c", +"#HB c #06114f", +".jx c #061a97", +"#F. c #061b52", +"#HK c #070723", +".gi c #071989", +"#uh c #071c51", +"#Fd c #071d4e", +"#tR c #071f5b", +".#h c #081283", +".ay c #08137f", +".fb c #081391", +".#l c #081571", +"#s5 c #081b53", +"#DY c #081c5b", +"#tS c #081e58", +"#DX c #08205e", +".ig c #08209a", +"#xZ c #082970", +"#s2 c #083061", +"#A# c #083753", +"#HJ c #09092d", +"#Fg c #091126", +".bG c #091386", +".fa c #091494", +"#uk c #091f5b", +"#sC c #092064", +".k0 c #092a9e", +"#wv c #092b72", +"#Gj c #092e65", +"#IW c #092e74", +"#Ke c #094078", +"#D7 c #0a0a22", +".au c #0a1487", +"#s7 c #0a1e59", +"#sz c #0a1e5d", +"#s8 c #0a205c", +"#wx c #0a2155", +"#s4 c #0a2359", +"#x0 c #0a2568", +"#uf c #0a2a63", +"#s3 c #0a2b5e", +".kZ c #0a2da1", +"#Aa c #0a324c", +".fc c #0b1692", +".hs c #0b1c92", +"#sy c #0b1f5e", +".aN c #0b1fb6", +"#ui c #0b2057", +"#s6 c #0b2059", +"#DW c #0b245c", +"#xM c #0b2653", +"#I0 c #0b294f", +"#J3 c #0b2f63", +"#xY c #0b3077", +"#s1 c #0b3364", +"#F6 c #0b3c4a", +"#D8 c #0c0e25", +"#Qt c #0c0f20", +"#CU c #0c0f2e", +"#BD c #0c1347", +"#BC c #0c154c", +"#An c #0c165b", +"#i9 c #0c195f", +"#0j c #0c1a1b", +".jw c #0c1c96", +"#sA c #0c2162", +"#sB c #0c2164", +".if c #0c229c", +"#ul c #0c2464", +"#Ql c #0c2961", +".kz c #0c29ab", +".q1 c #0c2d96", +"#LT c #0c2f29", +".uz c #0c4393", +"#z9 c #0c4b74", +"#NW c #0c4b98", +"#CV c #0d1230", +".cR c #0d1786", +".dZ c #0d1792", +".#i c #0d1884", +".cU c #0d188c", +".f4 c #0d1a83", +"#Gl c #0d1d59", +".jv c #0d1d97", +".aO c #0d22bd", +"#uj c #0d235c", +"#Ac c #0d2444", +".kx c #0d24a8", +".ey c #0d24b2", +"#E3 c #0d2565", +".ky c #0d25a9", +".l5 c #0d2fab", +"#V6 c #0d302a", +".l6 c #0d31ab", +"#IK c #0d3b90", +"#ue c #0d3c70", +"#A. c #0d405d", +".uE c #0d418c", +".uD c #0d428e", +".vP c #0d4693", +".uA c #0d4894", +"#CT c #0e0f2d", +".bH c #0e188b", +".#k c #0e1a7c", +"#Bu c #0e1c5b", +".f# c #0e1e8d", +".hu c #0e1e97", +".hr c #0e1f93", +".k. c #0e1f95", +".kw c #0e20a6", +"#RD c #0e2455", +"#xR c #0e2571", +"#E9 c #0e275f", +"#pv c #0e2875", +"#IY c #0e2a5c", +".aU c #0e2ab9", +"#IZ c #0e2b57", +"#Ab c #0e2d49", +".#H c #0e2fbc", +".uy c #0e4595", +".AU c #0e57c6", +"#BE c #0f1342", +"QtT c #0f16bc", +".bD c #0f1784", +"QtS c #0f17ba", +".cS c #0f1988", +".dY c #0f1994", +"#i8 c #0f1c62", +".dX c #0f1d8a", +".la c #0f1e95", +"#rK c #0f1f5a", +".fS c #0f1f98", +".gj c #0f2092", +"#D2 c #0f2243", +"#rL c #0f225d", +".j9 c #0f228b", +"#sx c #0f2360", +"#qy c #0f255e", +"#sD c #0f266c", +"#RC c #0f2753", +"#wt c #0f2765", +"#tM c #0f2868", +"#yZ c #0f294e", +"#IX c #0f2a61", +"#E5 c #0f2a6f", +"#tO c #0f2b6a", +"#tN c #0f2b6c", +"#wu c #0f2c68", +"#pw c #0f2c78", +"#xL c #0f2f58", +"#L7 c #0f372e", +".l7 c #0f37a8", +".tr c #0f3f8b", +".tq c #0f408c", +".uC c #0f4792", +"#Kf c #0f487f", +".uB c #0f4993", +"#NV c #0f4c9c", +"#CS c #10112f", +"#CR c #101332", +"Qt9 c #10149c", +"#HN c #101733", +".bE c #101885", +".bM c #101895", +".d0 c #101a93", +"#MC c #101b5d", +".aA c #101b87", +".cL c #101c8c", +".fd c #101c94", +".f5 c #101d86", +"#va c #101e5b", +"#Fj c #101f36", +"#pt c #101f70", +"#Av c #102051", +"#F# c #102054", +".fk c #102082", +".e7 c #10208f", +".hc c #102091", +"#Fk c #10213d", +".hy c #10218b", +".hd c #10218d", +"#pu c #102372", +".hC c #102382", +"#CJ c #10245f", +".jy c #1024a1", +"#qz c #102864", +"#vC c #102969", +".aP c #1029c3", +"#wP c #102d69", +"#vB c #10306d", +".l4 c #1031b2", +"#QT c #10323b", +"#J1 c #103674", +"#L2 c #103935", +"#Kd c #10427d", +".vO c #104690", +"#NX c #10509a", +".bf c #11109a", +"Qt2 c #1112ab", +"#D6 c #11132a", +"#HI c #11143f", +".#f c #111497", +"Qt7 c #1114a1", +".#a c #111592", +".eW c #11178f", +".#7 c #1117ad", +"#vb c #11195a", +".ax c #111b8a", +".av c #111b8c", +".#g c #111b8e", +".d1 c #111c92", +".#j c #111d83", +".f3 c #111d8b", +"#kh c #112065", +"#ps c #112071", +".go c #112093", +".k# c #112097", +".lh c #11219a", +"#rJ c #11225a", +"#Lm c #112268", +".i6 c #112296", +".ht c #112298", +".ds c #1123b5", +".hU c #1124a4", +".oC c #112595", +".hT c #1125a0", +"#qx c #11265b", +"#Ll c #112669", +"#tK c #112965", +"#wQ c #112967", +"#tJ c #112a63", +"#E4 c #112a6d", +"#tL c #112b68", +"#E6 c #112c71", +"#xS c #112e7c", +".k1 c #1130a5", +"#Rx c #11348e", +"#s0 c #113567", +"#Gg c #11366d", +"#QR c #113939", +".l8 c #1139aa", +"#so c #113b65", +".ts c #113f8a", +".uF c #11428e", +"#vz c #114382", +".vN c #114791", +"#vy c #114a8d", +".vQ c #114b95", +"#z8 c #114f78", +"#Gu c #120e2f", +".bg c #121298", +".#b c #121694", +".at c #121890", +".#6 c #1218ac", +".#1 c #1219b2", +".bC c #121a87", +".d2 c #121d93", +"#Au c #121e4e", +".cM c #121e8e", +"#DZ c #12205f", +"#kk c #122166", +".hb c #122196", +".ha c #122198", +"#0k c #122222", +".ju c #12229c", +".gs c #12238d", +".i5 c #122397", +"#ws c #122464", +".gf c #122492", +"#xQ c #122571", +"#rS c #12265b", +".do c #1226bb", +"#tT c #122760", +".nv c #1228a2", +"#ks c #122b6e", +".iK c #122ca7", +"#tP c #122e6d", +".iy c #122e99", +"#xP c #123076", +".iL c #1235ad", +"#Rz c #123668", +".it c #1236a8", +"#Bn c #123754", +"#vA c #123a77", +".yo c #123f94", +"#IJ c #12468f", +".ya c #124a95", +"#vx c #125196", +"#Gv c #130e25", +"QtZ c #1314bc", +".## c #131794", +".#8 c #1318b2", +".as c #131991", +"#Fh c #131a2c", +"#o9 c #131b59", +".bL c #131b97", +".eZ c #131c93", +"#0i c #131d1e", +"#Fi c #131e30", +"#hK c #131f69", +".kb c #131f97", +"#Am c #132066", +".dU c #132090", +"#vi c #132162", +".dV c #13218e", +".lk c #13219b", +".i8 c #132297", +".hD c #132385", +"#0s c #13241c", +".eC c #1324b0", +"#1A c #132620", +"#v# c #132661", +"#qw c #13275a", +"#rT c #13275c", +"#rR c #13285d", +"#qK c #132867", +"#s9 c #132869", +".hm c #132895", +".j3 c #13289b", +".ns c #1329a0", +".ie c #1329a3", +"#kr c #132a6e", +".jL c #132a9a", +"#rl c #132c64", +"#E8 c #13306a", +".iz c #133098", +".kA c #1330b2", +"#sZ c #133165", +"#yY c #133558", +"#V5 c #133630", +"#Gf c #133767", +"#ri c #133864", +".kY c #1338ab", +"#Hz c #133a7d", +".b7 c #133bc1", +".na c #133eb1", +".sd c #133f8a", +"#Cw c #134173", +".80 c #1341b1", +"#QV c #134238", +".tp c #134894", +"#ud c #134b7c", +".ye c #134c93", +"#IH c #13507f", +".AT c #1359d2", +"#D9 c #14162f", +"Qt5 c #1416a9", +"#BF c #141740", +".#e c #14179a", +".#4 c #1419b1", +"#p. c #141a56", +".#5 c #141ab0", +".ar c #141b90", +"#BI c #141c43", +".bF c #141c89", +".eY c #141d94", +".aw c #141e8d", +"#Fc c #141f5f", +"#k. c #142068", +".f8 c #142090", +".i9 c #142096", +"#j. c #142167", +".gO c #14229f", +".kv c #1422a9", +".dt c #1422b6", +"#Ad c #14234c", +"#vg c #142366", +"#kj c #142368", +".hE c #142388", +".gb c #142396", +".i7 c #142398", +".f. c #142493", +".gp c #142495", +".jt c #14249e", +"#Ln c #14256d", +".gc c #142597", +"#qJ c #142666", +"#qv c #14285a", +"#rM c #142865", +".iQ c #14289b", +"#pr c #142978", +".hn c #142996", +".mi c #1429a0", +".jz c #1429a6", +"#sY c #142b61", +"#vD c #142b6e", +"#m2 c #142b6f", +".iw c #142b9d", +"#o. c #142c6a", +"#oj c #142c84", +".#I c #142dbb", +"#og c #142e85", +".iv c #142fa2", +"#sw c #143173", +"#z1 c #143369", +".k2 c #1433a8", +".sg c #1433cb", +"#wO c #143675", +".n# c #143daf", +".tt c #14408b", +".dg c #1440b9", +"#QU c #14413a", +".vU c #144891", +".ux c #144b9d", +".yb c #144c96", +".vR c #144c97", +".y# c #144c99", +".w4 c #144e98", +".be c #1513a2", +".#c c #151899", +".#. c #151996", +"#BH c #151a40", +".eR c #151a82", +".bB c #151d8a", +"QtR c #151dbe", +"#BJ c #151e45", +"#hN c #151e6b", +"#vf c #151f64", +".cQ c #151f90", +"#qH c #152062", +".cX c #152094", +".f6 c #15218d", +".kc c #152199", +"#Bt c #152257", +".f9 c #152295", +"#qI c #152364", +".dW c #152390", +"#D3 c #152445", +"#rI c #15245b", +"#Gm c #15245d", +"#iY c #152467", +".ka c #15249b", +"#iX c #15266c", +".hz c #15278d", +".gh c #152797", +".iG c #15288e", +".g4 c #15288f", +".i2 c #15289e", +"#qL c #152972", +".ke c #152999", +"#rW c #152a6b", +"#rX c #152a6d", +"#oh c #152a83", +"#um c #152c70", +".aV c #152cba", +"#o# c #152e6e", +"#Qm c #152f6c", +"#kt c #153172", +"#oQ c #15326c", +"#rj c #153564", +"#T4 c #153679", +"#sv c #153774", +".bX c #1537b3", +"#Gi c #153973", +".l9 c #153aac", +"#Jz c #153b44", +"#JA c #153c43", +"#Bm c #153c59", +"#sn c #153e6a", +".iM c #153eb4", +"#YI c #153f4b", +"#Yy c #153f4d", +".nd c #1542b5", +"#Hv c #154390", +"#Hj c #15475e", +".vM c #154a98", +".w8 c #154e95", +".w3 c #154e9b", +".w5 c #154f99", +"#VF c #16171b", +".#d c #16199a", +"#Gp c #161a49", +".#9 c #161bb7", +"#Go c #161c4e", +".ck c #161ca4", +".aq c #161d92", +".cT c #16208f", +".cP c #162091", +".f2 c #162194", +".cV c #162195", +"#mY c #16226a", +".f7 c #162290", +".fe c #162298", +"#qr c #16235a", +"#lM c #16246f", +".js c #16249f", +"#rV c #16255c", +"#pd c #16255e", +".gn c #16259a", +".gw c #162688", +".li c #16269f", +"#rU c #16275d", +".he c #162793", +".jP c #16279d", +"#wy c #162856", +"#HG c #16285a", +"#lP c #162874", +"#kq c #16296e", +"#lQ c #162975", +".ib c #1629a2", +"#xD c #162a67", +"#rY c #162a6f", +"#m1 c #162a71", +"#oi c #162a83", +"#n9 c #162b6a", +".mj c #162ba2", +"#n8 c #162c68", +"#qN c #162c77", +".gS c #162c9c", +"#wA c #162d61", +"#kw c #162e78", +"#m3 c #162f72", +".jF c #162fa6", +"#rk c #163166", +"#ok c #163188", +"#E7 c #163377", +"#wD c #16347d", +".r. c #1634c8", +"#K. c #163689", +"#of c #16368b", +".b3 c #1636c9", +"#IV c #16377c", +"#Xj c #16393b", +".Jd c #16394c", +"#Bo c #163955", +"#rh c #163b67", +"#QS c #163c3f", +"#DR c #164178", +".rb c #1642d6", +".iN c #1643b8", +"#Hi c #16466a", +".uG c #164690", +".vT c #164a93", +".wY c #164b99", +".vL c #164b9b", +".w2 c #164c94", +".vS c #164c96", +".w7 c #164e98", +"#z7 c #164f7c", +".zt c #16509a", +".Ax c #1653a6", +"#NY c #16549d", +".zy c #16559a", +".pN c #1655b6", +".BQ c #1658a6", +".bh c #17179d", +"#BG c #171b41", +".eQ c #171b87", +".#3 c #171bba", +"#pa c #171c56", +"#CQ c #171d41", +".eX c #171d95", +".ap c #171e92", +".bA c #171f8c", +".fT c #171f9b", +"#Gn c #172057", +"#HC c #172059", +"#xz c #17215e", +"#Y5 c #172228", +"#i0 c #172272", +"#mZ c #17236d", +".j. c #172399", +"#RS c #17242a", +"#o3 c #172459", +"#o4 c #17245b", +"#i7 c #17246a", +"#lN c #172570", +"#pe c #17265f", +"#Bv c #172667", +"#kg c #17266b", +".hH c #17268d", +".h4 c #17269b", +"#Bs c #17275a", +"#vh c #172772", +".gx c #172787", +".ez c #1727b8", +".iC c #172890", +".i4 c #17289c", +".iW c #172aa0", +".ic c #172aa3", +"#m0 c #172b72", +".l. c #172b9e", +".jA c #172ca9", +".np c #172d9d", +".lo c #172da7", +".nr c #172ea0", +".gU c #172ea2", +"#LS c #173130", +"#sF c #17316e", +".q9 c #1731c4", +"#oa c #173374", +".aK c #1734b2", +".oS c #1734be", +".iu c #1736aa", +".tv c #1736cc", +"#wB c #173774", +"#ol c #17378c", +"#oe c #173d90", +"#JB c #173e43", +".ec c #173fae", +"#wN c #174080", +"#IL c #174098", +".tw c #1742de", +"#L5 c #17432c", +"#Cx c #174372", +".nc c #1744b9", +".ne c #1745b4", +"#Jy c #17464e", +".uH c #174791", +".nl c #1748b1", +".wZ c #174c98", +".w6 c #174f99", +".yd c #175097", +".zs c #17509d", +".GM c #1755a2", +".zx c #17569d", +".pM c #1756b7", +"#EV c #17606f", +"#Gw c #181327", +"Qt6 c #181baa", +".eS c #181d85", +"#p# c #181e58", +"#bD c #181f4d", +"#vj c #181f56", +".bI c #182196", +"#o8 c #182260", +"#hM c #18226a", +".cO c #182293", +".c0 c #182397", +".cj c #1823b0", +"#zd c #18245e", +"#mX c #18246c", +".h. c #182490", +".h5 c #18249a", +"#rH c #18255a", +"#j# c #18256b", +".dR c #182595", +".fy c #182598", +"#kn c #18266d", +"#lK c #18266f", +"#pb c #18275e", +"#lq c #182760", +"#ki c #18276c", +".j5 c #18279a", +".kJ c #1827a8", +".pO c #182899", +".lg c #1828a1", +".ia c #1828a2", +"#lm c #182957", +"#kp c #18296f", +"#kL c #182985", +".gr c #182993", +".eD c #1829b5", +".dp c #1829bf", +"#wz c #182a58", +".oB c #182a9a", +".iZ c #182aa8", +"#Br c #182b56", +"#tV c #182b63", +".jQ c #182ba3", +"#wj c #182c61", +".jJ c #182c9f", +".id c #182ca7", +".mq c #182ca9", +".a7 c #182cc3", +"#rQ c #182d62", +"#CK c #182d6e", +".hS c #182da2", +"#kJ c #182e7a", +".no c #182e9d", +".mh c #182ea5", +".nu c #182ea6", +"#sE c #182f75", +"#qA c #183070", +"#XY c #18312b", +"#xN c #183167", +"#xE c #18326d", +"#y8 c #18327c", +"#m9 c #183488", +".oR c #1835bf", +".b2 c #1836c8", +"#J9 c #183787", +".kB c #1839ba", +".l3 c #1839bc", +"#Gh c #183c78", +".mb c #183cae", +"#DQ c #183d72", +"#wC c #183d83", +".kX c #183db0", +"#Xi c #183e31", +"#ZM c #183e41", +".c4 c #183fb8", +"#JC c #184145", +".c3 c #1841b7", +".n. c #1842b2", +".nb c #1842b8", +".eb c #1844af", +".iO c #1847bb", +"#JJ c #184a47", +".wX c #184d9b", +".w1 c #184e96", +".yc c #18509a", +".yg c #18529c", +".pA c #1852bd", +".zn c #1853a1", +".zm c #1853a3", +".yk c #18549a", +".yj c #18549c", +".oz c #1856b9", +"#Yd c #185720", +".zz c #18579c", +".AH c #18579e", +".BU c #185aa4", +".BP c #185aa8", +".bd c #1917a8", +"#vc c #191a5d", +"Qt4 c #191ab2", +"#oE c #191b4e", +"Qt0 c #191cc3", +"#ve c #191e62", +".dM c #191e93", +".jn c #191e9c", +".bb c #191eae", +".bc c #191eb0", +".by c #19229b", +"#At c #192354", +"#t2 c #19235e", +".io c #192392", +"#Ao c #192464", +"#qG c #192466", +".cW c #192498", +"#jp c #192579", +".h6 c #19259b", +"#qs c #19265d", +"#jl c #192675", +".h# c #19268c", +".b. c #1926b3", +"#ko c #19276e", +"#lL c #192772", +".hI c #192790", +".lj c #1927a1", +".h3 c #19289d", +".lw c #1929b2", +"#Al c #192a72", +"#ic c #192a7c", +".gq c #192a96", +".jO c #192a9c", +".jI c #192aa0", +".ex c #192aae", +".hq c #192b9b", +".iY c #192ba7", +".nx c #192ba9", +".lv c #192bb3", +"#j9 c #192c66", +"#qM c #192c78", +"#MD c #192c88", +".lt c #192caf", +".kf c #192d9d", +".i3 c #192d9e", +".fR c #192da6", +".iJ c #192daa", +"#px c #192e7d", +".fM c #192eab", +".nK c #192ebb", +".hp c #192f9c", +".jK c #192f9f", +".lp c #192fa9", +".mx c #192fb8", +"#t. c #193074", +"#Bq c #193155", +"#n. c #193187", +".q2 c #1932a6", +"#m4 c #193477", +"#xv c #193567", +".yp c #1935a2", +"#pq c #193682", +".k3 c #1936ac", +"#XZ c #19372b", +"#lW c #193777", +"#m8 c #19388b", +"#Qj c #193a7f", +"#wE c #193a87", +"#xT c #193d8b", +"#sp c #193e72", +".m. c #193eb0", +"#J4 c #19408b", +"#su c #194175", +".xg c #1941a1", +"#L3 c #194433", +"#Cv c #194479", +"#L4 c #19452c", +"#wM c #194a8d", +".vK c #194da0", +".w0 c #194f99", +"#xI c #195089", +".y. c #1950a0", +"#II c #19518a", +".yf c #19529f", +".zu c #19539d", +".tm c #1954a0", +".yl c #19559b", +".yi c #19559d", +".pB c #1956c0", +".AM c #1959a0", +".C2 c #195ba9", +"#VG c #1a1b1f", +"#D5 c #1a1e37", +"##c c #1a1e5d", +"#i# c #1a1e75", +".aj c #1a20a8", +".FJ c #1a2127", +"#vk c #1a214f", +".ih c #1a2193", +".ao c #1a2195", +".h8 c #1a2196", +"QtN c #1a21c9", +"#vl c #1a2250", +".bz c #1a228f", +"#D4 c #1a2340", +"#bC c #1a234a", +".bJ c #1a239a", +".bK c #1a239c", +"#hL c #1a246c", +"#kB c #1a2479", +"#t1 c #1a255d", +".cK c #1a2598", +".cJ c #1a2599", +".cG c #1a259b", +".jp c #1a25a1", +".eA c #1a25b5", +".j# c #1a269c", +".ku c #1a26ae", +"#RR c #1a2730", +"#sX c #1a275e", +".g. c #1a279a", +".iH c #1a27a7", +"#c0 c #1a2865", +"#pc c #1a2960", +"#o5 c #1a2962", +".e6 c #1a2a99", +".gz c #1a2b85", +".iD c #1a2b95", +".h2 c #1a2b9f", +"#kC c #1a2c6a", +"#CL c #1a2c6e", +"#kx c #1a2c78", +".mt c #1a2caa", +".oO c #1a2cbc", +"#rN c #1a2e6b", +"#lR c #1a2e77", +"#jA c #1a2e8d", +".kg c #1a2e9f", +".jG c #1a2ea7", +".mp c #1a2eab", +".lu c #1a2eb5", +"#kI c #1a307b", +".nt c #1a30a8", +"#vE c #1a3174", +".gT c #1a31a1", +"#nF c #1a326e", +".ix c #1a32a0", +"#kN c #1a3387", +".mc c #1a34a3", +"#My c #1a3582", +"#kO c #1a3785", +".oT c #1a37c1", +"#CI c #1a3876", +".p2 c #1a3bc8", +".r# c #1a3ed4", +"#I3 c #1a4065", +"#rc c #1a4071", +"#Oj c #1a4228", +"#xW c #1a4288", +".ra c #1a44d8", +".sc c #1a4691", +".rc c #1a49d7", +"#Hu c #1a4b8e", +".HX c #1a4b98", +".nm c #1a4db6", +".x# c #1a4ea1", +".GN c #1a4f95", +".to c #1a529d", +".yh c #1a549e", +".BN c #1a56ac", +".C9 c #1a5ca6", +".C5 c #1a5ca8", +".CY c #1a60b5", +".D8 c #1a62b4", +".Qr c #1b180f", +"#Gx c #1b182d", +".fZ c #1b1b89", +".eP c #1b1e8f", +".#2 c #1b1fc0", +"#BB c #1b2062", +".dL c #1b2095", +"#c4 c #1b216d", +".jm c #1b219d", +".ai c #1b21ad", +"QtM c #1b21cd", +"#kz c #1b2374", +".bw c #1b23a0", +"#c2 c #1b245f", +"#nY c #1b2465", +"#nX c #1b2467", +"#0h c #1b2526", +"#ec c #1b2562", +"#kc c #1b257a", +"#jo c #1b2678", +".e0 c #1b269c", +".kK c #1b26a6", +".eE c #1b26b4", +".eB c #1b26b6", +"#zc c #1b2763", +"#iZ c #1b276f", +".ll c #1b27a1", +"#qq c #1b285d", +"#qu c #1b285f", +"#i6 c #1b286e", +".dT c #1b2898", +".ja c #1b289a", +".j6 c #1b289b", +"#Ui c #1b2934", +"#Vr c #1b2936", +".q3 c #1b2aa7", +"#xC c #1b2b69", +".e8 c #1b2b9a", +".a9 c #1b2bbc", +".jM c #1b2c96", +".ip c #1b2c98", +".l# c #1b2ca2", +".dr c #1b2cc0", +"#jk c #1b2d79", +".jN c #1b2d99", +".ny c #1b2dad", +"#0t c #1b2e28", +".hB c #1b2e8d", +".kk c #1b2ea6", +".ls c #1b2eb1", +".oP c #1b2ebb", +"#tU c #1b3069", +"#lY c #1b3081", +".gW c #1b30ad", +"#un c #1b317a", +"#n# c #1b3187", +".my c #1b31ba", +".g3 c #1b3298", +".ir c #1b329c", +".mg c #1b32a6", +"#jB c #1b338d", +".nD c #1b33b7", +"#tI c #1b346c", +".pU c #1b34b3", +".oW c #1b35c0", +"#X0 c #1b362d", +"#T5 c #1b3781", +"#ob c #1b387a", +".jE c #1b38b0", +"#R4 c #1b3a32", +".lM c #1b3bb2", +".ma c #1b3fb1", +"#xK c #1b4170", +"#xV c #1b428d", +"#sq c #1b4374", +"#IG c #1b4a76", +".nk c #1b4ab4", +"#L0 c #1b4b3d", +"#Hs c #1b517f", +"#uc c #1b5585", +"#Kg c #1b568e", +".pz c #1b56be", +"#vw c #1b5c9c", +".Az c #1b5dab", +".CX c #1b61b6", +".D9 c #1b62b4", +"#vd c #1c1c62", +".#r c #1c1e8b", +".eT c #1c208b", +".eV c #1c208e", +".ac c #1c20b5", +".bt c #1c23a7", +".ak c #1c23a8", +"#jn c #1c2477", +".#P c #1c25a8", +"#ib c #1c267b", +".cN c #1c2697", +".kd c #1c269f", +"#t0 c #1c275f", +".jf c #1c279b", +".aE c #1c27a5", +"#oZ c #1c285a", +".ff c #1c289e", +"#S6 c #1c2932", +"#qt c #1c2960", +".d7 c #1c2992", +".dS c #1c2999", +".jc c #1c299b", +".je c #1c299c", +"#wp c #1c2a67", +"#o6 c #1c2a6b", +"#je c #1c2a73", +".fj c #1c2a93", +".fE c #1c2aa4", +"#1z c #1c2b28", +"#pf c #1c2b66", +"#yL c #1c2b70", +".hG c #1c2b92", +".ga c #1c2b9e", +".gm c #1c2ba2", +"#wo c #1c2c68", +".e9 c #1c2c9b", +".le c #1c2c9d", +".e4 c #1c2d99", +"#lp c #1c2e60", +"#jf c #1c2e76", +".kI c #1c2eae", +".ki c #1c2fa5", +".nw c #1c2fa8", +"#kD c #1c306d", +"#na c #1c3087", +".kl c #1c30a9", +"#pz c #1c3182", +".gX c #1c31b0", +".pY c #1c31c8", +".oJ c #1c32ac", +".is c #1c339d", +".mf c #1c33a5", +"#nb c #1c348a", +".nE c #1c34b8", +".pV c #1c34bc", +"#Lk c #1c3578", +"#fQ c #1c3790", +".#G c #1c37c2", +"#xO c #1c3877", +"#Bp c #1c3957", +"#lV c #1c3a7a", +"#EK c #1c3b69", +"#Qi c #1c3c8f", +".xa c #1c3da4", +".p3 c #1c3dca", +"#rg c #1c3e6e", +".yn c #1c3e95", +"#xF c #1c3f77", +"#SN c #1c42ad", +"#xX c #1c4388", +"#Hy c #1c448a", +".xh c #1c44a6", +"#L6 c #1c4537", +"#Jx c #1c4547", +".nf c #1c4bb7", +".7M c #1c4cbb", +".HW c #1c4ea5", +"#NU c #1c50a3", +"#wL c #1c5197", +".om c #1c51b9", +"#LZ c #1c523a", +".x9 c #1c53a3", +".uw c #1c53a6", +".rf c #1c55d8", +".tn c #1c56a0", +".zw c #1c58a0", +".zv c #1c58a1", +".AC c #1c59a9", +".AA c #1c59aa", +".AD c #1c5aa7", +".AL c #1c5ba2", +".oA c #1c5cbe", +".AN c #1c5da1", +".BY c #1c5fa5", +".BX c #1c5fa6", +".cn c #1d179b", +".bi c #1d1da3", +".a# c #1d1db3", +"QtY c #1d1ec6", +".eO c #1d2095", +"#D1 c #1d215e", +"#i. c #1d2377", +"#ia c #1d2379", +"#nO c #1d245b", +".an c #1d2496", +".am c #1d24a6", +"#D0 c #1d2563", +"#jm c #1d2576", +".du c #1d25b8", +"QtQ c #1d25c5", +"QtO c #1d25c8", +"#N7 c #1d262b", +"#Ob c #1d262d", +"#wr c #1d2667", +".gL c #1d269d", +".kt c #1d26af", +".mB c #1d26b3", +"#o0 c #1d2758", +"#hO c #1d276e", +".cY c #1d289c", +"#RP c #1d2935", +"#nQ c #1d295d", +"#mW c #1d2971", +"#lD c #1d2973", +".ln c #1d29a3", +"#nR c #1d2a5f", +".lX c #1d2aaa", +".gJ c #1d2aac", +"#mN c #1d2b74", +".hJ c #1d2b96", +".gl c #1d2ba5", +"#i2 c #1d2c67", +"#kl c #1d2c6f", +"#kK c #1d2c8b", +".ch c #1d2cbd", +"#ek c #1d2d7b", +".iB c #1d2d8f", +".hx c #1d2d9c", +".fQ c #1d2da7", +"#HA c #1d2e76", +".fl c #1d2e8a", +".gd c #1d2ea0", +".iR c #1d2ea2", +"#XX c #1d2f2f", +"#qF c #1d2f6f", +"#id c #1d2f81", +".iX c #1d30a8", +".i1 c #1d30a9", +"#vm c #1d3163", +"#x1 c #1d316e", +"#z2 c #1d3170", +"#jg c #1d3178", +"#rP c #1d3267", +"#lX c #1d3283", +".oF c #1d32a9", +".oK c #1d32b1", +"#nG c #1d336d", +".ho c #1d33a0", +".nq c #1d33a3", +".kP c #1d33ab", +"#lS c #1d347a", +".nH c #1d34b8", +"#y9 c #1d357d", +".eq c #1d35af", +".jB c #1d35b1", +"#oR c #1d3770", +".jD c #1d37b2", +".oV c #1d37c2", +"#y7 c #1d3885", +".oU c #1d38c3", +"#Qk c #1d3c75", +"#oc c #1d3c7f", +"#Dv c #1d3d63", +".p1 c #1d3ecb", +".j0 c #1d40b6", +"#pp c #1d418b", +".j1 c #1d42b7", +".ng c #1d43b0", +"#xU c #1d4491", +".di c #1d44c3", +"#Cy c #1d4674", +"#yR c #1d467a", +".b4 c #1d46c2", +"#Bh c #1d487b", +".XC c #1d4bba", +"#F5 c #1d4c66", +"#xJ c #1d4c82", +"#z6 c #1d4d7e", +".wW c #1d52a2", +".AB c #1d5aaa", +".BM c #1d5bb0", +"#yU c #1d5c88", +".BO c #1d5eae", +".BW c #1d5fa9", +".CZ c #1d5fb3", +".BL c #1d5fb5", +".BZ c #1d60a6", +".E. c #1d61b2", +".BK c #1d63b8", +".cr c #1e1c97", +".cs c #1e1d94", +".a. c #1e1eb4", +".il c #1e1f93", +"Qt8 c #1e21ac", +"#HH c #1e2252", +".eU c #1e228e", +".ad c #1e22b7", +".i# c #1e2399", +".jo c #1e23a1", +".cB c #1e2496", +"#S1 c #1e2535", +"#c1 c #1e256b", +"#fx c #1e2677", +"#wq c #1e2768", +".h7 c #1e279c", +".g9 c #1e27a0", +"#tZ c #1e295f", +"#lt c #1e2979", +".cZ c #1e299d", +".b# c #1e29b6", +"#nP c #1e2a5c", +"#k# c #1e2a72", +".ci c #1e2aba", +"#nS c #1e2b62", +"#lO c #1e2b79", +".jb c #1e2b9d", +".fg c #1e2b9e", +"#ll c #1e2c5d", +"#rm c #1e2c6b", +"#n7 c #1e2c6d", +"#mJ c #1e2c73", +".en c #1e2c97", +".jr c #1e2ca7", +"#nT c #1e2d66", +"#oS c #1e2d68", +".hF c #1e2d92", +".hh c #1e2da0", +".fD c #1e2da2", +"#0r c #1e2e23", +"#ej c #1e2e7b", +".iA c #1e2e8d", +".hw c #1e2e9f", +".jH c #1e2ea7", +".mA c #1e2eb9", +".dq c #1e2ec2", +"#ze c #1e2f67", +".gy c #1e2f8b", +".hf c #1e2f9b", +".a8 c #1e2fc3", +"#y2 c #1e3070", +"#jq c #1e307c", +"#c9 c #1e3082", +".hA c #1e3092", +"#jy c #1e3096", +"#lk c #1e3169", +".iF c #1e3198", +".kj c #1e31a9", +"#kM c #1e328b", +".hX c #1e32ad", +"#0l c #1e332e", +".iq c #1e339e", +".oI c #1e33b0", +".pZ c #1e33ca", +".gV c #1e34ac", +"#wi c #1e3567", +".k5 c #1e38a7", +".df c #1e3ab7", +"#0o c #1e3b25", +"#m5 c #1e3b7d", +".jX c #1e3cb4", +"#rf c #1e3e71", +"#p0 c #1e3f75", +".ed c #1e3fb0", +".dj c #1e41c3", +".sl c #1e41d9", +"#rd c #1e4272", +"#wc c #1e4482", +"#JD c #1e4749", +"#ty c #1e486e", +"#tz c #1e487a", +"#wF c #1e4894", +".nj c #1e48b4", +"#tx c #1e4a71", +"#Kc c #1e4a89", +"#DS c #1e4c87", +"#xH c #1e5083", +".ol c #1e53b9", +".on c #1e53bd", +".AJ c #1e58a2", +".or c #1e58b9", +".AK c #1e5aa3", +"#yV c #1e5c85", +".pC c #1e5cc3", +"#vv c #1e5fa3", +".C4 c #1e60ae", +".B0 c #1e61a7", +".Ed c #1e62ad", +".D7 c #1e64b9", +".CW c #1e64ba", +"#SV c #1f1d28", +".91 c #1f1e57", +"Qta c #1f2073", +".aa c #1f20b6", +".kr c #1f21a8", +".cl c #1f22a7", +".kq c #1f23a8", +".ah c #1f24b3", +".h9 c #1f269b", +"#Ua c #1f2732", +"#nZ c #1f2766", +"#jb c #1f2772", +"#xA c #1f277a", +".bx c #1f27a3", +"#lr c #1f2869", +"#t8 c #1f295e", +"#nW c #1f296e", +"#lE c #1f2971", +"#lu c #1f2a7c", +".d3 c #1f2a9e", +".kN c #1f2aa6", +"#o1 c #1f2b5d", +".fF c #1f2ba5", +".tu c #1f2bcf", +"#mV c #1f2c72", +".fh c #1f2c9c", +".jd c #1f2c9e", +".fC c #1f2c9f", +"#n6 c #1f2d6e", +"#Mz c #1f2e71", +".iI c #1f2ead", +"#Z# c #1f2f2e", +".hv c #1f2fa8", +"#sM c #1f3068", +".h1 c #1f30a4", +"#lZ c #1f3183", +".gg c #1f31a1", +".ms c #1f31af", +".lr c #1f32b3", +".mz c #1f32bc", +"#0v c #1f332a", +"#kH c #1f337c", +".kh c #1f33a6", +".mr c #1f33b0", +"#rO c #1f3469", +".k9 c #1f34a7", +".lq c #1f34b3", +".jT c #1f35a5", +"#1B c #1f3729", +"#pk c #1f3773", +"#pj c #1f3870", +"#pl c #1f3878", +".k6 c #1f39a8", +"#wh c #1f3a6f", +"#pm c #1f3a7d", +"#RB c #1f3d63", +"#od c #1f3d83", +".lN c #1f3db5", +"#yQ c #1f3e77", +"#Cl c #1f3f6e", +"#K# c #1f4198", +".m# c #1f43b5", +"#UR c #1f4433", +"#kQ c #1f4488", +"Qts c #1f46cf", +"#xq c #1f487c", +".ni c #1f48b4", +"#sr c #1f4a77", +"#xG c #1f4a7f", +"#Iw c #1f4f77", +"#OZ c #1f539f", +".vJ c #1f53a7", +".I8 c #1f56b0", +".os c #1f5ab8", +".py c #1f5ac0", +".AG c #1f5ea5", +".pL c #1f5ebf", +".BV c #1f61ab", +".C3 c #1f61af", +".B1 c #1f62a8", +".D. c #1f62a9", +".Eb c #1f62b0", +".Ee c #1f63ae", +".Fq c #1f65ad", +".BJ c #1f65bb", +".Fj c #1f68b5", +".cq c #201e9d", +"QtX c #201ec7", +"#pP c #202054", +"#t3 c #202060", +"QtE c #2023ae", +".cg c #2023b2", +"#ls c #20246b", +".aB c #20259d", +".eF c #2025b4", +"#t7 c #20275e", +".g7 c #202799", +"QtP c #2028c8", +"#bB c #202952", +"#fu c #202974", +"#fv c #202976", +".kL c #2029aa", +"#XW c #202b31", +"#tY c #202b61", +".jg c #202b9f", +"#o2 c #202c5e", +"#y3 c #202c74", +"#u7 c #202c80", +".e2 c #202ca2", +".km c #202d9f", +".g# c #202da0", +".#W c #202db9", +"#Uj c #202e37", +"#aq c #202e6f", +".g2 c #202e99", +".jq c #202ea9", +".ml c #202eab", +"#Uf c #202f34", +"#lx c #202f84", +".gv c #202f94", +"#HF c #203061", +"#i1 c #203064", +"#oT c #203167", +"#Lo c #203181", +".ew c #2031b3", +"#jz c #203296", +".gB c #2032a0", +".i0 c #2032ae", +".fo c #203382", +".jR c #2033a9", +".pR c #2033ab", +"#x2 c #203471", +"#kE c #203473", +"#jw c #20348d", +".hY c #2034ad", +".m8 c #2034b1", +"#y0 c #203564", +"#py c #203586", +".bO c #2035b5", +".aM c #2035c6", +"#t# c #20367f", +".kQ c #2036b0", +".pX c #2036ca", +"#oW c #203761", +"#jh c #20377d", +".pT c #203ab5", +"#lU c #203b7e", +".kH c #203bbe", +".aQ c #203bd4", +"#re c #203d75", +".k4 c #203db3", +".l2 c #203ec2", +".tx c #2041e6", +"#QO c #204345", +".jZ c #2043b9", +".B4 c #2043c3", +"#KT c #20443a", +"#v5 c #20466a", +".nh c #2046b3", +"#wb c #204886", +"#KN c #20494b", +"#Hw c #20499b", +"#B. c #204a72", +"#L1 c #204b42", +"#st c #204c7b", +"#v8 c #204e7f", +"#DV c #204f93", +"#In c #205066", +"#Bi c #205080", +"#yS c #205283", +".XI c #2054ba", +".q0 c #2058b9", +".AI c #2059a6", +".zl c #205bab", +".oy c #205bbf", +".zo c #205ca5", +".C1 c #205cb2", +".uI c #205cd4", +".AE c #205ea9", +".C0 c #205eb3", +"#vu c #2060a7", +".E# c #2061b3", +".C6 c #2062ae", +".D# c #2063a9", +".Eh c #2064ad", +".Fi c #2069b8", +"#2M c #20783c", +".ct c #212095", +".N0 c #21221d", +"#Qs c #212237", +".dF c #21228e", +".ab c #2122b8", +"#Gt c #21234c", +"#bE c #212354", +".fU c #212392", +".#E c #2123aa", +"##b c #21265e", +".jj c #21269b", +".i. c #21269c", +".cE c #21289a", +".mC c #2128b6", +"QtK c #2128be", +"#ql c #212a61", +"#ed c #212a6b", +"#eb c #212a6f", +".dQ c #212b9e", +"#Y4 c #212c30", +"#tX c #212c62", +"#ky c #212c7c", +".e1 c #212ca2", +"#RQ c #212d39", +"#Ae c #212d5f", +"#jd c #212d77", +".e3 c #212da3", +".#V c #212dbd", +"#XQ c #212e37", +"#cY c #212e5b", +"#rG c #212e65", +".fL c #212eb1", +"#Ud c #212f2f", +"#zb c #212f70", +"#mK c #212f78", +".mk c #212fac", +"#nU c #21306b", +".gu c #213097", +".gP c #2130b1", +"#y4 c #21317c", +".hg c #2131a2", +".kO c #2131ab", +".H4 c #213239", +"#da c #21328c", +"#ie c #21328e", +".iE c #21329c", +".nL c #2132be", +"#v0 c #213349", +".hV c #2134b4", +".oQ c #2134bf", +".oN c #2134c1", +"#jv c #21358e", +".oD c #2135a6", +".iP c #2135a8", +".oL c #2135ba", +"#nL c #213661", +"#qO c #213685", +".sf c #2136c3", +".pW c #2137c8", +"#Zc c #21383e", +"#pi c #21386e", +"#wR c #21387b", +"#tb c #213884", +".nG c #2138bc", +"#nc c #21398f", +".jC c #2139b5", +".nF c #2139bd", +"#lT c #213a7d", +".b0 c #213ac8", +"#Lp c #213b92", +".md c #213baa", +".de c #213bb6", +".bY c #213ec0", +".jY c #2141b8", +"#Zp c #214227", +"#kP c #21438b", +"#Bg c #21467d", +".XA c #2146ae", +"#ZF c #214738", +"#Ge c #21476c", +"#IM c #21479c", +".lJ c #2148bd", +"#v6 c #214b73", +"#v7 c #214c79", +"#tA c #214d7c", +".ot c #214db6", +".XB c #214ec1", +".x. c #2150a0", +"Qtr c #2151d9", +"#Bl c #21527d", +"#QY c #215443", +"#Ht c #21548b", +".Wt c #2156b4", +"#Ii c #215761", +".oq c #2158bd", +"#yT c #215b89", +".r6 c #215db5", +"#vt c #215faa", +".Ay c #2160b0", +".AO c #2162a6", +".BT c #2163af", +".BR c #2163b1", +".Da c #2164a8", +".Ei c #2165ac", +".Fk c #2166b4", +"#OT c #216896", +".GA c #2169b3", +"QtU c #221fc8", +".eG c #222198", +"#Gy c #22223c", +"#nu c #222254", +".dE c #222292", +".dG c #22238f", +"Qtg c #222576", +".af c #2227b9", +".ji c #222898", +".cC c #22289a", +"#N9 c #222a35", +"#Ap c #222a69", +"#kA c #222a7d", +".kM c #222aa9", +"QtI c #222aaf", +"#Y6 c #222c36", +"#mH c #222c71", +"#i3 c #222d7d", +".ly c #222dba", +"#CP c #222e56", +"#tW c #222e62", +"#hP c #222e68", +"#mO c #222e76", +"#mI c #222f73", +"#ja c #222f75", +".lx c #222fb9", +"#Uh c #22303b", +"#n5 c #22306f", +"#lJ c #223077", +"#mM c #223079", +".gt c #223099", +".fi c #22309d", +"#pg c #22316c", +"#nM c #223361", +"#jr c #223381", +"#l1 c #223385", +"#if c #22338f", +".ge c #2233a5", +".hL c #2233a9", +".a2 c #2233b5", +"#ln c #223462", +"#mC c #223464", +"#l0 c #223486", +".lf c #22349a", +".eo c #2234a2", +"#0u c #22352f", +"#zf c #22356f", +"#aN c #223594", +".pS c #2235b5", +"#zZ c #223668", +"#NQ c #223673", +"#kG c #22367d", +".hZ c #2236a9", +"#lj c #223770", +"#x3 c #223776", +".jS c #2237aa", +"#uo c #223881", +"#pA c #22388b", +".dd c #2238b2", +"#ph c #22396d", +"#z. c #22397d", +"#r3 c #223989", +".me c #2239a9", +".j2 c #2239ab", +"#SS c #223a6a", +"#qB c #223b7d", +"#c# c #223cab", +".fs c #223cad", +"#m6 c #223f81", +"#pn c #223f83", +"#m7 c #224182", +".b8 c #2244cc", +".lL c #2245bb", +"#0F c #22462a", +"#S# c #22474d", +"#xu c #22477c", +"Qtq c #2248cf", +"#.c c #2249b0", +".B5 c #224dcd", +".b6 c #224dd0", +"#ss c #224e7b", +".sb c #22509d", +"#xk c #22517f", +"#F2 c #225268", +"#Q# c #225294", +".XD c #2253ba", +".wV c #2257a7", +".zr c #225ea4", +".Fl c #2261b0", +".C8 c #2264ae", +".Ej c #2266ad", +".Em c #2267aa", +".Fn c #2267b2", +".Fc c #2268ca", +".Fh c #2269b9", +"#Je c #23203b", +".cp c #2320a1", +".cm c #2321a6", +"#nt c #232556", +"#t4 c #232562", +".#O c #2325ac", +"#gi c #232659", +".jl c #2328a0", +".dN c #232a9e", +".#u c #232b98", +"#qk c #232c65", +"#mQ c #232c71", +"#gJ c #232c77", +".cF c #232da6", +"#sW c #232e66", +"#MB c #232e70", +".#D c #232ebc", +"#nN c #232f63", +".hN c #232fa5", +".lm c #232fa9", +"#Ug c #23313a", +"#Ue c #233235", +"#km c #233275", +".mm c #2332a9", +"#X1 c #233333", +"#lA c #233380", +"#db c #233392", +"#Vx c #23343e", +".h0 c #2334a8", +"#sK c #233670", +"#kF c #23367a", +"#yM c #233682", +"#g0 c #23378d", +"#ju c #23378e", +".gR c #2337aa", +".nJ c #2337bc", +".p0 c #2338cf", +".oH c #2339b3", +"#rZ c #233a80", +"#fP c #233b95", +"#fU c #233b9b", +"#g1 c #233c90", +".bZ c #233dc6", +".kG c #233ec1", +".p7 c #233fce", +"#kv c #234086", +".jW c #2340b8", +"#vn c #23417d", +".l1 c #2342c1", +"#DL c #234374", +".fq c #2344ad", +"#u0 c #234781", +"#Sc c #234841", +"#vo c #23498a", +"#xr c #234b7c", +"#J0 c #234d89", +"#ER c #235462", +"#TZ c #23548f", +"#Bk c #235681", +"#Bj c #235683", +".x7 c #2356a9", +".x8 c #2357aa", +".vI c #2357ab", +"#Yc c #23582a", +".uv c #2359af", +".oo c #2359c5", +".AS c #2359d7", +".zk c #235cad", +"#0U c #235f3b", +".r7 c #235fb5", +".Ea c #2360b3", +".BI c #2366bd", +".El c #2368ab", +".Ek c #2368ad", +".Fp c #2368b3", +".Fm c #2368b5", +".Ft c #2369af", +".GC c #236bb3", +".Gu c #236fba", +".f0 c #24238b", +".dD c #242398", +".dJ c #242496", +".cx c #242599", +".fV c #242697", +".ks c #2426af", +".#s c #242798", +".cA c #24279a", +".dK c #24279c", +"#t5 c #242865", +"#CN c #242867", +"#t6 c #242963", +"#n0 c #242a68", +"QtL c #242ac6", +".al c #242baf", +".bN c #242ca9", +"#N8 c #242d34", +"#fw c #242d7c", +".lz c #242dba", +"#hW c #242e75", +".gK c #242ea9", +"#o7 c #242f6f", +"#mG c #242f71", +"#t9 c #243062", +"#lv c #243084", +".fG c #2430aa", +"#LM c #243141", +"#qp c #243166", +"#rF c #243168", +"#VB c #243235", +"#n4 c #243271", +"#CM c #243273", +"#lC c #24327d", +"#jx c #24329b", +".lb c #2432ad", +".gI c #2432b7", +"#rn c #243374", +"#ig c #243493", +".pP c #2435a7", +"#i5 c #24365e", +"#js c #243688", +".gA c #2436a2", +".hl c #2436a4", +"#oX c #243762", +"#jj c #243783", +".oE c #2437ad", +"#j8 c #243877", +"#g4 c #24389b", +".oG c #2438b1", +".hW c #2438b5", +"#oU c #243a6b", +"#mw c #243a74", +"#pB c #243a8d", +"#fT c #243b9b", +".of c #243baf", +"#z3 c #243c7a", +".aL c #243cc4", +"##N c #243dbc", +"#eI c #243e9d", +".oe c #243eaf", +"#Dz c #244169", +"#p6 c #24416b", +".dn c #2441c1", +"#ku c #244282", +"#Bc c #244379", +"#Pw c #244530", +"#0x c #24453a", +"#UQ c #244647", +"#Cz c #244674", +"#2d c #244741", +"#ZN c #244c54", +"#z5 c #244c80", +"#Xh c #244d2f", +".dh c #244dc9", +".7L c #244eb2", +"#TL c #245073", +".I9 c #2459a7", +".op c #245ac4", +".rg c #245bdc", +"#TV c #245c8b", +".AF c #2462ab", +".GL c #2462b5", +".pD c #2464c6", +".D4 c #2466ba", +".Fu c #246ab0", +".GD c #246db2", +".Go c #246dcc", +".dB c #251789", +"Qtb c #25217f", +"QtW c #2523cc", +".eH c #25249b", +".dx c #2524a6", +".dI c #252595", +".dH c #252692", +".cy c #25269a", +"#hJ c #252968", +".jk c #252aa0", +".mD c #252ab9", +".cD c #252b9d", +"#WB c #252c3c", +".g6 c #252d9c", +"#WX c #252e2d", +"#gw c #252e71", +"#jc c #252e79", +".gM c #252ea3", +"#Ub c #252f38", +"#1I c #252f39", +"#gH c #252f76", +".fz c #252f9e", +".g5 c #25309a", +".hO c #2530a4", +".kn c #2530a6", +"#S5 c #25313d", +"#lw c #253185", +".#U c #2531c3", +"#S4 c #25323b", +"#qn c #253266", +"#mU c #253276", +"#oY c #253362", +"#xB c #253372", +"#gZ c #25338b", +"#kb c #25346f", +".e# c #253491", +".e. c #253493", +".ld c #2534ab", +"#nI c #253569", +"#RV c #25362c", +"#WL c #25363e", +"#Vw c #253640", +"#By c #25367c", +"#l2 c #253688", +"#ca c #2536b8", +".Jc c #25374d", +".fn c #253789", +".hj c #2537a5", +"#im c #2537a7", +".aF c #2537b5", +"#u6 c #25387d", +"#ih c #253897", +"#g5 c #25399c", +".ep c #2539aa", +"#mx c #253a73", +".dc c #253ab1", +".er c #253ab7", +".kR c #253ab9", +"#ta c #253b86", +"#oq c #253b90", +"#g6 c #253ba0", +"#oV c #253c68", +".bQ c #253cbe", +"#ot c #253e92", +".xe c #253ea2", +"##z c #253ea5", +".b1 c #253fd0", +".p6 c #2541d0", +"#po c #254288", +"#EJ c #25456c", +"#Cm c #25476d", +"#R5 c #25493b", +"#IN c #254a98", +"#L8 c #254b3c", +"#kR c #254c8d", +".xf c #254cab", +"#1W c #254d32", +"#zP c #254e7a", +"#xp c #254e86", +"#yC c #254f7f", +"#Vg c #255087", +"#yX c #255174", +"#zV c #25517e", +".rd c #2553dd", +"#tB c #255583", +"#ub c #25578a", +".ri c #2557d0", +"#0S c #255a2e", +"#No c #255c3f", +".qZ c #255fc0", +"#Kh c #256098", +".Fg c #2569ba", +".D6 c #2569be", +".Fo c #256ab5", +".Fv c #256bb0", +".Fz c #256cae", +".Gs c #256cba", +".Gz c #256db7", +".GF c #256eb3", +".Gt c #256ebb", +".Gq c #256ebd", +".Gv c #256fba", +".Gn c #2579d1", +"#LE c #261e35", +"#as c #262060", +".cu c #26259c", +".bj c #2625af", +".Pc c #26281d", +"#dY c #262960", +"Qt# c #262976", +".cz c #26299c", +".fO c #2629aa", +".ae c #262abf", +"#mE c #262b6b", +".fP c #262bab", +"#qm c #262d64", +"#XV c #262e3b", +"#h9 c #262e81", +".bv c #262ead", +".#C c #262ebd", +"#RZ c #262f2a", +"#Oc c #262f34", +"#Za c #262f3e", +".fK c #2630b3", +"#MA c #263173", +".c1 c #2631a7", +"#sN c #263266", +"#hQ c #26326e", +"#mP c #26327a", +"#aT c #2632a0", +".a1 c #2632b8", +"#S7 c #263339", +"#rE c #263368", +"#nH c #26336a", +"#0q c #263425", +"#n3 c #263473", +"#ly c #26348c", +".lc c #2634ae", +"#kf c #26357a", +"#el c #263586", +"#em c #263588", +".mw c #2635b4", +"#Bw c #26377c", +".pQ c #2637ad", +".nz c #2637bb", +"#jt c #26388c", +".oM c #2639c4", +".sh c #2639dd", +"#g3 c #263a9b", +"#lo c #263b68", +"#qE c #263b7a", +"#yP c #263c78", +"#qP c #263c8f", +"#fS c #263d9b", +"#eH c #263e9e", +".lQ c #263eb8", +"#jC c #264095", +".lO c #2640b9", +"#ni c #264192", +"#p5 c #26436d", +".kF c #2643c5", +".kE c #2644c6", +".dk c #2644c8", +"#Zx c #26472a", +"#S. c #264852", +"#KO c #264a48", +"#wf c #264c7d", +"#tF c #264c8d", +"#wd c #264d86", +"#Hx c #264d9c", +"#Vh c #264e89", +"#xt c #26537a", +"#JM c #265782", +"#EL c #265871", +".XE c #2658bb", +"#Lt c #265ba7", +".Av c #265bb7", +".nn c #265bc3", +".B6 c #265bcd", +"#yW c #265d84", +"#MI c #265daf", +".rh c #265ddb", +".Kj c #265fa6", +"#0T c #266037", +".r5 c #2661bb", +"#Zs c #26622f", +".zq c #2662aa", +".pK c #2666c7", +".C7 c #2668b2", +".CV c #2668bf", +".Fw c #266cb1", +".Fr c #266cb4", +".Fy c #266daf", +".Gw c #266eb8", +".GG c #266fb3", +".HG c #2673bb", +".92 c #271a52", +"#Jd c #272332", +".bm c #2728a6", +".#A c #272ab7", +"#VI c #272d2d", +"#BA c #272e72", +"#bP c #272e74", +".ba c #272ebc", +"#Y. c #272f0a", +"#mD c #272f6d", +"#1x c #27302d", +"#1y c #273130", +"#hV c #273176", +".gN c #2731aa", +"#VC c #273236", +".cI c #2732a6", +".cb c #2733c3", +"#S3 c #27343a", +"#Bz c #27347a", +".d8 c #27349a", +"#qc c #273574", +"#mL c #27357e", +"#bO c #273580", +".hK c #2735a0", +"#fO c #273695", +".fx c #2736ad", +".ce c #2736c3", +"#lB c #273784", +"#aQ c #273797", +"#sL c #273870", +".gE c #2738ae", +"#ii c #27399b", +".hk c #2739a7", +"#WI c #273a41", +"#ij c #273b9e", +"#NO c #273c7f", +"#om c #273c8f", +"#E2 c #273d6e", +"#r0 c #273d88", +"#op c #273d90", +"#r1 c #273e8a", +".bP c #273ebe", +".kS c #273ec0", +".lP c #273fb9", +".bR c #2740c1", +"#y6 c #27418e", +"#eJ c #2741a0", +".p4 c #2746d4", +".B3 c #2747c0", +"#M5 c #274a44", +".c5 c #274ac2", +".Xv c #274bab", +".lK c #274cc1", +"#A8 c #274f72", +"#2c c #27513b", +"#XK c #27518d", +"#A9 c #275287", +"#YJ c #27556c", +"#Yx c #275636", +".1h c #2757bb", +"#Rv c #2758d8", +"#QW c #275a4b", +".1g c #275ac7", +"#yF c #275d81", +".1d c #275dca", +"#MJ c #275eae", +".43 c #275eb8", +".px c #275ec5", +"#vs c #275fac", +".tl c #2761b3", +".tk c #2761b5", +".AV c #2762c8", +".zp c #2763ab", +".Ff c #2769bd", +".IK c #276bbe", +".Fx c #276db2", +".GH c #2770b4", +".HH c #2774ba", +"Qtf c #281d83", +".aX c #2821ab", +".dy c #2823a3", +".#R c #2825aa", +".N1 c #28272c", +"QtD c #2828ae", +".ik c #28299d", +".bl c #2829a7", +"#LD c #282a36", +".cf c #282dbc", +".jh c #282e9e", +".dP c #282fa3", +".lT c #282fb3", +"QtJ c #282fbd", +"#ee c #283078", +"#fn c #283174", +".aW c #2831be", +"#gx c #283279", +"#gI c #28327a", +".fI c #2833af", +".fN c #2833b1", +".m4 c #2833b3", +"#Ph c #28353b", +"#qo c #283569", +"#rD c #28356a", +"#n2 c #283673", +".mu c #2837b6", +"#dc c #28389a", +"#WM c #283943", +"#rp c #28397e", +"#Ak c #283a84", +"#d. c #283a8e", +"#g2 c #283a9c", +".gY c #283aa6", +".nC c #283ab6", +".nB c #283ab8", +"#ik c #283ba1", +"#il c #283ba2", +"#Zd c #283c45", +".c. c #283cbf", +".nI c #283cc1", +"#sJ c #283d76", +"#oo c #283d90", +".GT c #283e49", +"#g7 c #283ea4", +"#eG c #2840a0", +"##y c #2840aa", +"#du c #2841a8", +".kW c #2841bf", +".jU c #2842bb", +"#0n c #284332", +"#u# c #28457f", +"#aC c #284595", +".dm c #2845c7", +".c6 c #2846be", +".l0 c #2846c2", +"#R7 c #284741", +"#CA c #284776", +"#v2 c #284861", +"#vG c #28496c", +".kC c #2849ca", +"#RA c #284a70", +"##o c #284aa4", +"#u1 c #284b81", +"#Rw c #284bb3", +".oj c #284bbf", +"#vp c #284c96", +".bW c #284cc6", +"#KV c #284e35", +"#uZ c #284e8d", +"#Kb c #285095", +"#Lg c #285096", +".ok c #2850c2", +"#xs c #28517d", +"#Lf c #285193", +"#UU c #28523e", +"#NT c #2852a6", +"#yD c #28537e", +"#DC c #285397", +"#W9 c #28564b", +"#v9 c #285688", +"#wG c #2857a5", +"#O0 c #2857a9", +".ea c #2857bf", +"#DT c #285896", +"#Ru c #2858d6", +"#Ih c #28595d", +"#Hf c #285968", +".3M c #2859c2", +".De c #285acd", +".3Q c #285bc4", +".5p c #2860c1", +".r4 c #2863bf", +"#Y3 c #2867c8", +"#NI c #2868d2", +".BH c #286ac1", +".Ec c #286bb9", +".Gr c #286bba", +".Fe c #286fc1", +".GB c #2870b8", +".GI c #2871b5", +".GE c #2871b6", +".GK c #2872b1", +".HF c #2872bb", +".qT c #2879d2", +".fY c #29289d", +"#oF c #29295b", +"#WV c #292a2e", +".g1 c #292b9a", +".#Q c #292cb1", +"#Us c #292d2e", +".lU c #292db2", +"QtF c #292db5", +".ag c #292ebe", +"#As c #292f61", +".bs c #2930b5", +"#O. c #29313e", +"#Vo c #29323b", +"#Pg c #293241", +"#HO c #293251", +".g8 c #2932a9", +".m5 c #2932b3", +".lW c #2932b5", +"#ef c #293371", +"#mF c #293476", +"#HE c #293567", +"#sO c #293569", +"#i4 c #29357d", +"#kd c #29357f", +".q8 c #2935bf", +"#RO c #29363f", +"#nV c #29367c", +"#0p c #293726", +"#RT c #29373a", +"#Zb c #293742", +"#n1 c #293774", +".hM c #2938ad", +"#ka c #29396c", +"#Vv c #293a42", +"#rq c #293a80", +".e5 c #293aa6", +".aR c #293abe", +"#uL c #293b4f", +"#d# c #293b91", +"#in c #293ba7", +"#y1 c #293c76", +"#y5 c #293c88", +"#aO c #293c9a", +"#io c #293ca5", +"#RU c #293d32", +"#b. c #293db0", +".es c #293dba", +"#nd c #293e91", +"#fR c #29409e", +"#g8 c #2940a6", +".k7 c #2940b2", +".og c #2940b4", +"#ME c #29429c", +".kV c #2942c1", +"#R8 c #294344", +"#tQ c #294380", +"#cg c #2943b4", +".mW c #2946bb", +"#wg c #294783", +"#FS c #294867", +"#uq c #294877", +"#p1 c #29487e", +"#z4 c #294881", +"#2e c #294a3f", +"#Dw c #294a6d", +"#tG c #294b92", +"#Jw c #294c45", +"#v4 c #294c6a", +"#Cu c #295089", +"#Sb c #295149", +".HY c #29518f", +"#W8 c #295244", +".rj c #2953c9", +"#Im c #295673", +".re c #2957e0", +"#JZ c #29588e", +"#Ls c #2958a8", +"#U0 c #29596d", +"#DU c #29599b", +".42 c #295ab9", +".1j c #295ac0", +"#Hh c #295b72", +"#Ix c #295b7c", +".st c #295bd8", +".1f c #295cc9", +".XH c #295dc2", +".1e c #295dca", +".uu c #295fb5", +"#wK c #2960a1", +"#2I c #296460", +".qO c #2969d5", +".pE c #296ac8", +".D5 c #296bc1", +"#EU c #296d76", +"#NG c #296db8", +".GJ c #2973b4", +".Hz c #297bc5", +"Qtj c #2a1f95", +"QtC c #2a24ac", +"QtV c #2a28d1", +"#h0 c #2a2b7d", +"#VH c #2a2e31", +".bp c #2a2eab", +"#vM c #2a3060", +".nN c #2a30bc", +"#h3 c #2a3181", +".hP c #2a31a6", +".bu c #2a31b3", +"#Oa c #2a323d", +"#fy c #2a3285", +".kp c #2a32b1", +"#N6 c #2a335e", +"#Af c #2a336a", +"#fm c #2a3376", +"#hZ c #2a347c", +"#sS c #2a356d", +"#h8 c #2a3587", +".j8 c #2a35a9", +"#u. c #2a3668", +".d6 c #2a36a4", +".lR c #2a37b9", +"#mz c #2a3869", +"#en c #2a3890", +"#qd c #2a397a", +".eu c #2a39ba", +"#Vy c #2a3b43", +"#xc c #2a3b57", +".cc c #2a3bc7", +"#WK c #2a3c40", +"#yO c #2a3c7a", +".gG c #2a3cac", +".oX c #2a3cc2", +"#Vt c #2a3d39", +"#cZ c #2a3d77", +"#NP c #2a3e7d", +"#DM c #2a4072", +"#tH c #2a4079", +"#0m c #2a4137", +"##B c #2a41a7", +"#g9 c #2a41a9", +"#cf c #2a41b1", +"#fV c #2a44a3", +".jV c #2a44bd", +"#dv c #2a45ac", +".ee c #2a45b6", +".aT c #2a45d0", +"#p4 c #2a4676", +".oi c #2a47bc", +".fr c #2a48b6", +"#Zy c #2a4937", +".p5 c #2a49d7", +"#uO c #2a4a63", +"#Lq c #2a4a9f", +".v5 c #2a4db1", +".81 c #2a4db3", +".zA c #2a4eaf", +"#we c #2a4f83", +"#ua c #2a4f86", +".v6 c #2a50b5", +"#SM c #2a50cb", +"#V9 c #2a524a", +"#DK c #2a5283", +"#0G c #2a5335", +"#XL c #2a53a2", +".4Z c #2a53bc", +"#0Q c #2a543c", +"#tE c #2a548e", +".41 c #2a57bc", +".1i c #2a5ac0", +".6A c #2a5bc1", +".sq c #2a5ce3", +"#MH c #2a5eb2", +".1c c #2a5ecc", +".Ws c #2a60b8", +".Lu c #2a61b4", +".Ki c #2a62af", +".44 c #2a63ba", +".tj c #2a64b8", +"#TU c #2a6591", +".r3 c #2a65c3", +".45 c #2a67ba", +".qN c #2a68d5", +".Gp c #2a6bc7", +".Gx c #2a6cb8", +".Fs c #2a70b6", +".HL c #2a72bc", +".HE c #2a72be", +".HS c #2a73b7", +".HC c #2a77bf", +".mE c #2b1cb5", +"#LF c #2b263d", +".cv c #2b29a4", +"#LC c #2b2a38", +"#q2 c #2b2b61", +".hR c #2b2ca0", +".dw c #2b2eb1", +".#J c #2b2ebb", +"#Gz c #2b2f4c", +".#z c #2b2fb4", +"#wn c #2b3074", +"#gY c #2b308b", +".br c #2b31ad", +".ii c #2b32a4", +".dO c #2b32a6", +".#0 c #2b32c8", +"#c3 c #2b3372", +".#v c #2b33a0", +"#1H c #2b3439", +"#gL c #2b3481", +"#HD c #2b356a", +"#u8 c #2b3573", +"#gG c #2b357c", +".fB c #2b35a4", +"#sQ c #2b366c", +"#sR c #2b366e", +"#gv c #2b3678", +".d4 c #2b36aa", +".fJ c #2b36b4", +"#sP c #2b376b", +".iS c #2b38ab", +"#cb c #2b38b8", +".nM c #2b38c4", +"#S2 c #2b393c", +".GU c #2b3942", +".ev c #2b39bc", +"#dd c #2b3a9f", +"#qg c #2b3b79", +"#l3 c #2b3c8e", +"#WJ c #2b3d3f", +"#nJ c #2b3d6d", +".gH c #2b3dab", +"#WH c #2b3e45", +"#Bx c #2b3e83", +".ej c #2b3ea5", +".cd c #2b3ec9", +".gQ c #2b3fb2", +"#MZ c #2b4045", +"#nK c #2b406b", +".ei c #2b40a9", +"#ha c #2b40ab", +".db c #2b40b3", +"#bY c #2b4197", +"#aL c #2b41a7", +"#a9 c #2b41cb", +".kT c #2b42c6", +"#p7 c #2b436f", +"#v1 c #2b4462", +"#qC c #2b4487", +".oh c #2b44ba", +".kU c #2b44c5", +"#qD c #2b4582", +"#ch c #2b45b6", +"#dt c #2b46af", +".mX c #2b46bb", +"#zE c #2b476e", +"#eF c #2b47a8", +".p8 c #2b47d6", +"#eK c #2b48a6", +"#1R c #2b4931", +".Xu c #2b49a9", +"#Zn c #2b4a20", +"#ZA c #2b4b3e", +".8Z c #2b4cab", +"#Zo c #2b4d2c", +".fp c #2b4eb4", +"#V4 c #2b4f45", +"#1E c #2b512c", +"#KQ c #2b5142", +"#ZG c #2b5144", +".xi c #2b52b7", +"#2o c #2b5377", +"#DG c #2b538e", +"#jN c #2b5470", +".40 c #2b54bd", +"#wa c #2b5591", +"#YB c #2b564c", +"#M6 c #2b564f", +"#xo c #2b568d", +".c2 c #2b56c9", +"#yG c #2b5788", +".ou c #2b5ac2", +".sp c #2b5be3", +"#Xo c #2b5e73", +".XG c #2b5fc2", +".tB c #2b5ff3", +"#JY c #2b608a", +".MI c #2b61b9", +".Lv c #2b62bd", +"#Lu c #2b63ae", +"#qT c #2b6478", +"#wJ c #2b64a9", +".4a c #2b66c4", +".CU c #2b6bc3", +".BG c #2b6bc5", +".BS c #2b6db9", +"#e3 c #2b6e7e", +".qS c #2b70cd", +".HP c #2b74b9", +".Fb c #2b77d7", +".Gj c #2b7edc", +".co c #2c25a7", +"#Kp c #2c2a37", +".#T c #2c2fb2", +"#Ut c #2c3031", +"#hx c #2c3060", +".#t c #2c32a2", +"#XU c #2c3343", +"#gK c #2c3580", +"#gz c #2c367b", +"#gy c #2c367e", +"#q. c #2c376f", +".cH c #2c37ad", +"#wk c #2c396d", +"Qtt c #2c39c3", +"#yN c #2c3a79", +"#Z. c #2c3b3e", +"#ro c #2c3b7e", +".m2 c #2c3bb8", +".m7 c #2c3bba", +"#Ze c #2c3c4b", +"#za c #2c3d82", +".c# c #2c3dbf", +"#Tl c #2c3e42", +"#p9 c #2c3e70", +"#eD c #2c3ea4", +"#on c #2c4194", +"#bZ c #2c419a", +"#S9 c #2c4235", +"#h# c #2c42af", +".ft c #2c42b2", +"#a8 c #2c42cb", +"#1L c #2c4444", +"#z0 c #2c4588", +"#or c #2c4599", +".c7 c #2c47ba", +"#jD c #2c489b", +"#eZ c #2c49a7", +"#2f c #2c4b3c", +"#Lj c #2c4b8e", +"#f9 c #2c4ba6", +".57 c #2c4bbf", +".59 c #2c4cbb", +".58 c #2c4cbd", +"#DP c #2c4d82", +"#dH c #2c4db8", +".kD c #2c4dce", +"#v3 c #2c4e69", +"#Li c #2c4f93", +".sn c #2c50d8", +"#YQ c #2c5159", +"#Ka c #2c5198", +".Xz c #2c51b9", +".3H c #2c51c3", +"#KR c #2c5243", +".yt c #2c52bd", +"#ZL c #2c5350", +".Xw c #2c54b4", +"#bf c #2c55cb", +"#JQ c #2c567c", +".2w c #2c56c6", +"#xj c #2c5782", +"#T0 c #2c59ac", +"#xl c #2c5a8c", +".wU c #2c5aaf", +"#ZW c #2c5b77", +"#Rk c #2c5cb0", +".tJ c #2c5cca", +".2z c #2c5dc4", +"#gb c #2c5e75", +".1l c #2c5ec1", +"#qU c #2c5f74", +".Wo c #2c60b3", +"#OW c #2c60b6", +"#Xp c #2c6173", +"#e2 c #2c697e", +".Gy c #2c6bb8", +".pJ c #2c6ccd", +".qP c #2c6cd6", +".Fd c #2c6dc9", +"#JW c #2c7083", +".Gm c #2c70c1", +"#NF c #2c71a8", +".HD c #2c71be", +".HM c #2c74bc", +".IV c #2c76bd", +".IY c #2c77bb", +"Qtk c #2d219f", +".dA c #2d2298", +"#RF c #2d2942", +".bk c #2d2cb8", +"#ez c #2d30a3", +".FK c #2d3134", +"#WW c #2d3235", +"#h2 c #2d3283", +".#B c #2d32c2", +".H3 c #2d3349", +"#uw c #2d3365", +".ij c #2d33a5", +".bq c #2d33af", +"#Qu c #2d343a", +"#U# c #2d343c", +".iT c #2d34a9", +"#fz c #2d358a", +"#eC c #2d35a0", +"#sV c #2d366f", +"#hR c #2d377f", +"#mT c #2d3a7e", +"##M c #2d3cb1", +"#bM c #2d3d70", +"#mA c #2d3f6d", +".fm c #2d3f95", +"#bN c #2d4085", +"#Qo c #2d408f", +"#ip c #2d40a6", +"#T. c #2d4135", +".lI c #2d41c6", +"#mB c #2d426f", +".k8 c #2d42b5", +"#QK c #2d4336", +"#Qn c #2d438c", +"#l4 c #2d4396", +"#ji c #2d448a", +"##A c #2d44aa", +"#u4 c #2d4575", +"#O8 c #2d459f", +"#eO c #2d46aa", +"#uM c #2d4762", +"#fW c #2d47a8", +".bS c #2d49c7", +"#IU c #2d4a8e", +"#uN c #2d4b63", +"#zF c #2d4b71", +".lZ c #2d4bc5", +"#2i c #2d4c47", +"#g. c #2d4ca7", +"#uP c #2d4e6d", +"#vF c #2d4e71", +"#2p c #2d4e83", +"#dG c #2d4eb9", +"#dI c #2d4fba", +"#Co c #2d5086", +"#cs c #2d50c4", +"#V0 c #2d5143", +".B2 c #2d51c3", +"#KS c #2d5348", +"#Yv c #2d545b", +"#Gd c #2d5473", +"#Xf c #2d5634", +".so c #2d57df", +"#xn c #2d5a91", +".3L c #2d5acf", +".2x c #2d5cc6", +".sa c #2d5eaa", +".3N c #2d5ec4", +"#W2 c #2d622e", +"#QX c #2d6250", +"#G5 c #2d6268", +"#ZX c #2d6284", +"#ZZ c #2d6392", +".ox c #2d64c9", +"#r5 c #2d6681", +"#Nb c #2d6751", +"#2H c #2d6b66", +".qM c #2d6cd6", +".pF c #2d6ec8", +"#Na c #2d6f53", +".Ef c #2d71ba", +".qQ c #2d71d6", +".qR c #2d72d1", +"#N# c #2d7351", +".HO c #2d75bd", +".HT c #2d76ba", +".I2 c #2d78bb", +".IJ c #2d79b7", +".IQ c #2d7cc1", +".H2 c #2e2a45", +".#S c #2e2bb0", +".nO c #2e2bb6", +".cw c #2e2ca9", +"#VE c #2e2f34", +".bn c #2e2fad", +"#e9 c #2e3166", +".hQ c #2e31a6", +"#Aq c #2e346e", +"#mR c #2e3579", +"#iW c #2e3675", +"#h4 c #2e3687", +".in c #2e36a5", +"#Po c #2e373e", +"#qj c #2e3873", +".a3 c #2e38bc", +"#qi c #2e3a76", +".#X c #2e3ac2", +"#WE c #2e3b41", +"#rC c #2e3b70", +"#aR c #2e3ba1", +".fv c #2e3fab", +".nA c #2e3fc3", +"#ke c #2e4066", +".#w c #2e40a4", +"#R9 c #2e4249", +"#b1 c #2e42a3", +"#l5 c #2e4497", +"#h. c #2e44b1", +"#p3 c #2e457b", +"#r2 c #2e4595", +"#NN c #2e4690", +"#fZ c #2e46aa", +"#eQ c #2e47ab", +"#c. c #2e48b6", +"#nh c #2e499a", +"#f8 c #2e4daa", +".mV c #2e4dc1", +".sm c #2e4ed5", +".7j c #2e4fb6", +".mU c #2e4fc2", +"#xe c #2e506c", +"#UT c #2e513b", +"#V8 c #2e513d", +".v7 c #2e51b7", +".3G c #2e51c5", +"#uQ c #2e5276", +"#KP c #2e534b", +"#Bd c #2e5387", +"#IO c #2e5399", +"#GY c #2e546b", +"#uR c #2e557e", +".6. c #2e55bc", +"#OX c #2e58c4", +"#0Y c #2e593b", +"#yE c #2e5983", +"#Yw c #2e5a41", +"#Cq c #2e5b84", +"#SA c #2e5c8d", +".uO c #2e5cd4", +"#Wb c #2e5d6d", +"#tC c #2e5e8c", +"#tD c #2e5e8f", +"#ES c #2e5f6d", +".1k c #2e5fc5", +".Db c #2e5fd6", +".XF c #2e60c1", +".sr c #2e60e3", +".1m c #2e63c1", +".6d c #2e64ba", +"#LY c #2e6546", +"#SK c #2e65c0", +".pG c #2e6ecf", +".Eg c #2e72bb", +"#OS c #2e739d", +".HA c #2e75cf", +".HI c #2e76be", +".HV c #2e78b7", +".HU c #2e78b9", +".IZ c #2e79bd", +".IR c #2e7bbf", +".IP c #2e7bc1", +"#Ny c #2e8455", +".LB c #2f253e", +".g0 c #2f2c9f", +"#MY c #2f2e3e", +".Kq c #2f3034", +"#LL c #2f3241", +".bo c #2f33b0", +"Qto c #2f33b8", +"#ti c #2f3454", +".ca c #2f35c7", +"#fN c #2f3799", +".ko c #2f37b3", +"#S0 c #2f383d", +"#Fa c #2f3974", +"#Fb c #2f3976", +"#hX c #2f3980", +"#1G c #2f3a36", +"#Vq c #2f3a4e", +"#cc c #2f3ab8", +"#1J c #2f3b47", +"#my c #2f3b6f", +"#R0 c #2f3c35", +"#RM c #2f3d40", +"#lz c #2f3d95", +"#CO c #2f3e67", +"#qe c #2f3e7f", +".lY c #2f3ebd", +"#1K c #2f4047", +"#b2 c #2f42a8", +"#hb c #2f42ab", +"#.M c #2f43b6", +"Qtp c #2f43c8", +"#p8 c #2f4473", +"#xd c #2f476b", +"#ba c #2f48bc", +"#Bf c #2f4986", +"#fX c #2f49aa", +"#1C c #2f4c36", +"#eY c #2f4dad", +"#01 c #2f4e50", +".56 c #2f4ec3", +".YI c #2f50b9", +"#Ci c #2f5177", +".7k c #2f52b8", +"##2 c #2f52c8", +"#KU c #2f5443", +"#bd c #2f54c9", +"#Lr c #2f55a8", +".uX c #2f55b6", +"#be c #2f56cd", +"#ZB c #2f573c", +"#YC c #2f574c", +"#Sa c #2f5756", +"#ct c #2f57c9", +"#yB c #2f598b", +".2s c #2f5acb", +"#0R c #2f5d39", +"#xm c #2f5d91", +".2t c #2f5dcd", +"#QZ c #2f5f4f", +"#vr c #2f5fab", +".Wn c #2f5fc1", +"#F9 c #2f6089", +".6b c #2f60bc", +".6c c #2f62bb", +"#Q. c #2f639f", +".3P c #2f63c9", +".tG c #2f63d9", +"#wH c #2f64b0", +"#OY c #2f65af", +"#Nn c #2f662f", +".zj c #2f66b9", +"#EW c #2f6798", +"#Lv c #2f67b2", +".6e c #2f67ba", +"#wI c #2f68af", +".r2 c #2f69ca", +".r8 c #2f6ab6", +"#ZE c #2f6b49", +".qY c #2f6ecd", +".qL c #2f6ed7", +"#NH c #2f71cf", +".vV c #2f74cf", +".HN c #2f77bf", +".HQ c #2f78bd", +"QtB c #3028b1", +"#Jc c #302b31", +"#HY c #302b41", +"#Ja c #302c3b", +".fX c #302fa6", +"#Jf c #303052", +"#gX c #30318e", +"#h1 c #303384", +".Je c #303435", +"#bS c #303684", +"QtH c #3037b9", +"QtG c #3037bb", +"#XR c #303948", +"#df c #303998", +"#QC c #303a44", +".FI c #303b41", +"#dq c #303baf", +".fH c #303cb6", +"#XP c #303d45", +"#h5 c #303d8c", +"#ep c #303d9b", +".ym c #303daf", +"#lI c #303e85", +".d9 c #303e9f", +"#Uk c #303f44", +".hi c #3040af", +"#WN c #304149", +".gD c #3041b5", +"#Vu c #304244", +"#rr c #30428a", +"#p2 c #30447f", +".oc c #3044bd", +"##C c #3045ae", +"#bX c #30469b", +".83 c #30499d", +"#a1 c #3049d7", +"#.P c #304bc0", +"#IR c #304c96", +"#dw c #304cb0", +"#eL c #304da9", +"#EI c #304e74", +"#FT c #304e80", +"#00 c #305158", +"#ga c #305476", +".3I c #3054c6", +"#KK c #30563d", +".7l c #3056b9", +"#vq c #3057a4", +"#zO c #305a84", +".6# c #305abe", +"#zM c #305b7e", +"#yw c #305b86", +"#uS c #305b88", +"#Ij c #305d70", +"#w. c #305d94", +"#w# c #305d96", +".wT c #305db2", +"#uT c #305e8f", +"#SH c #305fad", +"#ZC c #30603a", +"#LX c #306143", +"#TY c #30619c", +".zG c #3061d8", +".ss c #3061e1", +"#Wd c #30627b", +".2A c #3062c5", +"#zU c #306493", +".pw c #3064ca", +"#TW c #306599", +".1n c #3065c1", +".2C c #3065c5", +".uJ c #3066e0", +"#N. c #306f50", +".r0 c #3070c7", +".qK c #3072d0", +".HR c #3079bd", +"#10 c #307a3d", +".IX c #307ac1", +".I1 c #307bbe", +".8N c #31285f", +".MP c #312c40", +"#ml c #313163", +".Jb c #31324e", +"#v. c #313467", +".a6 c #3135ba", +"#Zf c #31374d", +"#c5 c #313978", +"#fA c #31398e", +"#wm c #313b6e", +"#Ag c #313b80", +"#lF c #313b82", +".lS c #313bbe", +".d5 c #313caf", +"#dh c #313d9f", +"#aX c #313dad", +".fw c #313fa8", +"#Vs c #314043", +"##Q c #3140bd", +".mv c #3140bf", +"#QJ c #314137", +"#e# c #314174", +".lH c #3141c8", +".j4 c #3142b6", +"#dr c #3143b3", +"#b0 c #3146a3", +"#ne c #31479a", +"#qR c #31479c", +"#dl c #3147b4", +".aG c #3147bf", +"##V c #3147ce", +"#WY c #314834", +"#AT c #314874", +".da c #3148ba", +"#tw c #314a68", +"#ng c #314a9c", +".aH c #314ac0", +"#ci c #314bba", +"#Tk c #314c43", +"#.p c #314db1", +"#dE c #314dba", +"#.n c #314eb6", +".bT c #314fc9", +"#Th c #315041", +"#NS c #3150a3", +"#cm c #3150ba", +"#zH c #315178", +".7h c #3151be", +".8v c #3152bb", +".7i c #3152bd", +".8z c #3153b4", +"#1D c #315434", +"#kW c #3154a6", +"#R6 c #315547", +"#hn c #3155ad", +".8A c #3155b3", +"#2h c #31564f", +"#SO c #3157ac", +"#FQ c #31595b", +".7m c #3159b8", +"#zQ c #315a88", +".7n c #315cb8", +".6a c #315dbe", +"#EP c #315e85", +"#yx c #315e88", +"#TM c #315f6e", +"#Iz c #315f80", +".7o c #315fb7", +"#Yh c #316036", +"#G4 c #316066", +"#uU c #316094", +".2y c #3160ca", +".Lw c #3161b6", +".1b c #3161d0", +"#X# c #31624f", +"#SI c #3164b7", +".Z1 c #3164cf", +".Z2 c #3164d1", +".ow c #3166cc", +".ut c #3167bf", +".ti c #316ac1", +".Aw c #316ac3", +"#Wl c #317393", +"#2L c #31785a", +".qW c #3178d4", +".IO c #3179c3", +".Fa c #317ad6", +".IW c #317bc2", +".Hu c #317ed6", +".IM c #317fc1", +".IE c #3180cd", +".qU c #3181da", +".lC c #3229b8", +".nP c #322ab3", +".MO c #322e2b", +"#gM c #322e85", +"#gN c #322f86", +"#gO c #32328a", +"#tj c #32336b", +"#Gq c #323868", +"#Ar c #32386c", +"#Pf c #323953", +".lA c #3239c7", +"#Uc c #323d41", +".#F c #323ec6", +"#eo c #323f9b", +".#x c #3240ab", +".m3 c #3240bd", +".q4 c #3241b8", +".mn c #3242b3", +"#a7 c #3246cb", +"#b# c #3247ba", +".m9 c #3247c4", +"#aD c #32497f", +"#ds c #324ab6", +"#l9 c #324b9b", +".n8 c #324cc3", +".w9 c #324eb9", +"#IA c #325188", +"#eN c #3251ac", +"#O2 c #3252b5", +".7g c #3252c1", +"#US c #32533e", +"#UZ c #325376", +".7N c #3253be", +".8y c #3254b6", +"##3 c #3255cb", +"#Xm c #325a5a", +".8B c #325ab2", +"#ZI c #325b39", +"#KL c #325b4b", +"#KM c #325b57", +"#DH c #325c96", +".2v c #325dcd", +"#SG c #325ea7", +"#Rt c #325ed7", +"#Be c #325f80", +"#Le c #325f9a", +"#Rl c #325fbc", +"#OD c #326053", +"#1a c #326091", +".2u c #3260cf", +".uM c #3260d0", +".pv c #3261c9", +".Wm c #3261cb", +".uN c #3261d5", +".x6 c #3262b4", +".7p c #3262b7", +".6B c #3263c9", +".ov c #3263ca", +".2B c #3267c7", +"#19 c #326d41", +".D2 c #326ed0", +".IL c #3271c1", +".HB c #3272c9", +"#OU c #3278a9", +".zI c #3278d7", +".Eo c #327ae6", +".I3 c #327dbe", +".I0 c #327dc0", +".I4 c #327ebc", +".J9 c #327fc3", +".J8 c #327fc5", +".Ka c #3280c2", +".GS c #332735", +"Qty c #332cb8", +"#fC c #332f8d", +"#Qp c #333043", +"#GJ c #333359", +"Qt3 c #3334cd", +"#cM c #33356e", +"#C7 c #333570", +".a4 c #3337bc", +"#VD c #333a40", +"#uK c #333a44", +"#XT c #333a4d", +"#bW c #333a82", +"#Kx c #333b52", +"#ap c #333c73", +"#q# c #333d78", +"#fp c #333d7b", +"#ea c #333f73", +"#qb c #333f7b", +"#di c #3340a6", +"#qh c #33417e", +".oY c #3341c6", +"##O c #3342b9", +".et c #3342c3", +".m0 c #3346be", +"#ce c #3347ba", +".od c #3347c0", +"##U c #3349d0", +"#P# c #334a98", +"#eE c #334baf", +"#R3 c #334c49", +"#nf c #334c9e", +"#eP c #334cb0", +"#QM c #334d5a", +"#SR c #334f7e", +"#dN c #334fb0", +".b9 c #334fd6", +"#eM c #3350ac", +"#dO c #3350ae", +"#cq c #3350c6", +"#Yr c #33515b", +".55 c #3351c9", +"#f7 c #3352af", +"#dK c #3352be", +"#CH c #33538c", +".8u c #3353c0", +"#hp c #335475", +"#dA c #3354b5", +"#0y c #33553c", +"#.d c #3355ac", +"#Mx c #3356a7", +".rk c #3357c9", +"#B# c #33596c", +"#xh c #33597d", +"#Lh c #3359a0", +"#Qa c #3359ba", +"#Rm c #335ac1", +".2r c #335acf", +"#Xe c #335b43", +"#A7 c #335b7f", +".su c #335dd6", +".uV c #335ec6", +"#Wj c #335f68", +"#zT c #335f84", +"#Ik c #336077", +"#0O c #33613d", +"#MG c #3361b7", +".Z3 c #3363d1", +"#2J c #33656c", +"#1b c #33659a", +".Au c #3365c6", +".tI c #3365d4", +"#Zr c #33663d", +"#SJ c #3366bf", +".tH c #3366d9", +".tF c #3366dc", +"#qS c #336981", +"#Hb c #336985", +"#0I c #336a42", +"#SL c #336ac7", +"#TT c #336e96", +".pI c #3373d4", +".qJ c #3374d2", +".IN c #3378c3", +".E9 c #337ce2", +".qV c #337ed9", +".I6 c #337fbb", +".I5 c #337fbd", +".JY c #3381bf", +".IC c #3384d5", +".La c #3392c2", +".7z c #342a5f", +".lD c #342dbb", +"#HZ c #343150", +".fW c #3435ab", +"#hw c #343673", +"#wZ c #343a6c", +"#ux c #343b6f", +"#O# c #343c49", +"#cN c #343d66", +"#j7 c #343e7b", +".j7 c #343fb3", +"#cd c #3442bc", +"#de c #3443aa", +"#aB c #344482", +"#h6 c #344492", +"#WG c #34454c", +"#a4 c #3445c7", +"#Vz c #34464a", +"#.N c #3449be", +"#f0 c #344aad", +".mY c #344ac1", +"#AU c #344b77", +"#O3 c #344cb8", +"#l8 c #344d9f", +"#fY c #344db2", +".o. c #344dc4", +".n9 c #344ec5", +"#m. c #344f9e", +"#.m c #3450bb", +".dl c #3450d5", +"#zG c #345179", +"#.Q c #3451c6", +"#eX c #3452b4", +".4U c #3452ca", +".4T c #3452cc", +"#Bb c #345370", +"#dF c #3453bf", +"##1 c #3453c8", +"#yH c #34547a", +".8x c #3454b9", +".8w c #3454bb", +".3K c #3454c5", +"#Xl c #345743", +"#kX c #3458ac", +"#V1 c #345a45", +"#uY c #345b9c", +"#O1 c #345bb6", +".uW c #345bc0", +".4L c #345bda", +"#L9 c #345c44", +".pu c #345dc6", +".Xx c #345ec0", +"#Ok c #346144", +"#Xx c #346178", +".J. c #34619c", +"#Xn c #346271", +"#YK c #346283", +"#0E c #346341", +"#Wa c #346373", +".XJ c #3464a4", +".7q c #3464b8", +".At c #3464c8", +".Dd c #3464e0", +"#e1 c #346583", +"#gc c #346d7e", +"#ET c #346d8a", +".D3 c #3474ce", +".pH c #3474d5", +"#dT c #34768c", +".qX c #3476d4", +".Gi c #347ada", +".IS c #347dc2", +".NO c #347ed5", +".NT c #347fda", +".I7 c #3480bc", +".Ke c #3482c0", +".Kd c #3482c2", +".mF c #3526bd", +".eL c #352997", +".dz c #352da7", +"#RE c #352f55", +"#uA c #352f6d", +"#Ks c #35313f", +"#Kt c #353247", +".lE c #3532bf", +"#la c #353364", +"#gW c #353492", +"#sb c #35356b", +"Qtz c #3537be", +"#sT c #353a74", +".dv c #353abc", +"#mS c #353c80", +"Qt. c #353c82", +"#Pi c #353e43", +"#hY c #353f86", +"#Eg c #35426f", +"#WF c #354449", +"##P c #3545be", +"#u3 c #354698", +"#0w c #35493e", +"#Yk c #35494a", +"#iq c #3549ac", +"#.H c #3549ce", +"#l6 c #354b9e", +".ob c #354bc3", +"#P. c #354c98", +"##p c #355095", +"#cA c #3551b4", +"#Hr c #355270", +".v1 c #3552b8", +"#Zz c #355349", +"#bg c #3553cf", +"#up c #355483", +"#FU c #35548a", +"#cx c #3554c0", +".4V c #3554c9", +".4Y c #3555c6", +"#zI c #35567f", +"#u2 c #355689", +".3J c #3556c7", +"#cr c #3556ca", +"#hm c #3557b0", +".v4 c #3557b9", +".bV c #3557c5", +"#Ic c #35585c", +"#ZK c #355967", +"#MF c #3559b1", +".09 c #355acc", +"#I4 c #355c83", +"#NL c #355cb9", +"#cu c #355ed0", +"#FX c #355f85", +"#Yz c #356067", +".uU c #3561ca", +".sv c #3562d9", +"#hq c #35637b", +"#DJ c #356395", +".vH c #3563b9", +"#We c #356474", +"#XO c #3564b4", +"#XN c #3564b6", +"#KX c #356555", +"#NK c #3565cb", +".uK c #3566dc", +"#0N c #356736", +"#Ld c #356798", +".Kk c #3568a1", +"#NJ c #3569d6", +"#pH c #356a7a", +".2D c #356aca", +".r1 c #356fd0", +".D0 c #3577d8", +"#dS c #35788b", +".HJ c #3579c2", +".NP c #357fd8", +".NS c #3580db", +".J3 c #3582c6", +".JQ c #3582c8", +".Kf c #3583c1", +".Kc c #3583c3", +".J2 c #3584c7", +".ID c #3584d3", +".Lc c #358bc4", +".dC c #362595", +"Qte c #362e95", +"#Jb c #363030", +"#Kq c #363032", +"#Kr c #363138", +".eI c #3631a9", +"#HX c #363241", +"#MX c #363449", +"#Ku c #36364e", +"#Ej c #363873", +"#Pb c #363940", +"Qt1 c #3639e0", +".lV c #363abf", +"#sU c #363c76", +"#N3 c #363d57", +"#vN c #363e6d", +"#Vn c #363f3c", +"#fo c #363f82", +"#lH c #363f84", +"#SZ c #364037", +"#QB c #36404c", +"#hS c #364183", +"#rA c #364377", +".m1 c #3646bf", +".gF c #3647bb", +"##R c #3648c8", +"#Sf c #364a55", +"#z# c #364a91", +"##E c #364abb", +".mZ c #364bc2", +"#Tn c #364c5a", +"#.s c #364dbd", +"#.I c #364dcf", +"#O9 c #364f9f", +"#kS c #364fa1", +".o# c #364fc6", +"#dD c #3650be", +"#cz c #3651b8", +".d# c #3652c0", +"#dx c #3653b7", +"#dL c #3653b9", +"#eW c #3653bb", +"#QN c #36545c", +".3F c #3654cc", +".4S c #3654ce", +"#UP c #365567", +"#jE c #3655a5", +"#cl c #3655bf", +"#dJ c #3655c1", +".4W c #3655c9", +"#.V c #3656c3", +".4X c #3656c7", +"#Xk c #365738", +"#V7 c #36573c", +"#zJ c #365780", +"#.W c #3657c2", +"#1S c #365b32", +"#iA c #365cb1", +".uR c #365dc6", +".4Q c #365dd4", +"#FY c #36618b", +"#yA c #366194", +"#SF c #3661a6", +".uS c #3661ca", +"#Il c #36627d", +"#uW c #36629f", +".b5 c #3662df", +"#XM c #3663b8", +"#K0 c #366a75", +"#Va c #366a8f", +".3O c #366acf", +"#Lc c #366b93", +".th c #366fc8", +".D1 c #3676d8", +".JV c #367db5", +".Hv c #367fce", +".NQ c #3680d9", +".J4 c #3681c4", +".NR c #3681dc", +".J1 c #3683c9", +".IB c #3683d3", +".Ht c #3683db", +".K# c #3684c6", +".Kg c #3685c0", +".Hs c #3686df", +".Lg c #3689bd", +"#GK c #373566", +"#fD c #373693", +"#gV c #373895", +".lF c #373ac5", +"#Gs c #373b6b", +"#gQ c #373b94", +".gZ c #373fae", +"#Pp c #374045", +"#e. c #374069", +"#dp c #3740b9", +".lG c #3740c9", +"#hU c #374186", +"#dn c #3741bd", +"#gA c #374280", +"#Y7 c #37434f", +"#qa c #37437d", +"#RW c #37443b", +"#RN c #37444a", +"#fk c #374479", +".em c #3744ac", +"#ey c #3745ae", +"#Y9 c #37464d", +"#DN c #37477a", +"#aP c #3747a6", +"#aM c #3749ab", +".9t c #374acd", +"#EE c #374b64", +"##T c #374bd0", +"#xw c #374c67", +"#NR c #374da2", +"#u5 c #375079", +"#os c #3750a4", +"#eR c #3750b4", +"#cp c #3750c7", +"#VK c #375146", +".c8 c #3751bf", +"#Yq c #375369", +"#dM c #3754b8", +"#cy c #3754bc", +"#bb c #3754c9", +"#Sd c #375553", +"#dz c #3755b7", +"#cw c #3755c3", +"#kV c #3756a8", +"#NM c #3756a9", +".bU c #3756ca", +"#.R c #3756cb", +".v8 c #3757ba", +".8t c #3757c4", +"#2q c #37588e", +".9J c #3758c1", +"#a# c #3758cb", +"#ZQ c #375a54", +"#0Z c #375a5c", +"#Cn c #375a84", +".xj c #375ac0", +"#Cj c #375b7f", +"#A6 c #375c86", +"#K7 c #375d66", +"#Qb c #375dc0", +"#FW c #375e85", +"#Cp c #375e95", +"#Zq c #375f3d", +".8C c #375fb6", +".ZY c #375fce", +".zF c #3763de", +"#Wc c #376575", +"#WA c #376596", +".YQ c #3765d5", +"#U1 c #37686d", +"#Io c #376877", +".Z0 c #376ad5", +"#Iq c #376c72", +".s# c #376cb8", +".MJ c #376cd6", +"#JV c #376d91", +".us c #376dc5", +"#r4 c #37708e", +"#Mp c #37719f", +"#Xz c #37758c", +"#OV c #3775b2", +".NN c #377ed6", +".J7 c #3784ca", +".Kb c #3785c7", +".Kh c #3786c1", +".JO c #3786d1", +".Lf c #3789c1", +".Lb c #3792c7", +"Qtu c #3828af", +"#w3 c #38356c", +".f1 c #38389a", +"#LK c #38394d", +"#s# c #383a61", +"#gP c #383a91", +".a5 c #383bc0", +"#MR c #383c47", +".90 c #383d74", +"#cP c #383f6d", +"#ar c #383f85", +".lB c #383fcd", +".#y c #3841ba", +".m6 c #3843c3", +"#Ey c #38457a", +"#eq c #3845a3", +"#VJ c #384848", +"#ir c #384cad", +"#Um c #384d46", +"#l7 c #384ea1", +".ef c #384ebb", +"#T6 c #3851a3", +"#.O c #3851c7", +"#cj c #3854c2", +"#J8 c #3855a1", +"#IQ c #3855a3", +"#iB c #385678", +"#bi c #3856ce", +"#bh c #3856d0", +"#G0 c #385769", +".pj c #3857c1", +"#.S c #3857cb", +"#bj c #3857cc", +".9N c #3858bb", +"#.U c #3858c7", +"#IP c #3859aa", +".9O c #3859ba", +".9I c #3859c2", +"#Ct c #385a97", +"#hl c #385ab3", +"#A4 c #385b85", +"#xi c #385f88", +".1. c #3860d1", +".AR c #3860da", +".4M c #3860dc", +".x3 c #3861b1", +".1a c #3861d3", +"#JE c #386260", +"#yv c #38628c", +".wS c #3862b4", +"#YN c #38638e", +"#UV c #386455", +"#TK c #386495", +".uT c #3864cf", +"#DI c #38669a", +".Z4 c #3866d5", +"#Nl c #386840", +".YT c #3868d6", +"#YO c #386991", +"#Iy c #386994", +".Z9 c #3869d2", +".zh c #386ac1", +"#1Y c #386b4a", +"#Nc c #386b5a", +"#PE c #386b64", +"#H# c #386b8a", +".YW c #386cd1", +"#DF c #386e92", +".yu c #3870cd", +".r9 c #3872bc", +"#JP c #387588", +".vW c #3875ce", +"#e4 c #387a8a", +"#Ye c #387c41", +".JZ c #387ec6", +".NM c #387fd7", +".Ep c #387fe7", +".J0 c #3880c8", +".IA c #3881ce", +".K1 c #3883c7", +".K. c #3885c9", +".JP c #3886ce", +".Ld c #388ac6", +"#jU c #392f6b", +".eJ c #3931a8", +"Qtn c #3934b2", +".Jf c #393536", +"#Ko c #393544", +".a0 c #3938c2", +"#q1 c #393a70", +".8M c #393a72", +"#gU c #393a97", +"#I5 c #393b47", +"#iJ c #393b76", +"#iK c #393d6d", +"#gR c #39409a", +"#N5 c #394168", +".8G c #39417f", +"#bQ c #39427b", +"#dm c #3944c2", +"#1F c #39463c", +"#rB c #39467a", +"#S8 c #39474a", +"#Ul c #39484b", +".ek c #3948af", +"#a0 c #3948c9", +"#aW c #394ab6", +".9s c #394acc", +"#VA c #394b4d", +"#b4 c #394bb7", +"#b3 c #394cb5", +"#a5 c #394ccd", +"#KE c #394e51", +"#cn c #394ec5", +"#pC c #394fa4", +"#ho c #395177", +"#sG c #39518f", +"#Se c #395257", +"#.q c #3954bb", +"##0 c #3954c9", +"#dy c #3956ba", +"#Ya c #39573d", +".4R c #3957d3", +".7f c #3958cc", +"#FR c #395968", +"#.T c #3959ca", +".9H c #395ac5", +"#aa c #395acb", +"#ZJ c #395b64", +".9P c #395cb8", +"#UY c #395d77", +".YJ c #395ec6", +"#Xd c #395f52", +"#Wi c #395f74", +".08 c #395fce", +"#1V c #396043", +"#ZP c #39605d", +"#iC c #39607d", +".ps c #3960c5", +".pt c #3960c7", +".4P c #3960d7", +".4O c #3960d9", +"#TD c #396149", +"#uX c #3962a2", +".sx c #3962d4", +"#ZH c #39633d", +".sw c #3963d9", +"#yz c #396596", +"#1X c #396649", +"#TG c #396652", +"#uV c #3966a1", +"#ZV c #39677f", +".Dc c #3967e1", +"#r6 c #396882", +".tE c #3968de", +"#1d c #396aa4", +"#KW c #396b46", +"#jO c #396b84", +"#Nm c #396c43", +"#Ne c #396c5b", +".vX c #396dc1", +".0. c #396dd2", +"#cH c #396e8e", +".1o c #396fc7", +"#OE c #397140", +"#pG c #397180", +"#dQ c #39718a", +".yv c #3971d2", +".rZ c #3977cc", +"#0J c #397947", +"#Zt c #397a44", +".Gh c #397fdf", +"#U8 c #3980a0", +".Hr c #3986e0", +".Kp c #3a2e44", +"#MT c #3a335c", +"#LG c #3a344e", +"#fB c #3a3591", +"#vQ c #3a3671", +"#mm c #3a3869", +"#fJ c #3a38a3", +"#MQ c #3a3c4b", +"#Fv c #3a3d74", +"#Ky c #3a3f5d", +"#RY c #3a403c", +"#C4 c #3a4074", +"#do c #3a42be", +"#rs c #3a4c94", +"#.G c #3a4dd0", +"##D c #3a4fbc", +"#2j c #3a504d", +".oa c #3a50c8", +"##Z c #3a51c5", +".9u c #3a51d1", +".8g c #3a52ce", +".5o c #3a54b3", +"#Sj c #3a5769", +"#f6 c #3a58b8", +".d. c #3a58c6", +"##4 c #3a58d0", +".9M c #3a5abf", +"#.X c #3a5ac7", +"#bc c #3a5bcf", +".zB c #3a5cb5", +"#2r c #3a5d95", +"#A5 c #3a5f89", +".zE c #3a60cb", +".4J c #3a61e2", +"#Rs c #3a63d7", +"#Q0 c #3a6458", +"#SB c #3a649e", +".Xy c #3a64c8", +"#TE c #3a6547", +"#0W c #3a6655", +"#yy c #3a6693", +"#Vb c #3a678e", +".vG c #3a67bc", +".uP c #3a67de", +".Z6 c #3a69d3", +"#PH c #3a6a52", +"#Ng c #3a6b55", +"#PB c #3a6c63", +"#15 c #3a6d4c", +"#dP c #3a6d8a", +"#Xy c #3a6e6c", +"#ZY c #3a6f99", +"#Rj c #3a6fb5", +".0a c #3a6fcb", +"#XC c #3a737c", +".tg c #3a73cd", +"#JX c #3a778a", +".F. c #3a78db", +"#NB c #3a7c9e", +".NJ c #3a81cf", +".JN c #3a88d3", +".FA c #3a8ae1", +"#iI c #3b3468", +".LC c #3b3539", +"Qtc c #3b3599", +"Qtm c #3b35b3", +"#pQ c #3b386d", +"#fK c #3b3aa2", +"#pO c #3b3c72", +"#eA c #3b3cb0", +".se c #3b3cd5", +"#Zg c #3b3d56", +".GV c #3b3f48", +"#mk c #3b3f6f", +"#C3 c #3b4060", +"#Fu c #3b4171", +".aD c #3b43c0", +"#dZ c #3b446d", +".9w c #3b46bc", +"#Ah c #3b488e", +"#h7 c #3b4b99", +"#hc c #3b4cb4", +".gC c #3b4cbe", +"#Tm c #3b4d61", +"##n c #3b4d95", +"#jF c #3b54a8", +"#cB c #3b55b6", +"#QL c #3b5647", +"#IS c #3b569d", +".uY c #3b56bf", +"#g# c #3b577e", +".YH c #3b57c2", +".3B c #3b57d2", +"#cv c #3b59c9", +"##5 c #3b59d1", +"#jI c #3b5aad", +".9L c #3b5bc2", +".9G c #3b5bc8", +".8s c #3b5bca", +"#TC c #3b5d4c", +"#bk c #3b5ed2", +".2q c #3b5ed4", +".uQ c #3b60c8", +".7O c #3b61c2", +"#03 c #3b6261", +".8D c #3b63ba", +".Wh c #3b64b6", +".AP c #3b65c7", +"#F7 c #3b669b", +"#JG c #3b675a", +"#1# c #3b6796", +"#YA c #3b6865", +".Wi c #3b68bb", +".As c #3b68cf", +"#0D c #3b693b", +"#TF c #3b6a4a", +"#F0 c #3b6b7f", +"#H. c #3b6b91", +".Z7 c #3b6bd7", +"#1c c #3b6ca6", +"#cD c #3b6d86", +"#Z0 c #3b6ea3", +".YU c #3b6ed7", +"#XB c #3b7686", +"#Mo c #3b76a2", +"#XA c #3b788b", +"#mc c #3b7988", +".6f c #3b79b4", +".0b c #3b7ac1", +".J5 c #3b80c5", +".Gg c #3b81e1", +"#0K c #3b8246", +".NL c #3b82d2", +".MF c #3b86d7", +".Y3 c #3c2039", +".#K c #3c27b2", +"#HU c #3c324d", +".eK c #3c32a5", +"#tl c #3c3970", +"#uz c #3c3d76", +"#X2 c #3c3e4b", +"##a c #3c3e6e", +"#eB c #3c3fb0", +"#et c #3c40a1", +"#Kw c #3c425a", +".fA c #3c44af", +".im c #3c44b3", +"#gT c #3c45a0", +"#fq c #3c477d", +".6z c #3c4ca1", +".pg c #3c4cbb", +".8f c #3c4fcf", +"##S c #3c4fd2", +"#ru c #3c508d", +"#Pa c #3c51a2", +"#sI c #3c528c", +"#eV c #3c54b6", +".c9 c #3c54be", +"#.b c #3c55a9", +"#jG c #3c56aa", +".aI c #3c57c8", +"#jH c #3c58ac", +"#KF c #3c5954", +".3C c #3c5ad6", +"#DA c #3c5b9c", +"#hk c #3c5bb6", +".9K c #3c5bc5", +"#Ym c #3c5d48", +"#.1 c #3c5dbe", +"#ab c #3c5ecc", +".54 c #3c5fd3", +".ZX c #3c60d0", +"#bl c #3c60d2", +"#Px c #3c6249", +"#pI c #3c6277", +"#jM c #3c62b7", +"#So c #3c6351", +"#yu c #3c638c", +"#T3 c #3c63a6", +"#VL c #3c644a", +"#Ig c #3c6463", +"#TB c #3c6547", +"#EM c #3c68a7", +"#0X c #3c694c", +".zg c #3c69c4", +"#PG c #3c6a50", +"#0H c #3c6b49", +".5q c #3c6bc3", +".MK c #3c6cd8", +".YR c #3c6cdb", +"#Nd c #3c6d69", +"#Nf c #3c6e53", +"#KY c #3c6f5e", +"#TX c #3c6fa8", +"#JL c #3c707e", +".zH c #3c70dd", +".0# c #3c71d1", +"#cE c #3c728a", +".Wp c #3c72bc", +"#14 c #3c7445", +"#V# c #3c769b", +"#PK c #3c775b", +"#md c #3c7787", +"#P7 c #3c77c3", +"#1Z c #3c794d", +"#OK c #3c7b5c", +".DZ c #3c7bdc", +".HK c #3c7cc4", +"#Wm c #3c7d9b", +".T1 c #3c7fc5", +".IT c #3c80c7", +".NI c #3c81ce", +".NK c #3c83d1", +".MG c #3c87d8", +".MH c #3c87da", +".K9 c #3c88c4", +".Ls c #3c89c1", +".Li c #3c8bc4", +".L# c #3c8dc5", +"#11 c #3c9345", +"#MS c #3d375d", +".#o c #3d3d9d", +"#Ur c #3d3e40", +"#C6 c #3d3f78", +"#AF c #3d4073", +"#BU c #3d4077", +"#jW c #3d4170", +"#BS c #3d4373", +"#HP c #3d444e", +"#Eh c #3d4979", +"#aS c #3d49b5", +"#Uu c #3d4a53", +".q5 c #3d4dbe", +".fu c #3d4fbf", +".eg c #3d50b9", +"#rt c #3d518e", +".3D c #3d51cc", +"#qQ c #3d53a8", +"#kT c #3d56a8", +".v2 c #3d59ba", +"#.o c #3d5ac0", +"#Qh c #3d5cb7", +"#.Y c #3d5cc8", +"##7 c #3d5cd0", +"##6 c #3d5cd1", +"#Uw c #3d5d52", +"#af c #3d5dc0", +"#.0 c #3d5dc2", +"#ae c #3d5dc4", +".9F c #3d5dca", +"##8 c #3d5dce", +"#WZ c #3d5e3f", +"#0z c #3d5e41", +"#.2 c #3d5ebd", +"#ad c #3d5ec7", +"#Rn c #3d5fcd", +"#xg c #3d6080", +".9Q c #3d60ba", +"#J5 c #3d61ab", +"#zW c #3d6274", +".2o c #3d62d7", +"#kY c #3d63b6", +".pr c #3d65c7", +".1# c #3d65d7", +".ZZ c #3d69d6", +".YP c #3d6bdb", +"#W0 c #3d6d3d", +".YS c #3d6ddc", +".uq c #3d6fc4", +"#Mv c #3d70db", +"#iD c #3d7187", +".9S c #3d7196", +".Hy c #3d72b4", +".Gk c #3d72ce", +".CR c #3d72d0", +"#1v c #3d7365", +"#Mt c #3d73c9", +".s. c #3d75c0", +"#dR c #3d7b90", +"#TS c #3d7ba2", +".zM c #3d7be2", +".JW c #3d7fcd", +".ME c #3d85d7", +".MD c #3d86d5", +".En c #3d87f0", +".Lm c #3d89c7", +".Lt c #3d8ac2", +".K2 c #3d8bd3", +".L. c #3d8cc5", +".K3 c #3d8fd8", +"Qtx c #3e20b4", +".aY c #3e2eb5", +"#Qr c #3e3c54", +"#yd c #3e3e72", +"#Fw c #3e3e7a", +"#gh c #3e3f7f", +"#C5 c #3e437a", +"#Pn c #3e4651", +"#lG c #3e468e", +"#Y# c #3e472a", +"#gB c #3e4a86", +"#Y8 c #3e4b54", +"#.F c #3e4dcc", +"#qf c #3e4e8c", +"#Un c #3e4f49", +"#a6 c #3e51d2", +".ph c #3e53c0", +".3E c #3e56d0", +"#iv c #3e59b2", +".82 c #3e59c0", +"#ck c #3e5ac7", +"#hj c #3e5bb7", +".uZ c #3e5bc3", +".7e c #3e5dd1", +"#.Z c #3e5ec5", +"#ac c #3e5ecb", +"#xf c #3e5f7e", +"#.3 c #3e5fbe", +".v0 c #3e60c4", +"#bm c #3e60ce", +"#2s c #3e619b", +"#wS c #3e6278", +"#W3 c #3e6341", +"#FV c #3e6390", +".vZ c #3e65c0", +"#UX c #3e6672", +"#1f c #3e679f", +"#zN c #3e688e", +"#T1 c #3e69b7", +".Wl c #3e6ac9", +"#YM c #3e6b95", +"#Sn c #3e6c45", +"#Vf c #3e6c9e", +"#Z2 c #3e6da3", +".Z5 c #3e6dd5", +".yy c #3e6ed4", +".Z8 c #3e6eda", +"#ai c #3e7093", +"#Mb c #3e7556", +"#Mc c #3e7862", +".qI c #3e79d7", +"#PY c #3e7a58", +".7r c #3e7ab0", +"#Or c #3e7d60", +".J6 c #3e81c7", +".NF c #3e83ce", +".NH c #3e83d0", +".MC c #3e85d5", +".Hq c #3e88df", +".Lr c #3e8bc3", +"#ON c #3e8e73", +".H1 c #3f3357", +"Qtl c #3f34b6", +".LA c #3f353d", +"#k7 c #3f3969", +"#Od c #3f3a51", +"#tm c #3f3a72", +"#I6 c #3f3e4c", +"#y# c #3f417e", +"#zq c #3f4373", +".xb c #3f449f", +"#jY c #3f4575", +".H5 c #3f464e", +"#Ei c #3f467c", +"#iL c #3f496c", +"#gS c #3f49a2", +"#gC c #3f4a8a", +".#Y c #3f4bd5", +".q7 c #3f4cce", +".9r c #3f4dc8", +"#Zh c #3f4f5c", +".8# c #3f519b", +"#Yi c #3f5646", +".9v c #3f57d3", +"#To c #3f585d", +"#Jp c #3f585f", +"#AY c #3f5881", +"#Tp c #3f595a", +"#kU c #3f59ad", +".qo c #3f59c8", +"#2u c #3f5a91", +"#Sk c #3f5b80", +"#f5 c #3f5bbe", +"#Du c #3f5d83", +"#iw c #3f5db5", +".2p c #3f5dd5", +".tN c #3f5ec8", +"#Sh c #3f5f47", +"#jJ c #3f5fb4", +".u0 c #3f5fc6", +"#bn c #3f5fcc", +"##9 c #3f5fce", +".aJ c #3f5fd6", +"#W6 c #3f604d", +".pk c #3f60c9", +"#Sg c #3f6140", +".5Z c #3f61dd", +"#ys c #3f6288", +".2n c #3f62d8", +"#iz c #3f63b9", +".4N c #3f65e0", +"#Xu c #3f6685", +"#SC c #3f66a9", +".4K c #3f66e7", +".tD c #3f68de", +"#0P c #3f6951", +"#Vc c #3f698f", +"#1U c #3f6a4e", +"#G9 c #3f6a97", +".x4 c #3f6ab9", +"#YP c #3f6b84", +"#.4 c #3f718c", +"#17 c #3f7249", +"#Mu c #3f73d6", +"#Q9 c #3f7446", +".YX c #3f75bb", +".yw c #3f76da", +"#P6 c #3f78c5", +".CT c #3f7ece", +".Mh c #3f80d0", +"#NC c #3f84a3", +"#U9 c #3f84a5", +".NG c #3f84cf", +".Gf c #3f84e3", +".K8 c #3f86c4", +".MB c #3f86d4", +".JM c #3f89d2", +".Ll c #3f8bc9", +".Le c #3f8fcc", +"#12 c #3f9b46", +".0i c #402627", +".mG c #4030c6", +"#MU c #403a60", +".Ew c #403e43", +"#zn c #404086", +"#GI c #404160", +"#BR c #404273", +"#q0 c #404378", +"#es c #4043a2", +".iV c #4045ba", +"#LN c #404757", +"#AE c #404775", +"#u9 c #404876", +".yq c #4048ad", +"#f. c #404970", +"#QE c #404c4c", +"#AR c #404e7b", +"#M0 c #405256", +"#Aj c #40529c", +"#is c #4054b3", +"#.7 c #40558c", +"#T7 c #4055ae", +"#sm c #405779", +"#ur c #405781", +".YF c #4057bf", +"#eU c #4058ba", +".8h c #4058d2", +".69 c #4058d4", +".7a c #405ad1", +"#02 c #405c72", +".xk c #405dc1", +"#Si c #405f57", +"#2t c #406099", +".u1 c #4060c7", +".9E c #4060cf", +".8r c #4060d1", +"#yq c #406182", +"#SQ c #406194", +"#bo c #4061ca", +".5Y c #4062e0", +"#Q4 c #40635d", +"#Dx c #406383", +".sy c #4064d4", +"#Hk c #40659c", +"#V2 c #406651", +"#jL c #4066bb", +"#Q1 c #40685f", +"#zR c #406995", +"#1T c #406b40", +"#e0 c #406b8d", +"#W. c #406c6f", +"#Wu c #406c8f", +".AW c #406ccf", +"#YL c #406d94", +".Wk c #406ecc", +"#0V c #406f4d", +"#pF c #407084", +".B7 c #4072d1", +"#PD c #40736a", +"#PF c #40736c", +"#Wp c #407489", +"#nm c #407585", +".yx c #4075db", +"#JN c #407887", +".tf c #4078d5", +"#Mq c #407aac", +"#k2 c #407f90", +"#PZ c #408360", +".SL c #4083d1", +".Md c #4087c9", +".MA c #4087d5", +".Lk c #408cc6", +".Kn c #413646", +"QtA c #413dc6", +"#MP c #413e53", +"#H0 c #413e69", +"#Qq c #413f55", +".Pb c #414045", +"#sa c #414278", +"#BV c #41437c", +".#q c #4143aa", +"#Jj c #414574", +"#VQ c #414659", +"#W5 c #41494b", +"#N4 c #414a6b", +"#cO c #414a71", +".pf c #414dbd", +"#rz c #414e85", +"#R1 c #415049", +"#yK c #415172", +".4n c #4152ac", +"#WO c #415357", +"#b7 c #4153b5", +"#Yj c #41564f", +"##x c #4156b3", +".pi c #4157c4", +"#b9 c #4159c5", +"#iu c #415ab4", +"#Dy c #415b80", +"#cC c #415bba", +"#Cd c #415c77", +".tO c #415dc8", +"#Xw c #415e9a", +"#hi c #415eba", +"#Jv c #416050", +"#VX c #416156", +"#qV c #41617a", +"#a. c #4161d0", +"#VW c #416259", +".zC c #4162b3", +".pl c #4162cb", +".tM c #4162cd", +"#JU c #416480", +"#A3 c #41648a", +".9R c #4164be", +".pm c #4164cc", +".53 c #4164da", +"#OC c #416a4a", +"#kZ c #416abc", +"#G6 c #416b81", +".Ar c #416ed5", +".qG c #4172cf", +"#2# c #41735a", +"#Z1 c #4173a8", +".Wj c #4175cb", +"#Y2 c #4176c2", +"#DD c #41778f", +"#Oo c #417b62", +".rY c #417dd3", +".F# c #417edb", +"#Yf c #418049", +".Mg c #4180d0", +".IU c #4184ca", +".Mi c #4184d3", +".TS c #4185d0", +"#1w c #418667", +".K0 c #4186c7", +".Mx c #4189d1", +".Mw c #418acf", +"#OM c #418d71", +".Lj c #418dc7", +".Qh c #418fcf", +".Qi c #4191d0", +".FB c #4191e8", +".7A c #422e5f", +".#N c #422fbd", +".GR c #42344b", +"#J# c #423b4d", +".Eu c #423c3c", +".Ev c #423d44", +".7t c #423d7f", +".n5 c #423eb6", +"#vP c #42437b", +"#e8 c #424384", +"#er c #4243a0", +"#cQ c #424475", +"#fM c #4244a9", +"#Td c #424848", +"#BT c #42487a", +"#N2 c #42495c", +"#zp c #424975", +"#XS c #424a5d", +"#Gr c #424a7b", +".mT c #424ac7", +"#QA c #424c58", +"#dg c #424cab", +"#fI c #424cae", +".8d c #424ec4", +"#ry c #424f86", +"#b5 c #4251b0", +".qm c #4252c3", +"##F c #4253c9", +".84 c #425496", +".4m c #4255b3", +"#Tg c #425654", +".9e c #4257b2", +"#EH c #425a88", +"#.B c #425ac4", +"#.r c #425ac6", +".7. c #425ad4", +"#IT c #425da2", +"#m# c #425dac", +".7P c #4261bc", +".7d c #4261d6", +".w# c #4262c9", +".9D c #4262d3", +"#TA c #426466", +"#GZ c #426579", +".52 c #4265db", +"#jK c #4266ba", +"#CF c #426794", +"#YH c #42686b", +"#K6 c #42687b", +".xn c #4268cb", +"#Yb c #426a48", +"#ZO c #426a6c", +".YK c #426bd4", +"#Sp c #426d52", +"#G7 c #426d8d", +"#UW c #426f6c", +"#TQ c #426f74", +"#Wz c #4270a4", +"#X. c #427266", +"#16 c #427353", +"#PC c #42756c", +"#Ha c #427590", +".t# c #4275c6", +"#hr c #42768b", +".ta c #4276c9", +".YV c #4276dc", +"#Xq c #427882", +"#2K c #427976", +"#gd c #427a8b", +".tc c #427ad1", +"#tc c #427ca1", +"#nl c #427d8b", +"#Zw c #427e48", +".NC c #427fd0", +".TR c #4284d0", +".Iz c #4286d1", +".Hp c #4286d9", +".Mz c #428ad4", +".Lq c #428dc4", +".Ml c #428eca", +".8O c #432656", +".6n c #432855", +".n4 c #4339b3", +"#ld c #433b6c", +"#MV c #433d5f", +"#sc c #433e76", +"#nv c #434172", +"#AD c #434284", +"#yc c #434576", +"#Kv c #434760", +"#fF c #4347a8", +"#ak c #434888", +"#yb c #434a76", +".8e c #4352d1", +"#dj c #4354bc", +"#O4 c #4357c8", +".YG c #4358c1", +"#FM c #43597e", +".7# c #435bd5", +"#2g c #435d6a", +"#it c #435db4", +".rl c #435dce", +".3s c #435fdd", +"#Tz c #436082", +".tK c #4361cf", +"#bp c #4363ca", +".8q c #4363d4", +"#CG c #436499", +"#yr c #436588", +".5X c #4365e3", +"#VZ c #43665f", +"#Ys c #436a4d", +".yz c #436dd3", +"#R. c #436f58", +"#zS c #436f96", +"#cI c #437099", +"#1e c #4370ab", +"#Nh c #437167", +"#PA c #43716e", +"#bs c #43718b", +".x5 c #4372c2", +"#Sz c #43739b", +"#F1 c #437580", +".qH c #4378d6", +".8E c #4379a7", +"#Ms c #4379c1", +".DY c #437ade", +"#ZD c #437b54", +".U8 c #437cd3", +"#cG c #437d95", +".46 c #4383c0", +"#Zu c #43844c", +"#P3 c #43867d", +".TT c #4388d3", +".Rv c #438bd3", +".Ln c #438cc1", +".Mt c #438cd0", +".Rw c #438dd4", +".Lp c #438ec5", +".Qj c #4392d4", +".O6 c #4392dd", +"##e c #442d63", +".Ko c #443647", +"#q3 c #444176", +"#fL c #4443ab", +"#qZ c #444573", +"#w2 c #444679", +"#.e c #4448a9", +"#w1 c #444a7a", +"#fG c #444aac", +"#zo c #444b75", +"#Ft c #444b77", +"#w0 c #444b79", +".oZ c #444bcd", +".qk c #444fb9", +"#ew c #4450b6", +"#wl c #44517d", +"#hT c #445281", +"#Ez c #445580", +".p9 c #4456d2", +"#dk c #4457c0", +"#co c #445ad1", +"#AV c #445b87", +".Xr c #445cbe", +"#FN c #445d7b", +"#k0 c #446183", +".u2 c #4461c9", +".tL c #4462d0", +"#GX c #446377", +"#wT c #44647b", +"#TH c #44696f", +"#bv c #446b94", +".Wu c #446bae", +".u6 c #446bc8", +".tC c #446be0", +".wR c #446dbc", +"#St c #446e6a", +".ze c #446fcb", +"#Wq c #447385", +".CQ c #4474d8", +"#Mj c #447a7a", +"#ah c #447a94", +"#W1 c #447b42", +"#ow c #447e8a", +".JX c #447fcd", +"#Op c #448064", +".ND c #4481d1", +"#Oq c #448366", +".zJ c #448aea", +".My c #448cd4", +".Lo c #448dc2", +".Mv c #448dd2", +".Rx c #448ed7", +".Y2 c #452346", +".eM c #4538a1", +"#dX c #454689", +"#l# c #454777", +"#oD c #45487b", +".n6 c #4548bd", +".n7 c #454abf", +"#k9 c #454b7b", +"#WD c #454f58", +"#QD c #455054", +"#rx c #45548d", +"#rw c #455590", +".eh c #4557bd", +"#R2 c #45585c", +"#f1 c #4559bc", +"#AS c #455b8d", +"#dB c #455bca", +".aS c #455be2", +"#TJ c #455d8d", +"#hh c #455fbc", +".Xq c #4561c2", +"#I# c #456574", +"#Sl c #45657e", +"#bw c #456598", +"#ix c #4565bc", +"#Rp c #4565ca", +"#CE c #456794", +"#Yu c #456a70", +"#yt c #456b92", +".YO c #456bd8", +".zf c #4570cc", +"#Wy c #4572ad", +".Gl c #4572c7", +".uL c #4573e3", +"#ox c #457486", +".BD c #4574d0", +"#M. c #45754d", +"#PI c #457a60", +".tb c #457bd1", +".CP c #457bdf", +"#PL c #457d60", +"#Wo c #457d96", +"#13 c #458145", +"#jP c #458295", +"#V. c #4585a8", +".Mj c #458ad8", +".Mq c #458bd1", +"#P0 c #458c6e", +".FC c #458de1", +".Mu c #458ed2", +".O5 c #4593dd", +".nQ c #4638c1", +"#LB c #464155", +".FL c #46454a", +"#WU c #46454d", +"#GL c #46457e", +"#ao c #464773", +"#jV c #464883", +"#hv c #464974", +".MN c #464a3c", +"#Ji c #464f78", +"##J c #4651ba", +"#a3 c #4654d7", +"#hd c #4655bc", +"#Ai c #46579f", +".mo c #4657c3", +".3x c #465ad3", +"#b8 c #465bc4", +"#O7 c #465bd8", +".3v c #465cc9", +"#E1 c #465d89", +"#eT c #465ec0", +".66 c #465ed8", +".3A c #465eda", +".9U c #466093", +"#hg c #4660bd", +".3t c #4660db", +".7b c #4661d6", +"#Z3 c #46639b", +"#DO c #46649a", +"#Xv c #466697", +"#bq c #4666cd", +"#W7 c #466858", +"#iy c #4668bf", +".50 c #4668e3", +".51 c #4669e1", +"#SD c #466ab4", +"#me c #466c83", +"#1n c #466c99", +"#Rr c #466cd9", +".YN c #466fdb", +".9T c #46719b", +".Aq c #4671d7", +"#td c #467390", +"#k1 c #46748e", +"#.5 c #467797", +".U3 c #467ac5", +"#2G c #467d84", +"#Lb c #467d9b", +".Mf c #4683d4", +".Eq c #4687e3", +"#NE c #468bb4", +".Ru c #468cd2", +".Mo c #468cd4", +".Mr c #468fd3", +".O4 c #4694de", +".Lh c #469ccd", +"##d c #473f7b", +"#mh c #474073", +"#fE c #4748a5", +"#HQ c #474a59", +"#ex c #4754bd", +"#.E c #4756cb", +".ry c #4758c4", +"#Uv c #475b5c", +"#bx c #475c9d", +"#VR c #475e58", +".tP c #475ec8", +"#AW c #475f8b", +"#AX c #476089", +".4I c #4760de", +"#eS c #4761c2", +".67 c #4761da", +".qp c #4763d1", +"#05 c #476460", +"#Cf c #476486", +"#aj c #476597", +".ZV c #4767d4", +"#CC c #476891", +"#Q3 c #47694e", +"#Q5 c #476973", +".07 c #4769d7", +"#Ia c #476a6e", +"#CD c #476a92", +"#zL c #476a94", +".pn c #476ad2", +"#Ib c #476c75", +".po c #476cd4", +"#Vi c #476dac", +".qs c #476dd8", +".AQ c #476dda", +".x2 c #476ebd", +"#Sm c #476f66", +"#e7 c #477090", +"#G8 c #47709c", +".pq c #4771d3", +".YL c #4772db", +"#K8 c #477582", +".4b c #4775c3", +"#Sq c #477751", +"#U2 c #477769", +"#Xa c #477960", +"#Wk c #477976", +".E8 c #477ee2", +".te c #477fdc", +"#OJ c #47805d", +".Nt c #4780cf", +".U7 c #4784d7", +".TQ c #4785d0", +".Ge c #4786e3", +"#Mf c #478874", +"#Mn c #47888a", +"#K4 c #478a9b", +".Mk c #478cda", +".Mn c #478dd2", +".Mm c #4791d0", +".Qg c #4793d1", +"#0M c #47974e", +".Lz c #484443", +"#LH c #48445f", +"#bF c #484572", +"#bA c #484a83", +"#pN c #484b80", +".mS c #484dcb", +"#vO c #484e80", +"#eu c #484eb0", +"#Vp c #485063", +"#nE c #485081", +"#ev c #4851b6", +"#RX c #48524a", +"#f4 c #4858b8", +"#gg c #485f81", +"#yp c #485f89", +".8p c #485fd3", +"#dC c #4860ce", +".3r c #4860dc", +"#Uz c #48625f", +".v9 c #4862c3", +"#VT c #486561", +"#Hl c #4866ac", +"#CB c #486891", +"#Mw c #486ec1", +"#SE c #4870b5", +".u7 c #4874d5", +"#bu c #487594", +"#TP c #487674", +"#W# c #487683", +"#mb c #48768d", +"#bt c #487791", +".qF c #4879d5", +".NU c #487ccf", +".ur c #487cd2", +".zN c #487de3", +"#18 c #488051", +".FD c #4882cb", +".rX c #4882d6", +"#dU c #4884a0", +".TV c #4885c8", +".SG c #4888d2", +".1p c #4889c9", +".K7 c #488ccb", +".SC c #488dd0", +".Rt c #488ed4", +".O3 c #4895dd", +".Y4 c #493443", +".RF c #493f48", +"#q5 c #494075", +"Qtd c #4941a8", +"#j1 c #494275", +"#zr c #494b7e", +"#QF c #495352", +"#jX c #495376", +".xd c #495591", +".8c c #4955bb", +".el c #4956be", +"#f3 c #4959bb", +"##Y c #495ed1", +".qn c #4960d0", +".xl c #4961c3", +".6C c #4962c6", +".7c c #4964d9", +"#Ro c #4967c9", +".2m c #4967df", +"#1P c #496942", +"#VO c #49695a", +".v3 c #496acb", +".wa c #496ad1", +"#Q6 c #496f7a", +"#1u c #497077", +"#0C c #497248", +"#Ni c #497371", +"#k4 c #497389", +"#ag c #49798f", +"#Ss c #497a5d", +"#Sw c #497d8b", +"#PX c #497f5d", +".Va c #4980c1", +"#Mr c #4981bc", +".Ns c #4981ce", +"#iE c #498295", +".NB c #4983d5", +"#P9 c #4984bc", +"#Wn c #4986a2", +"#k3 c #498796", +".SF c #4989d3", +".SK c #498cda", +"#P1 c #498e79", +"#Mg c #498e7c", +".Mp c #498fd7", +".FH c #4a403f", +"#pR c #4a4176", +".Kr c #4a454c", +"#Oe c #4a475a", +"#tk c #4a4982", +"#RG c #4a4b50", +"#MK c #4a4b5d", +"#AG c #4a4b81", +".iU c #4a4fc4", +".aC c #4a50ca", +"#ya c #4a517b", +".pe c #4a51c3", +".#Z c #4a55e3", +"#oP c #4a5686", +"#Ew c #4a568a", +"#he c #4a57bd", +"#EF c #4a5c8c", +"#f2 c #4a5cbe", +".3z c #4a5edb", +".9C c #4a61d5", +"#Yl c #4a635f", +"#Sv c #4a678f", +"#ma c #4a6986", +"#Ch c #4a6a91", +"#Su c #4a6d83", +"#SP c #4a6dad", +"#Ck c #4a6e90", +".8F c #4a6ea2", +".pp c #4a6fd7", +"#PQ c #4a716c", +".vF c #4a74c6", +"#M# c #4a7a60", +"#EO c #4a7a90", +"#F8 c #4a7aaa", +"#Q8 c #4a7b5d", +"#PM c #4a8162", +"#P5 c #4a81c4", +".E7 c #4a81e5", +"#Xr c #4a8283", +"#cF c #4a8299", +".Nu c #4a83d2", +".Me c #4a84d6", +".CS c #4a86dc", +".TU c #4a87ca", +".NE c #4a88d5", +"#jQ c #4a8b9d", +"#OR c #4a8ba9", +".SB c #4a8ecf", +".zL c #4a8ef3", +".Mc c #4a8fd0", +".JL c #4a90d6", +"#L. c #4a9195", +".SD c #4a91d3", +".O2 c #4a94db", +".Qf c #4a96d4", +"#Nx c #4a997a", +"#q4 c #4b447a", +"#hC c #4b467c", +"#LI c #4b4863", +".pd c #4b4ec1", +"#mj c #4b5181", +"#c8 c #4b5298", +".rv c #4b55ce", +".rw c #4b56cc", +".9i c #4b58b4", +"#LR c #4b5a5f", +".9z c #4b5acf", +"#yo c #4b5b7d", +"#.C c #4b5bbd", +".tQ c #4b5cc6", +".3y c #4b5dd9", +".T2 c #4b5ec4", +".3w c #4b5fd8", +"#Tq c #4b6061", +"#vH c #4b6281", +"#1Q c #4b6750", +".Xt c #4b67c8", +"#Ce c #4b6886", +".2l c #4b68de", +"#Qg c #4b69ed", +".T3 c #4b6ec0", +"#DB c #4b6fc7", +".wc c #4b71d6", +"#Xg c #4b754f", +"#.6 c #4b759f", +"#Wf c #4b767f", +"#ou c #4b7689", +".YM c #4b76df", +"#TN c #4b7979", +".up c #4b7bcf", +"#It c #4b7c80", +"#Cr c #4b7c9a", +".Df c #4b7cd9", +".AX c #4b7ddc", +"#ov c #4b7f8d", +"#Xs c #4b7f94", +"#P4 c #4b7fb8", +"#PN c #4b815f", +"#Nv c #4b8262", +".Vf c #4b82d5", +".Wr c #4b83d0", +".TP c #4b84d1", +".BF c #4b86d6", +".U6 c #4b88d8", +".TW c #4b8acd", +"#oG c #4c487b", +"#Ef c #4c4a71", +".pc c #4c4bc0", +"#Jg c #4c5076", +".9V c #4c528e", +"#WC c #4c5662", +"#QI c #4c5751", +".9x c #4c57cd", +".tR c #4c58c4", +".q. c #4c58d2", +".8i c #4c5ad4", +"#.l c #4c5fae", +"#EG c #4c6198", +".3u c #4c63d5", +"#Pv c #4c6456", +"#Dq c #4c647e", +".u3 c #4c64ce", +".68 c #4c64e0", +"#Tx c #4c6876", +".7s c #4c69a5", +".ZW c #4c6cd9", +"#IF c #4c6d90", +".ZS c #4c6dd6", +"#1N c #4c6e55", +"#04 c #4c6e6d", +"#zK c #4c6f97", +".wd c #4c6fd5", +"#Rq c #4c6fd7", +"#Qc c #4c70e0", +"#1g c #4c71a8", +".xo c #4c72d5", +".qt c #4c75df", +"#Wv c #4c76a6", +"#OB c #4c7a3a", +"#Rf c #4c7b8d", +"#2C c #4c7bc1", +"#FZ c #4c7d8c", +"#EN c #4c808e", +"#K5 c #4c8096", +".zi c #4c80d4", +".TO c #4c81cd", +".CO c #4c82e2", +".E6 c #4c82e6", +".U9 c #4c84db", +"#Yp c #4c8564", +"#P8 c #4c89c8", +".K4 c #4c89cc", +".Ho c #4c89da", +"#2. c #4c8a65", +"#Nw c #4c8a7b", +"#OQ c #4c8b9d", +".SE c #4c8cd4", +".SH c #4c8ed8", +"#Nz c #4c9085", +".Qe c #4c98d4", +"#HW c #4d455c", +"#HV c #4d455d", +"#MW c #4d4964", +"#.f c #4d5198", +".tT c #4d5aca", +".8j c #4d5bd5", +"#.L c #4d5cd1", +".tU c #4d5dcc", +"##I c #4d5ec6", +".rz c #4d60c6", +".xm c #4d61c2", +".rm c #4d61d2", +"#EA c #4d627d", +".8o c #4d64d8", +"#pE c #4d65bb", +".4H c #4d65df", +".6g c #4d66a8", +".ZR c #4d69d4", +".sz c #4d69d7", +".ZU c #4d6fda", +"#Ti c #4d705c", +".wb c #4d70d6", +".x1 c #4d72c2", +"#Yt c #4d7654", +".vY c #4d7acf", +"#Ve c #4d7bac", +"#XG c #4d7d71", +"#nk c #4d7e8f", +"#Sr c #4d7f59", +"#Re c #4d8084", +"#PJ c #4d856c", +".Nr c #4d85d2", +"#Ox c #4d8666", +".UX c #4d88d4", +"#Os c #4d8c6f", +"#P2 c #4d9182", +".Rs c #4d92d7", +".Rp c #4d95d0", +".Y7 c #4e2045", +".Wz c #4e3b69", +"#at c #4e3f78", +".mH c #4e3fd0", +"#oI c #4e4679", +"#nq c #4e467f", +"#sd c #4e477d", +"#MO c #4e4862", +".o0 c #4e49c9", +"#pM c #4e4b80", +"#Ek c #4e4d89", +".mR c #4e4dcd", +"#LJ c #4e4e66", +"#jZ c #4e4f87", +"#ns c #4e5184", +"#aY c #4e51c2", +"#Pe c #4e5275", +".NZ c #4e5452", +"#mv c #4e5484", +"#Pm c #4e5663", +"#fH c #4e56b9", +"#H5 c #4e5792", +"#zC c #4e5d86", +".ty c #4e5ee5", +".65 c #4e62dd", +"#VS c #4e6763", +".9# c #4e68bf", +".YE c #4e69d0", +"#Jq c #4e6e69", +"#0B c #4e6f5a", +"#LW c #4e715b", +".Vh c #4e71b5", +"#Qd c #4e71e7", +"#nj c #4e728a", +".yA c #4e72d3", +"#2F c #4e7a93", +"#Wt c #4e7a95", +"#Yn c #4e7c58", +"#0f c #4e7d9b", +".t. c #4e7dcd", +"#PS c #4e7e66", +"#hs c #4e7e92", +"#YY c #4e86ab", +".Gd c #4e86dd", +".td c #4e87de", +".UY c #4e8cd9", +"#Np c #4e8d58", +"#ND c #4e93b4", +".Rq c #4e96d1", +".Qd c #4e98d5", +".n3 c #4f3fbb", +"#nx c #4f477a", +"#oH c #4f487b", +"#oB c #4f4a84", +"#ML c #4f4d62", +"#X9 c #4f4f35", +"##L c #4f53be", +"#uy c #4f548b", +"#oC c #4f5587", +"#li c #4f5684", +".rx c #4f5cce", +"#Tf c #4f5d60", +"#zD c #4f6596", +".ZQ c #4f67d3", +"#Jr c #4f696a", +".2k c #4f69e0", +".zd c #4f6dcf", +".Wv c #4f6ea5", +".ZT c #4f70db", +"#Qf c #4f70f1", +"#A1 c #4f7290", +"#1t c #4f7383", +"#Wx c #4f78b6", +".Wd c #4f79cf", +"#Q7 c #4f7a73", +"#br c #4f7b96", +"#NA c #4f7bac", +".BC c #4f7bde", +".uo c #4f7ece", +"#Ol c #4f806d", +".TN c #4f80cd", +".DX c #4f80e7", +"#Ra c #4f865f", +".A1 c #4f88cb", +".Nv c #4f88d9", +".3R c #4f91ce", +".Ro c #4f95d0", +"#mo c #504a7a", +"#GM c #504e8f", +"#GN c #504f93", +"#H1 c #505084", +"#H4 c #505493", +"#U. c #505558", +"#vZ c #505662", +"#fj c #505783", +".Et c #505968", +"#gj c #505980", +".ql c #505dcd", +"#hf c #505ec1", +".9q c #505ec9", +".9d c #5066bc", +"#E. c #506775", +"#FJ c #50688e", +"#A0 c #506c94", +".zD c #5072cb", +".qr c #5072de", +".Ap c #5076d7", +"#Ux c #507764", +"#XJ c #507b9b", +"#T2 c #507bc0", +"#Xt c #508096", +"#PW c #508163", +"#2B c #5083c4", +".V# c #5083d6", +"#jR c #50869e", +".AY c #5087da", +".NV c #5087e4", +".SA c #508fd2", +".RH c #51152e", +".0l c #512443", +"#iS c #512a3f", +"##f c #513565", +"#se c #51487f", +"#lc c #514b7b", +".FG c #514f5c", +"#Fx c #514f90", +"#Tc c #515554", +"#l. c #515585", +"#Jh c #515882", +".8L c #515988", +"#ft c #515ba3", +".9j c #515bb0", +"#.A c #515fc0", +".9Z c #516194", +".9n c #5167bc", +".YB c #5167cc", +".w. c #516ac7", +"#Zm c #516b48", +"#Ty c #516b90", +"#YR c #516e72", +"#Cg c #516f95", +"#J7 c #516fb8", +"#TI c #51708d", +".GO c #5171ae", +"#1O c #51744c", +"#1o c #517597", +"#Vd c #51789f", +"#PR c #517978", +".U1 c #5179d0", +"#Nk c #517d6c", +".U0 c #5180d2", +".E5 c #5183e4", +"#K9 c #518c9c", +"#0g c #518cae", +".Iy c #5191d9", +".K6 c #5192d4", +".Rr c #5196db", +"#OL c #51987a", +"#OP c #51a184", +"#aE c #522777", +"Qtv c #522cb3", +"#aH c #523762", +"#pS c #52487d", +".mQ c #524bcd", +"#am c #525491", +"#bT c #525a99", +"#fl c #525b92", +"#ei c #525b9c", +"#M1 c #525c5e", +"#by c #5260a7", +"#a2 c #5260e5", +".YA c #5261c8", +".u4 c #5264d0", +"#rv c #5265a0", +"#B6 c #52689a", +".sK c #526dd6", +".yB c #5270d2", +"#J6 c #5272bb", +".we c #5272d9", +"#cJ c #5276aa", +"#Uy c #527766", +".xp c #527ada", +"#TR c #527e87", +"#TO c #52807d", +"#R# c #528365", +".V. c #5283e2", +".Nw c #528bdc", +"#e5 c #528ca0", +".O8 c #528ccc", +".K5 c #528fd2", +".T0 c #5292d9", +".SJ c #5296e1", +"#Nq c #529754", +".2E c #5298cc", +".O1 c #529ae4", +"#Mm c #529c8d", +"#0L c #529f5b", +".6o c #53335c", +"#Lz c #534a65", +"#ye c #534f82", +".sE c #534fc7", +"#Pq c #535562", +"#N0 c #535665", +"#gu c #53568d", +"#k8 c #535989", +"#Pl c #535b68", +"#hy c #535d81", +"#Ex c #535e94", +".8a c #535fa9", +"#.D c #5361ca", +"#B8 c #536394", +"#B7 c #536396", +".u5 c #5364d0", +".ys c #5369b2", +".5W c #536de8", +".sL c #536ed5", +".Xp c #5374d1", +".FE c #537ab3", +"#Xc c #537b73", +"#U3 c #53806c", +"#M9 c #53836b", +"#Ov c #538466", +"#iF c #53859c", +".Er c #5388ce", +".Nq c #538ac3", +"#Rd c #538c7d", +".SI c #5395e1", +".zK c #5399fb", +".O0 c #539be5", +".Qc c #539ddc", +".nR c #5443cd", +"#fe c #544473", +".6h c #54488a", +"#nw c #544d80", +"#mn c #545082", +"#Lx c #545365", +".qj c #5459bf", +"#aZ c #5459cf", +".Ez c #545c69", +"#bR c #545c9b", +".tS c #545cc7", +".9h c #545fb9", +".9y c #5460d6", +"#aV c #5461c7", +".q6 c #5463d8", +"#rb c #54678f", +".9A c #5468db", +".T4 c #5469aa", +"#2v c #546a9c", +".2i c #546fe4", +"#Oi c #547061", +".qq c #5472e0", +"#Tj c #547665", +"#Qe c #5476f2", +"#0. c #5477a1", +".SP c #5477d1", +"#PP c #547b5c", +"#Wr c #547f8f", +".SO c #5480df", +".Wc c #5482d7", +".TM c #5483d1", +".rD c #5483d3", +".qE c #5487e0", +"#JI c #54896b", +"#Ow c #54896d", +".NW c #5489e5", +".IF c #548bcc", +"#K1 c #548c9d", +".Nx c #548cdf", +".Sy c #548dd0", +"#Rb c #548e66", +".Sz c #548fd1", +".Qb c #549bdb", +".Ms c #549edf", +".mI c #5544d0", +"#tn c #554e84", +"#lb c #555281", +"#Of c #555462", +".#p c #5558b9", +"##K c #555ac0", +"#pZ c #556692", +"##W c #5566d8", +".8l c #5568de", +"#ED c #556970", +".5V c #556de7", +".9. c #556ec8", +".2j c #5570e5", +"#VY c #557367", +"#FO c #557488", +"#VU c #557570", +".4# c #5575d8", +".06 c #5575e4", +"#x4 c #55798f", +"#Q2 c #557a4e", +".xq c #557cdb", +".qu c #557ee8", +".u8 c #5580df", +"#2a c #558180", +"#1r c #55819a", +".s9 c #5583d1", +".BB c #5583e1", +".O7 c #5585cd", +"#KZ c #558b71", +".UZ c #558cdc", +".NA c #558dda", +".BE c #558de0", +"#PV c #55915e", +".Rn c #5597d3", +".OZ c #559ae5", +".2N c #562e46", +".MQ c #564148", +"#X3 c #564e65", +".pb c #5653c8", +".FM c #56555d", +"#LO c #565769", +"#NZ c #565968", +"#T8 c #565c50", +"#Te c #565c5c", +"#Zi c #566663", +"#WP c #56686a", +".8m c #5669df", +".rC c #566fc9", +"#Dt c #567095", +"#1M c #56716c", +"#Tv c #56765f", +"#UN c #567675", +"#UL c #567766", +"#UM c #567868", +"#YU c #567882", +"#YD c #567972", +".CN c #567cdd", +"#CW c #56808e", +".Jy c #568bcd", +".rW c #568ce2", +".Ve c #568ed8", +"#Me c #569582", +".OY c #569ae3", +".Qa c #569bdc", +".0h c #573448", +".0g c #573455", +".Ks c #573f4c", +"#zs c #575587", +".Vm c #575789", +"#Lw c #575968", +"#N1 c #575d6d", +"#nr c #575d8f", +".ru c #575fc1", +"#WQ c #57616b", +".RN c #576192", +".63 c #5763d3", +"#.J c #5764d7", +"#VP c #57666b", +"#an c #57669d", +"#Hm c #576da6", +".rB c #5770cc", +"#Tw c #57776c", +"#A2 c #577a9a", +".JR c #577fba", +"#2b c #578278", +"#1s c #578295", +"#ge c #57869a", +".U2 c #5787d1", +".UW c #578ad9", +".qD c #578ae3", +"#YZ c #578bb3", +".Ny c #578ed1", +".Nz c #5790d7", +"#Md c #579679", +".OX c #579be4", +"#OO c #57a78c", +".mL c #5847cb", +".Vl c #584f7a", +"#mp c #585081", +"#w4 c #585187", +"#iQ c #585282", +".Ex c #58585a", +"#.8 c #585898", +"#.g c #58598f", +"#SW c #585a55", +"#mi c #585e90", +"#QG c #586160", +".8k c #5868e1", +"#Ca c #586994", +"#Ds c #587092", +"#pD c #5870c6", +".XK c #5873a8", +"#G1 c #587583", +"#Tu c #587863", +".6D c #5878cf", +"#Vk c #587bbf", +".wP c #587dc4", +"#Vj c #587ebf", +".vE c #5881d0", +"#Pz c #588281", +"#e6 c #5887a1", +".rE c #5887d5", +"#dV c #5888ac", +"#He c #588a91", +".Sx c #588dd1", +"#XD c #588e90", +"#On c #588f78", +".U4 c #5890db", +".O9 c #5894ca", +".Rm c #5899d3", +".30 c #592943", +".32 c #592d3c", +"#lf c #594a83", +".aZ c #594cda", +"#q6 c #594f84", +"#al c #595295", +"#Ly c #59546b", +"#C8 c #595b94", +"#FI c #596891", +".FF c #59698b", +".Xs c #596dd0", +".sA c #596edb", +"#FK c #597099", +"#JR c #597291", +".2h c #5974e9", +".YC c #5975d9", +"#nn c #597894", +".xr c #597bdc", +".We c #597cd6", +"#Ww c #5983bd", +"#Nj c #59847b", +"#dW c #5984ae", +".Gc c #5989dd", +"#Sx c #598ca1", +".A2 c #598cdd", +".A0 c #5995d4", +"#Mk c #599c93", +".OW c #599ce3", +".Q# c #599ddc", +".Pd c #5a2537", +"Qtw c #5a27c2", +".LD c #5a4a54", +".mP c #5a4acf", +"#J. c #5a4e66", +"#d2 c #5a5c8d", +"#H2 c #5a5c95", +".sJ c #5a5cc0", +".8b c #5a64bb", +".64 c #5a68e2", +".8n c #5a6fe4", +".rA c #5a71d1", +"#AZ c #5a739c", +".zc c #5a74d5", +".05 c #5a78e8", +"#2E c #5a7caa", +".ML c #5a7cc4", +"#1m c #5a83b9", +"#Ou c #5a8663", +".s8 c #5a88d5", +"#Ip c #5a8e99", +".AZ c #5a92dc", +".U5 c #5a95e1", +".OV c #5a9de4", +".mJ c #5b49d3", +"#HT c #5b516c", +".WA c #5b5386", +".GW c #5b565d", +"#cR c #5b5885", +"#AH c #5b5b8f", +".Qz c #5b5d84", +"#KD c #5b6475", +"#Dk c #5b6799", +".MM c #5b6c7e", +"#Cc c #5b6d95", +".3b c #5b6fd0", +".4G c #5b6fe2", +".9B c #5b70e5", +".ZP c #5b72dc", +".47 c #5b74b6", +"#1p c #5b77a7", +".YD c #5b78dc", +".Ao c #5b7ad7", +".Es c #5b7ba4", +".E4 c #5b86e2", +".zO c #5b8bef", +".Ju c #5b8cd1", +".rU c #5b8de2", +"#PT c #5b9366", +".Hn c #5b94e3", +".Rl c #5b97d3", +".TX c #5b9adf", +".Mb c #5b9dda", +".JK c #5b9ee2", +".5f c #5c2737", +".1z c #5c2f46", +".#L c #5c36c1", +"#to c #5c5189", +"#.9 c #5c5598", +".Di c #5c5976", +"#Kz c #5c5c7e", +".Ey c #5c5f64", +"#H3 c #5c609d", +"#d1 c #5c6391", +"#Pj c #5c656c", +"#O5 c #5c6de1", +".4l c #5c6ed0", +".wf c #5c74de", +".sM c #5c7adc", +"#0A c #5c7b69", +"#Vl c #5c7ec5", +".wO c #5c7fc3", +".yC c #5c7fd9", +".DW c #5c80e1", +"#V3 c #5c8170", +"#1q c #5c82a6", +"#0b c #5c86b0", +"#Yg c #5c9261", +".Jz c #5c92d2", +".qC c #5c94df", +"#La c #5c96ae", +"#Rc c #5c9777", +".KZ c #5c9ad3", +".1x c #5d2b50", +".5d c #5d3152", +".2L c #5d3243", +".1w c #5d3a40", +".LE c #5d3c47", +".sF c #5d4cb4", +"#sf c #5d5388", +"#LA c #5d556d", +"#hB c #5d5e94", +"#QH c #5d6663", +".Ly c #5d687a", +"#eg c #5d6a96", +"#B5 c #5d6b9a", +"#.w c #5d6dcf", +"##X c #5d6ee2", +"#FL c #5d739a", +"#r7 c #5d7694", +"#GW c #5d7895", +"#0# c #5d7aa2", +"#Z4 c #5d7cab", +".Wg c #5d81d5", +"#JF c #5d887f", +"#JK c #5d9385", +"#PU c #5d9764", +".OU c #5d9de5", +".Re c #5d9ed6", +".Q. c #5d9ede", +"#Ml c #5daa96", +"#L# c #5dab9d", +".7B c #5e345c", +".n2 c #5e48c6", +".Jg c #5e4d53", +".o1 c #5e4eca", +"#uB c #5e5491", +"#zt c #5e5b8a", +".9g c #5e64ba", +"#.x c #5e68c7", +"#Dl c #5e6a9a", +"##H c #5e6ace", +"#xy c #5e6c89", +".9o c #5e6dbe", +"#B9 c #5e6e9f", +"#Tr c #5e6f76", +"#EY c #5e6f8b", +".3q c #5e6fe1", +"##w c #5e70ae", +".Na c #5e7295", +"#JT c #5e767a", +"#Dr c #5e7893", +"#gf c #5e7d9a", +"#KJ c #5e7e66", +"#0e c #5e819d", +".tA c #5e81e5", +"#G. c #5e82a4", +"#0a c #5e83ad", +"#Ot c #5e8661", +".Ce c #5e86db", +".um c #5e88d0", +".TH c #5e89d8", +"#U4 c #5e8a7d", +"#JO c #5e8fc7", +".Jx c #5e91d3", +"#Ma c #5e926c", +".Rk c #5e99d5", +".Rf c #5e9fd7", +"#j3 c #5f3656", +".93 c #5f3f70", +".XO c #5f436c", +"##q c #5f479d", +"#tp c #5f528a", +"#MN c #5f5671", +".H6 c #5f5a61", +"#Pc c #5f617a", +"#WR c #5f6772", +".62 c #5f67cc", +"#T# c #5f6c63", +".Xn c #5f6dce", +".5U c #5f74eb", +"#Dh c #5f75a7", +".9c c #5f78cc", +".Lx c #5f7fb8", +".un c #5f8bd6", +".rF c #5f8fd9", +"#Yo c #5f9571", +"#Ri c #5f95c4", +"#Zv c #5f9e67", +".P9 c #5f9fdd", +".U# c #602845", +".2M c #602a4e", +".mO c #604ad1", +"##g c #604d7b", +".48 c #605192", +"#GO c #605fa5", +".tV c #6063c4", +"#H6 c #6068a7", +"#Uo c #606b67", +".3c c #606dcd", +".sB c #606ddd", +".5r c #6072c6", +".Nb c #60769f", +".wg c #6077e1", +".x0 c #607ad1", +"#ht c #60829d", +".DV c #6084e5", +"#FP c #60858e", +".qv c #6089d9", +"#U7 c #608e9b", +".qy c #608fdd", +"#Om c #609380", +".Wq c #6096de", +".qB c #6098e3", +".Rg c #609bd3", +"#hG c #61292c", +".XP c #614f77", +"#bG c #615d82", +"#GP c #6160a6", +".q# c #6163da", +"#UA c #616d7b", +"#.K c #616ee1", +"### c #6171a5", +"#.k c #6172aa", +".2g c #6173e1", +"#.t c #6178ea", +".Xo c #617ad7", +"#UO c #617e8e", +".Hw c #617ecc", +".04 c #617fed", +".sN c #6180dd", +"#VV c #61847e", +".TI c #6186d4", +"#VN c #618e71", +"#XF c #61938a", +".St c #6198db", +".5c c #623458", +"#LP c #626171", +"#iO c #62639b", +".RO c #626494", +"#GQ c #6265ac", +"#Pk c #626a75", +"#gD c #626eaa", +"#Jo c #62708b", +".4o c #6274ca", +"#sH c #627ab6", +".Ne c #627ba3", +".TJ c #627cc6", +".3# c #6282d9", +"#1. c #6285a1", +".yD c #6286de", +"#Aw c #6287a4", +"#Py c #628a8c", +"#G3 c #628a92", +"#2D c #628ac5", +".Ix c #6296d2", +".qz c #6296e2", +".Rd c #629fd6", +".XT c #633157", +".1y c #633c57", +".mN c #6347d0", +".mK c #6351d7", +".Pk c #635a79", +".GQ c #635b80", +"#Pr c #636571", +".8K c #636699", +"#GR c #6367b0", +".ZN c #636cd5", +"#gF c #636db4", +"#Dn c #63709a", +"#hu c #637397", +"#b6 c #6373d2", +"#cK c #6380ba", +"#Ba c #63858f", +".SN c #6389de", +".wQ c #638ad5", +".Wb c #6390e3", +"#Sy c #6394b4", +"#Mi c #63968f", +".Rj c #639bd6", +".P6 c #639ddc", +".P8 c #63a0df", +".N2 c #643e49", +"#uC c #645492", +"#X4 c #645a7d", +"#vR c #645a96", +"Qti c #645dc4", +".Qq c #64606f", +"#zm c #6461a4", +"##G c #646ac8", +"#aU c #646aca", +".60 c #646bbc", +".Yz c #646fd8", +"#Dj c #6471a5", +".9p c #6471cd", +"#.v c #6471cf", +".N# c #647591", +".4F c #6475e1", +".HZ c #6478ab", +"#CX c #647a85", +".Nd c #647aa3", +"#Ax c #647c98", +".6E c #647dd7", +".Vg c #647ed3", +"#x5 c #648096", +"#Z8 c #6481b9", +".If c #6482ca", +".u9 c #6483d6", +"#jS c #6485a8", +".E3 c #6486dd", +".ul c #648cd2", +".zP c #648ef0", +"#Y0 c #6491ba", +"#Y1 c #6492c4", +"#Xb c #649577", +".Rh c #6497ce", +"#YX c #6498ae", +".rV c #6498ec", +".Ss c #6499dd", +".JA c #649bdb", +"#K2 c #64a19a", +".P7 c #64a1e0", +".1v c #653954", +".31 c #653a4e", +".mM c #6546d0", +".3T c #655795", +"#y. c #656297", +".Km c #656b81", +"#iH c #656c9a", +"#jT c #656d9e", +"#gk c #656f93", +"#O6 c #6578ff", +".2f c #6579ea", +"#M4 c #657b78", +".ED c #657bc6", +".Xl c #657cda", +"#EB c #657d89", +".xs c #6581e2", +"#0d c #6586a5", +".DU c #6586e5", +".wh c #658de2", +".TG c #658fe3", +"#JH c #659879", +"#Oy c #659e7b", +".2P c #662939", +".5b c #662c52", +".7v c #66578e", +".ST c #665872", +"#hD c #66608e", +"#wY c #666189", +"#HR c #666378", +"#Jk c #66689b", +".Ja c #66698a", +".ZM c #666fce", +"#C. c #6677a5", +"#IE c #66787a", +".2e c #667bf0", +"#I. c #667d9f", +".BA c #6680dd", +".uk c #668dd2", +"#PO c #668f57", +".Jt c #6690d8", +".qx c #6694e2", +"#VM c #669573", +".rT c #6696ea", +".Jv c #6697da", +"#Ir c #669988", +".Np c #669bd1", +".qA c #669be7", +"#OA c #66a070", +"#Nu c #66a36a", +".94 c #67395e", +"#Kn c #675e73", +"#I7 c #675f74", +".sD c #675fd8", +".9X c #67619f", +"#j0 c #67629a", +"#bz c #6767ad", +"#Uq c #67686a", +".6V c #676ab7", +".9Y c #676ca4", +"##. c #676ca6", +"#RI c #676e5e", +".8. c #676eb2", +".QA c #677494", +"#Zj c #67776d", +".2c c #6778ea", +".9f c #677bda", +"#zY c #678084", +"#iG c #6785a7", +".yE c #678be1", +"#zg c #678ca7", +".Js c #678fd4", +".rS c #6794e5", +"#F3 c #6798a9", +"#F4 c #6799a4", +".rG c #6799de", +"#Iu c #679a9d", +"#Cs c #679ab9", +".Su c #679adb", +".Iw c #679bd5", +".OT c #67a0ed", +".TZ c #67a7ee", +".P3 c #67a8e8", +".2K c #68365c", +".5e c #683a54", +".6p c #683b5a", +".95 c #683d5b", +".o2 c #684fc7", +"#d9 c #685b6f", +".8H c #685d9f", +"#AI c #68689a", +"#bH c #686995", +".0I c #6871bc", +"#Ts c #68727e", +".6U c #6872c7", +".4E c #6873dc", +".76 c #6874ca", +"#Cb c #687aa2", +"#wU c #687d92", +".An c #687dd6", +".Ie c #6880ca", +".s7 c #6885d5", +"#UK c #68887b", +".UV c #688edf", +"#0c c #6890b4", +".A4 c #6891fd", +".qw c #6893e2", +"#Hc c #689a99", +".Jw c #689bdd", +".JB c #689fdf", +"#Rg c #68a2a3", +".OS c #68a3ef", +".OR c #68a3f1", +".P5 c #68a4e3", +".P4 c #68a8e8", +"#hF c #69414c", +"#iR c #695578", +"#uD c #695791", +"#AC c #6968ac", +"#UB c #696d86", +"#RL c #697078", +".77 c #6970be", +".Xm c #6973d5", +".0H c #6974c4", +".5S c #6974e0", +".5T c #6979ea", +"#E# c #697b8f", +".2Y c #697bc5", +".CM c #697bdf", +".2Z c #697dd3", +".zb c #697ddc", +".SM c #6987cd", +"#M8 c #698878", +"#Z9 c #6989bc", +".Ii c #6990d5", +".Ri c #6996cd", +".rR c #6996e7", +"#Hd c #69a282", +".TY c #69aaee", +".6i c #6a528e", +".8I c #6a5e9c", +"#MM c #6a647e", +".9W c #6a64a4", +"#Tt c #6a6f82", +"#.u c #6a6fca", +"#gl c #6a719f", +".6T c #6a72c7", +"#Qv c #6a756f", +"#Dp c #6a789f", +".SQ c #6a7bc1", +"#W4 c #6a7e72", +".2d c #6a7ff4", +".xZ c #6a80d5", +".7Q c #6a82cc", +".3a c #6a84e1", +".wN c #6a8dd1", +".Jr c #6a8ec8", +"#U6 c #6a969f", +".rQ c #6a99e7", +"#Rh c #6aa3b7", +".OQ c #6aa5f3", +".P2 c #6aaae8", +".6q c #6b2e3e", +".1A c #6b3149", +".Vp c #6b3555", +".0m c #6b3956", +".#M c #6b47db", +".n1 c #6b51d0", +"#mr c #6b5c97", +".eN c #6b5cc1", +"#ny c #6b6394", +"#yf c #6b6595", +"#vL c #6b6788", +"#mg c #6b6998", +"#k6 c #6b6d96", +"#T9 c #6b706a", +"#RH c #6b7165", +"#iM c #6b7599", +".ZO c #6b75e4", +"#fr c #6b77ab", +".2b c #6b78e1", +".02 c #6b79e6", +"#FH c #6b7aa5", +".YY c #6b7fba", +".KE c #6b8095", +"#Z7 c #6b86bb", +"#EX c #6b8ac3", +".Ig c #6b8ec8", +"#U5 c #6b9594", +".Rc c #6ba2da", +"#Nr c #6bac94", +".SV c #6c304c", +".3Z c #6c3451", +".WE c #6c3555", +".2O c #6c404f", +".1u c #6c4772", +".MR c #6c4c57", +"#au c #6c5b92", +"#gn c #6c689b", +"#Ec c #6c6a92", +".7K c #6c6fb4", +".si c #6c6ff2", +"#LQ c #6c707c", +".75 c #6c76cd", +".6K c #6c77b7", +".9m c #6c77c6", +".Pl c #6c798c", +".5A c #6c79c8", +".01 c #6c7ae5", +"#C# c #6c7da9", +".LS c #6c7f90", +".Nc c #6c7fa9", +".J# c #6c83ad", +".Nf c #6c8aae", +".yF c #6c8cdf", +".Sv c #6c95d5", +".A3 c #6c98f9", +"#K3 c #6ca3c2", +".7D c #6d242f", +".8Q c #6d2c40", +".WB c #6d5e99", +".RM c #6d6783", +"#Fy c #6d68aa", +"#np c #6d6b9d", +"#Et c #6d6ca5", +".Dj c #6d6d87", +"#cL c #6d6db3", +"#Pd c #6d7091", +".Jn c #6d7170", +"#hA c #6d73a3", +"#M2 c #6d7577", +"#SY c #6d7663", +"#hz c #6d779b", +".Yy c #6d7ae2", +".CL c #6d7eda", +"#Fl c #6d808e", +".FS c #6d80c5", +".9a c #6d87dc", +".s6 c #6d8ada", +".3. c #6d91e5", +"#Wh c #6d92a5", +".wM c #6d93da", +".KY c #6da7d7", +".Vb c #6da7d9", +"#gp c #6e5b7b", +"#pT c #6e6498", +".7y c #6e6590", +"#iP c #6e699f", +".61 c #6e75cf", +".QR c #6e777c", +"#d0 c #6e779e", +".Vi c #6e7db4", +"#UD c #6e7f87", +"#oy c #6e87a5", +".II c #6e92c4", +".Ij c #6e95da", +".NX c #6e97d7", +".Sr c #6e9de1", +".rP c #6e9eea", +"#Hg c #6ea2a0", +".8P c #6f395d", +".0j c #6f456b", +"#gq c #6f4958", +".Jh c #6f545b", +"#le c #6f5890", +".sC c #6f5ed1", +".4B c #6f6cd3", +"Qth c #6f6fc7", +".qi c #6f6fcf", +"#xb c #6f7487", +"#iN c #6f75a5", +".5I c #6f75cb", +".LR c #6f7d97", +"#aK c #6f81c1", +".9b c #6f88dc", +".DT c #6f89e6", +".E2 c #6f8adb", +".Dq c #6f8fd8", +".sO c #6f8fe6", +".Ih c #6f93c5", +".t0 c #6f95e6", +".t1 c #6f96e5", +".Iv c #6fa2d7", +".rH c #6fa2e1", +".JJ c #6fa3d5", +"#Oz c #6fa87d", +".Ma c #6faae2", +".P1 c #6face5", +"#OF c #6fae67", +".rt c #7061b4", +"#oJ c #70669a", +"#oA c #706ba1", +".8J c #706ba3", +".H0 c #706d98", +"#fa c #7077a5", +"#GS c #7077bf", +".Yx c #707adb", +"#Ev c #707cae", +".Hx c #707ec5", +"#M7 c #708177", +".7W c #7081c6", +".sk c #7083e9", +"#UE c #70858a", +"#te c #7087a6", +".1W c #7088de", +".Wa c #7094ea", +".Cf c #7097f6", +".JC c #709bd0", +"#EQ c #70a3a7", +"#Iv c #70a6a8", +".WD c #714266", +".49 c #715a8e", +"#j2 c #715b8a", +"#GF c #716789", +"#KB c #716b91", +"#KA c #716d92", +"#fb c #7173a6", +".6S c #7173c6", +".5y c #7176ad", +".QQ c #717777", +".4u c #7177cd", +"#H7 c #7179ba", +"#Qz c #717b85", +".5G c #717bc2", +".03 c #717ded", +"#Di c #717eb3", +".QB c #71809d", +".EG c #7180df", +".FT c #7184c6", +".NY c #71879f", +".Gb c #718be2", +"#YT c #718d9b", +".Sq c #719ce1", +"#YW c #71a0a8", +".rO c #71a1e9", +".Rb c #71a4d9", +".rL c #71a4e6", +".6m c #724f77", +".7u c #725d9e", +".qa c #7268d9", +"#KC c #727190", +".Jm c #727268", +"#gm c #7273a9", +"#.z c #7276cf", +".0J c #727bbc", +".tZ c #727bd8", +"#Do c #727fa9", +"#UC c #72808b", +"#pJ c #7282a3", +".Xk c #7283dd", +".EE c #7287d8", +".xt c #7289e9", +".1V c #728ce1", +".W# c #728de6", +".Wf c #728feb", +".TF c #7296ec", +".Ik c #7299de", +"#Ws c #729caa", +".rN c #72a4e9", +".rM c #72a5e7", +".OP c #72aaf5", +"#Mh c #72ac9d", +".7C c #73334b", +".Qs c #73354e", +".pa c #7356c4", +".6j c #736795", +"#HS c #736a85", +"#D# c #7375a5", +"#.y c #7377d0", +".74 c #7378cc", +".TK c #737fc7", +".FQ c #737fd1", +".72 c #7381c2", +".5B c #7381cc", +"#UH c #738587", +"#If c #73938e", +".Kl c #7393b9", +".TE c #7393e8", +".TD c #739cdc", +".Il c #739cde", +"#XE c #73a6a1", +".KX c #73a8d2", +"#DE c #73adbb", +".3Y c #742950", +".H7 c #74636d", +"#w5 c #746a9f", +".7w c #746e9e", +".QS c #74818a", +"#Dm c #7481ae", +".4s c #7482da", +".89 c #7483c4", +".CK c #7483e0", +".FR c #7484d1", +".3S c #748dcf", +".uj c #748ed9", +".yG c #748fe0", +".vB c #7497d9", +"#BK c #749db3", +"#1l c #74a0d1", +"#XH c #74a295", +".rI c #74a8e2", +".rK c #74a9dd", +".6r c #75323b", +"#iT c #753d48", +".n0 c #7558d8", +"#vS c #7568a0", +"#pL c #756ea2", +".5H c #7576c8", +"#f# c #757ea5", +".KD c #757f8b", +".Oo c #7580a0", +"#GT c #7580c2", +"#UI c #758288", +"#IB c #7583b2", +".Am c #7584d9", +".S1 c #7586ba", +".EF c #7589e2", +"#BL c #758ba0", +"#GV c #758cb6", +".Ga c #758ee0", +".V9 c #7595ec", +".Sp c #759ce1", +"#YV c #759ea2", +".Cd c #759ee0", +"#XI c #75a2a5", +".JD c #75a3d5", +".rJ c #75aae0", +".P0 c #75ace4", +".EH c #767fda", +".N. c #768298", +"#mf c #7684a7", +"#zh c #7690ab", +".Hh c #7696cf", +".Hi c #769ad4", +".wj c #769ff1", +".wi c #76a0f6", +".KW c #76aacf", +".rn c #7763d6", +"#q7 c #776aa0", +".5P c #7778d5", +".9k c #7779c4", +"#Ps c #777a81", +".R6 c #77818b", +".00 c #7784ea", +".R7 c #778592", +".71 c #7785c2", +".4r c #7787de", +"#GU c #7788c0", +".xY c #7788da", +".7X c #7789cb", +"#UF c #778c8d", +".Or c #778ead", +".JU c #778eb8", +".Os c #778fab", +".KF c #7792ad", +".s5 c #7792e1", +".t2 c #779cea", +"#Wg c #779da8", +".Hj c #779fdc", +".M. c #77a8d1", +".Iu c #77a9da", +".MS c #784652", +".S2 c #786da7", +".6W c #7873b6", +".GP c #7882b5", +"#H8 c #7882c0", +".5F c #7882c7", +".3p c #7884e8", +".v. c #7887cc", +"#KG c #788885", +"#k5 c #7888aa", +".20 c #788bda", +".ui c #7890da", +".Hg c #7895d1", +".Dp c #7896d4", +".wL c #789ae1", +".vC c #789de3", +".UT c #789eef", +".vz c #789fe2", +".Hk c #78a4e5", +".Hm c #78a6f3", +".JI c #78aadb", +".OO c #78aef4", +".Wy c #795480", +".Ji c #795a62", +"#vT c #79689e", +".XQ c #796990", +"#uv c #797397", +"#cS c #79759a", +".xc c #7978b1", +".5R c #797ee4", +".ZL c #797fd5", +".3o c #7980db", +".za c #7984e0", +".EA c #79859f", +"#Zl c #798b7f", +".H# c #7990d4", +".sR c #799ae7", +".sS c #799eef", +".Im c #79a2e4", +".Hl c #79a5ec", +".M# c #79aee0", +".Kt c #7a4d54", +"#oK c #7a609d", +"#nA c #7a6aa8", +".2I c #7a6e94", +".qh c #7a75d1", +".rp c #7a76ee", +"#Ed c #7a78a0", +"#Jl c #7a79b2", +"#Vm c #7a8479", +"#LU c #7a8982", +".88 c #7a8abe", +".W. c #7a8ee7", +".A5 c #7a92d0", +".US c #7a99e9", +"#Z5 c #7a9ac1", +".sT c #7a9fef", +".Vq c #7b3f58", +".3X c #7b546f", +"#mq c #7b639d", +"#GH c #7b7591", +".PA c #7b7c81", +".0Z c #7b85e7", +".3n c #7b8dcd", +".xu c #7b8def", +".EC c #7b8fc1", +".Hf c #7b95d2", +".V8 c #7b95e9", +".B8 c #7b9ceb", +".vA c #7b9ede", +".ON c #7baeef", +".OG c #7bb0e2", +"#Is c #7bb487", +".7x c #7c76a2", +"#qY c #7c76a4", +"#BQ c #7c7fb6", +"#Up c #7c8081", +"#Qx c #7c878b", +".CJ c #7c87e1", +".4c c #7c88d2", +"#H9 c #7c8cc0", +".Ch c #7c91e4", +".Ha c #7c93d6", +".H. c #7c93d7", +".zQ c #7c9bed", +".UU c #7c9bee", +".sQ c #7c9dec", +".t3 c #7ca0ea", +".sU c #7ca1ef", +".OK c #7caeeb", +".PZ c #7cafe4", +".5g c #7d4852", +".XN c #7d527d", +"#nz c #7d65a1", +"#FB c #7d71c3", +".S3 c #7d75ae", +".6k c #7d779b", +"#zu c #7d77a3", +"#WT c #7d7d87", +"#Jm c #7d7db3", +".RP c #7d81ae", +".2a c #7d83e5", +".PB c #7d8592", +".LQ c #7d8598", +".21 c #7d8ed3", +".Id c #7d8fcd", +".1X c #7d8fe3", +".G4 c #7d91ce", +".5s c #7d91d8", +".Cg c #7d91f0", +".G# c #7d93df", +".Ds c #7d93e8", +".A6 c #7d95d5", +"#06 c #7d9693", +".zR c #7d9cec", +".wk c #7d9de8", +".Ip c #7da9e8", +".KG c #7dabc2", +".OJ c #7dafea", +".OL c #7dafee", +"#Ns c #7dc887", +".8R c #7e4556", +".SW c #7e505d", +"#pU c #7e659f", +"#El c #7e78b4", +"#Fp c #7e7a9f", +".5j c #7e7bb4", +".4D c #7e83e9", +".5J c #7e86db", +"#qW c #7e87a8", +".PC c #7e8a98", +".7U c #7e8abc", +".Op c #7e8dae", +".0c c #7e8eca", +".1Y c #7e8edc", +".4p c #7e8fe1", +".DS c #7e8fe7", +".uh c #7e92db", +".zS c #7e9be7", +".Jq c #7e9fca", +".Ng c #7ea0bc", +"#2A c #7eaad7", +".L9 c #7eacd0", +".It c #7eacdd", +".P. c #7eaddb", +".OM c #7eaeec", +".OH c #7eb3e7", +".OF c #7eb4e3", +"#Nt c #7ec384", +".nS c #7f44d2", +".o3 c #7f5dd5", +"#w6 c #7f73a5", +"#.h c #7f7fb1", +".Pz c #7f8084", +".4A c #7f81d8", +"#Og c #7f848a", +".3e c #7f84d8", +".3d c #7f86e1", +".1Z c #7f89d0", +".4q c #7f8fe4", +".E1 c #7f95e1", +".Dr c #7f95eb", +".s4 c #7f9be5", +".sP c #7f9ff2", +".In c #7fabea", +".JE c #7faedc", +".2G c #806b8a", +"#X5 c #807788", +"#Eu c #807fb8", +".LP c #80808c", +".2# c #8081dd", +".0Y c #8083e2", +".Py c #808581", +".4v c #8087df", +".6Q c #8089c0", +".6P c #808abf", +".6J c #808db7", +".5C c #808dd1", +".Oq c #8093b3", +"#UG c #809596", +".G9 c #8097dd", +"#EC c #809a9b", +".He c #809ad7", +".vy c #80a3e5", +".sV c #80a4ee", +".OI c #80b3ec", +".SU c #813a5c", +".LF c #81484f", +".Y8 c #815377", +"#ff c #815d77", +".Qy c #816a84", +".WS c #8176ba", +".Oh c #817c83", +".M4 c #817d8e", +"#Fs c #817da0", +".Zr c #817eb5", +".78 c #8180c4", +"#fs c #818bc6", +".6L c #818dc9", +".PD c #8190a3", +".A7 c #8196d9", +".zT c #8199e1", +"#YG c #81a5a3", +".TC c #81a7e5", +".Ra c #81a9e6", +".Io c #81adec", +".No c #81aed8", +"#OI c #81b591", +".ro c #8278f2", +".M5 c #828095", +"#WS c #828490", +".Dk c #828499", +"#Jn c #8286b3", +".Ia c #82887e", +".Yw c #828adf", +".6Z c #828ed8", +".ug c #8293d9", +".1J c #8294dc", +".Hb c #829ada", +"#Z6 c #829fc9", +".So c #82a8e9", +".vD c #82aaf2", +".Is c #82ade0", +".JH c #82b5e2", +".RG c #833e5d", +".96 c #836a8a", +"#oL c #8373b1", +"#GG c #837c9b", +".4h c #83809f", +".4t c #8384d6", +".Uh c #8386b9", +".4j c #8388bf", +".yr c #8388cc", +".Ui c #838ccf", +".0u c #838fc1", +".R8 c #8390a1", +".Jo c #83919c", +"#JS c #83969c", +".G8 c #8396da", +".yH c #8396e5", +".sZ c #83a7e5", +".sW c #83a8ee", +".KV c #83aacb", +".Nn c #83abcf", +".0k c #845c7e", +"#hE c #84728c", +"#yg c #847ba8", +".5. c #847d9f", +"#Fq c #847ea4", +".Bz c #8480e1", +".3f c #8485d5", +".5x c #8486b9", +".z# c #8488df", +".Pa c #84899f", +".6R c #848ac4", +".M9 c #848b9b", +".xX c #848bdb", +".Al c #848cdd", +".4d c #848ecb", +".xv c #848fdf", +"#Qw c #849084", +".QT c #8491a2", +"#eh c #8491be", +".G. c #8495db", +".t4 c #84a6ed", +".sY c #84a7e7", +".sX c #84aaeb", +".Ir c #84ade3", +".OE c #84bae8", +".Ky c #857791", +"#I9 c #857892", +"#sg c #8578ae", +"#cX c #857c91", +".QP c #85827d", +".5w c #8585a7", +".7G c #8587ae", +"#Eb c #8588ab", +".6I c #858bbd", +".By c #858be3", +"#no c #858eb7", +"#Ea c #8590ac", +".5E c #8590d2", +"#Hq c #85989e", +".LT c #859aaf", +".Dt c #859aed", +".Hd c #859ddb", +"#G2 c #85a5b0", +".Iq c #85aee6", +"##t c #8676a5", +".GX c #867b83", +"#I8 c #867c95", +".M6 c #86838e", +".ZK c #8687d9", +".Vx c #8689b6", +".EI c #868cda", +".T8 c #868dbb", +"#UJ c #868f98", +".On c #8690ab", +".73 c #8690d5", +".1I c #8692c2", +"#Dg c #8694c5", +".va c #8695da", +"#x6 c #8696ad", +".G7 c #869adf", +".UD c #869b92", +"#LV c #869e90", +".Hc c #869edc", +".s3 c #86a0ea", +"#1k c #86aed1", +".KK c #86afdd", +".Qt c #874960", +".rq c #8776dc", +".Vn c #877bbb", +"#s. c #8780a9", +".Og c #87818b", +".3V c #87839e", +".6u c #8784af", +"#AJ c #8785b4", +".5Q c #878aeb", +"#Tb c #878c88", +".Px c #878e87", +".Om c #878fa4", +".5z c #8793b9", +".FU c #8799d9", +".A8 c #8799db", +".6F c #8799e3", +".wl c #879bda", +"#yI c #87a1a0", +".t7 c #87a7e4", +".Nm c #87aaca", +".R# c #87aee9", +".PX c #87b3e4", +".JF c #87b8e3", +".Qm c #87c2ea", +".p. c #8864d2", +"#d6 c #886989", +".3U c #8872a1", +".WT c #887ab5", +".qg c #8880d6", +".M7 c #888691", +".M8 c #888a97", +".R5 c #888f95", +"#us c #888fac", +".5O c #888fdf", +".7V c #8895c9", +".1K c #889aee", +".wK c #88a3e8", +".LW c #88a4c9", +".t6 c #88a7e7", +".LX c #88a8cf", +".PY c #88b3e6", +".KR c #88b4d7", +".nT c #894eda", +".5a c #896a89", +".KA c #897b88", +".KB c #897f87", +".qf c #897fd5", +".FN c #898896", +".9l c #898bd5", +"#RJ c #899184", +".DR c #8991e2", +".F9 c #8997d8", +"#Fm c #8999a9", +".G3 c #8999cd", +".1L c #899aea", +".zU c #899ce0", +".Ot c #899fb7", +".vb c #89a3f0", +".nU c #8a52db", +".rr c #8a68b5", +"#Eo c #8a71cc", +".4z c #8a83d1", +".Oi c #8a8a8c", +"#yn c #8a8ea7", +".10 c #8a8fcf", +".CI c #8a90e6", +".6M c #8a95cd", +".0V c #8a95d3", +".LV c #8aa3c2", +".vc c #8aa4e1", +".vx c #8aa8e8", +".KJ c #8ab5df", +".KS c #8ab6db", +".JG c #8abbe6", +".nZ c #8b5acf", +".Y1 c #8b628a", +".p# c #8b6bda", +"#q8 c #8b72a9", +"#GE c #8b81a3", +".4C c #8b8af0", +"#BW c #8b8dc0", +".1O c #8b8fce", +".Ol c #8b939e", +".Vy c #8b93d1", +".uf c #8b95da", +".G5 c #8ba2e5", +"#YS c #8ba3ad", +".s2 c #8ba3eb", +".Do c #8ba6d3", +".LY c #8bacd5", +".t5 c #8bacef", +".PW c #8bb7e4", +".Ku c #8c4e4f", +".o4 c #8c65da", +".0e c #8c6d8f", +"#lg c #8c7ba8", +"#FC c #8c83d2", +".36 c #8c86cc", +".5# c #8c88a1", +".4f c #8c89cc", +".79 c #8c8acb", +".KC c #8c8b93", +"#C0 c #8c8cb0", +".Bx c #8c90e9", +"#SX c #8c9383", +".Xj c #8c97e7", +".5t c #8c98ea", +".Tl c #8c99a1", +"#Pu c #8c9b94", +".Vz c #8c9bdc", +".3m c #8c9fda", +".nW c #8d59d8", +".U. c #8d7390", +"#pV c #8d7eb9", +".T5 c #8d7fb4", +".WR c #8d84c5", +"#X8 c #8d8583", +"#th c #8d87ab", +".E0 c #8d8bdf", +"#Fo c #8d8daf", +".0A c #8d8ec7", +".5K c #8d8ede", +".Ak c #8d94e4", +".F8 c #8d95d4", +"#M3 c #8d9999", +".Tk c #8d9ba6", +".1q c #8d9cd3", +".Sw c #8da3df", +".s0 c #8da4e8", +".s1 c #8da4ea", +"#2n c #8daecd", +".RB c #8db6f8", +".RA c #8dc0ff", +".Ql c #8dc2f4", +".Pg c #8e3d44", +".LG c #8e484a", +".qb c #8e76e4", +".Yi c #8e83c7", +".LO c #8e848c", +".1P c #8e90c1", +".24 c #8e90cd", +".6H c #8e96bb", +"#C2 c #8e96bd", +".5D c #8e9cdd", +"#Zk c #8e9d9a", +".TB c #8eb1e9", +".Dg c #8eb1f3", +".KU c #8eb6d9", +".KL c #8eb8e2", +"#j4 c #8f586b", +".XS c #8f6289", +".33 c #8f6370", +"#tq c #8f82b8", +"#Kl c #8f859e", +".6X c #8f89c9", +".5n c #8f8dce", +".6Y c #8f90d3", +"#D. c #8f91c4", +".FW c #8f97e0", +".Ib c #8f989f", +".7T c #8f9ac8", +".PE c #8f9fb8", +".UR c #8fa2ef", +".LU c #8fa7c1", +"#ZR c #8fafaa", +".Qk c #8fbbfc", +".MT c #904951", +".LH c #904e4f", +".nV c #9058dd", +".6l c #907fa3", +".2H c #90829c", +".ZJ c #908bdd", +".F0 c #9095d7", +".FZ c #9095d9", +".Pw c #909994", +".6O c #909acd", +"#Qy c #909ba1", +".R9 c #909dae", +".FV c #909de1", +".Dh c #909fca", +".19 c #909fd8", +".2. c #90a0dc", +".Du c #90a1f1", +".UC c #90a3a1", +".Ci c #90a5e6", +".G6 c #90a7eb", +".vd c #90a8e6", +".Ua c #915265", +".o9 c #916bda", +".Y5 c #916f94", +".35 c #917fb1", +".Jl c #918086", +".z. c #918ce0", +".Zk c #918dca", +".5N c #918dd7", +".ZA c #9192c8", +"#C9 c #9194cb", +".F7 c #9195d5", +".23 c #9195dc", +"#Ay c #9196b4", +".VB c #9199ca", +".xx c #919ae7", +".85 c #919cd2", +".yI c #919ceb", +".Ic c #919dc3", +"#FG c #919dcf", +"#GA c #919faa", +".WN c #919fdc", +".70 c #91a0db", +"#Id c #91afad", +".LZ c #91b4dc", +".L8 c #91bcdc", +".KT c #91bcdf", +"#cV c #92696d", +"#X6 c #928891", +"#Kk c #928aa1", +".4g c #928eb1", +".Yj c #9291cb", +"#CY c #9294a0", +".4e c #9294e1", +".4. c #9295dc", +".Ww c #9296c3", +"#oz c #9297c1", +".FY c #9297db", +"#Pt c #929a9c", +".Pv c #929a9d", +".Tm c #929da1", +".6N c #929ed2", +".t8 c #92a8f3", +".Sn c #92b4f1", +".R. c #92b7ec", +".Vd c #92cdff", +"#gr c #935d5d", +".Kx c #937b89", +"#go c #938db9", +".xW c #938fdc", +"#pK c #9392be", +".TL c #9396db", +".F1 c #9398d8", +".8U c #939ac6", +".ue c #939ade", +".QU c #93a2b9", +".V7 c #93a3f1", +".t9 c #93a7f0", +".tz c #93a7ff", +".vw c #93a8e7", +".PV c #93c0e9", +".N5 c #94414b", +".nX c #9460dc", +".Y0 c #946e95", +".Yr c #9486d3", +"#En c #948bc2", +".0X c #9491ec", +"#AK c #9493bd", +".F6 c #9495d6", +".F3 c #9499d3", +".Ul c #949bc7", +"#gE c #94a1d5", +".1M c #94a2e9", +".QC c #94a6be", +".0v c #94a7ec", +".Jp c #94acc8", +".KM c #94bee4", +".Y6 c #956d92", +"#Da c #9580ab", +".Kz c #95869b", +"#aI c #9587b8", +"#Km c #9589a1", +".Yh c #958bc7", +".Ug c #9594b6", +"#BP c #9598cf", +".F2 c #9599d8", +".22 c #959be7", +"#C1 c #959cc8", +".RQ c #959ec7", +".Dv c #959ee9", +".xw c #95a0f0", +"#bV c #95a1c7", +".Pm c #95a2b3", +".2F c #95a3d0", +".wJ c #95a6eb", +".TA c #95b1e3", +".KQ c #95bede", +".H8 c #967f89", +".EZ c #9693e4", +".Zj c #9694df", +".O. c #9695a7", +".WQ c #9695d1", +".Bw c #9696ec", +"#BY c #9697c5", +".Yv c #9698e3", +".0z c #9699de", +".Ok c #969b9f", +".ZG c #969bdf", +"#Ta c #969c98", +".v# c #969edd", +"#c6 c #96a3c6", +".0x c #96a3f2", +".3l c #96a5dc", +".u. c #96a7ef", +".Nh c #96b6cd", +".Ry c #96b9fb", +".Rz c #96c3ff", +".rs c #9773b9", +".1t c #9783a8", +"#iV c #9785af", +".5L c #978dd4", +".Ya c #978fbe", +"#qX c #9790ba", +"#Fz c #9790d3", +".3W c #9792a6", +"#Kj c #9794a5", +"#Ee c #9795bd", +"#Df c #9798c6", +"#r8 c #979abb", +".5v c #979ac3", +".FX c #979ae9", +".F4 c #979cd6", +"#vI c #979db3", +"#Fn c #979eb8", +".0K c #979ed4", +".Dl c #97a0b1", +".Tn c #97a1a3", +".7S c #97a3cd", +".Zf c #97a8ed", +"#OG c #97d896", +".sG c #9875c7", +".Vs c #988587", +"##j c #9888b7", +"##h c #988cbe", +".99 c #988fbc", +".QO c #989793", +".25 c #9898ca", +".EJ c #9898d6", +".DQ c #9898e2", +".UE c #989ba2", +".S6 c #989bc4", +".WM c #989fd3", +".WP c #98a1dc", +".6G c #98a5d2", +".18 c #98a5da", +".Uk c #98a8dc", +"#Oh c #98a9a3", +".Qn c #98c7f3", +".Qw c #995758", +".N9 c #99879f", +"#av c #998bc6", +".T9 c #998dcb", +".X6 c #9990df", +".4i c #9996cb", +"#zB c #999cbb", +".11 c #999cd3", +".yJ c #99a0f0", +".zV c #99a2e3", +".0S c #99a3d4", +".Tj c #99a7b4", +".7Y c #99a9e7", +".P# c #99b1d7", +".Nl c #99b8d4", +".Ca c #99bbeb", +"#q9 c #9a8bc2", +".5M c #9a8fd3", +".W5 c #9a93c6", +"#CZ c #9a95ab", +".Zq c #9a98bf", +".Zz c #9a99d2", +".Oj c #9a9b9d", +".5u c #9a9ee5", +".FP c #9aa0ba", +".3h c #9aa0d4", +".UQ c #9aa2eb", +".Pu c #9aa3ac", +".Ze c #9aa7db", +".u# c #9aa8ef", +".ve c #9ab0ea", +".L0 c #9ab6db", +".PU c #9ac6eb", +".RI c #9b6774", +".N3 c #9b6d7a", +".2J c #9b76a9", +".qc c #9b76df", +".6v c #9b91b3", +".ZI c #9b92e5", +"#FA c #9b95d5", +".VC c #9b97ca", +"#d3 c #9b98c7", +".ZB c #9b9dd0", +".Xi c #9b9ee5", +".F5 c #9ba0d8", +".xy c #9ba2e8", +".A9 c #9ba4e5", +".0U c #9ba5e0", +".vv c #9ba6e4", +".0T c #9ba7db", +".KN c #9bc6e8", +".tW c #9c8edd", +".y9 c #9c90e2", +"##u c #9c94c5", +".Of c #9c95a5", +".X5 c #9c99e0", +".0B c #9c9bc3", +".Ym c #9c9bd4", +".S4 c #9c9cd0", +".Dw c #9c9fe4", +".1N c #9ca0e9", +".ZD c #9ca1d8", +"#zi c #9ca5c4", +".2X c #9ca8d8", +".wm c #9ca8e2", +".G2 c #9ca9d6", +".ua c #9ca9ef", +".Tz c #9cb1de", +".nY c #9d6ce2", +".Ys c #9d91db", +".7F c #9d98b8", +".CH c #9d98e8", +".W6 c #9d99d6", +".4w c #9d9bee", +"#BX c #9d9fcf", +".ud c #9da1e1", +".0R c #9da4d2", +".V6 c #9da4ec", +".X2 c #9daced", +".RC c #9dafef", +".PT c #9dcae9", +".N4 c #9e5e6c", +".4y c #9e91d9", +".M3 c #9e949f", +".0W c #9e98f2", +"#FD c #9e9ae6", +"#AB c #9e9cdd", +"#BM c #9ea0b5", +"#AQ c #9ea0c6", +"#.i c #9ea0d0", +".ub c #9ea8ed", +".RR c #9eabce", +".Uj c #9eadf0", +".7R c #9eaee2", +".0w c #9eafff", +".Sm c #9ebbf3", +".Q9 c #9ec2f2", +".OD c #9ec3f0", +".0f c #9f7fa4", +"#sh c #9f87b9", +"#BZ c #9f8bb0", +".1S c #9fa3bc", +".R4 c #9fa4a7", +".wI c #9fa7e8", +".VA c #9faee7", +"#EZ c #9fb0b7", +".vf c #9fb2ec", +".1s c #a08baa", +".ZH c #a092e9", +".EL c #a099dc", +".EK c #a09dd2", +".W9 c #a09ecd", +".Yp c #a09fe5", +"#B4 c #a0a2cb", +".S5 c #a0a4d3", +".G1 c #a0a9d2", +"#2m c #a0b6cb", +".L1 c #a0bee4", +".KP c #a0c5e2", +".KH c #a0cdea", +".o5 c #a16ddc", +".Jj c #a1838b", +".1r c #a18bb2", +"#hI c #a18cb3", +".sI c #a18de2", +"#ms c #a18fbf", +".xV c #a195e1", +".Aj c #a196e2", +".Zv c #a19ebd", +".Yu c #a19ee5", +".X. c #a19fce", +".Yk c #a1a0d9", +".0Q c #a1a5d4", +".vu c #a1a5e2", +".Zh c #a1a8f6", +".0y c #a1aaf5", +".WO c #a1b1ed", +"#2z c #a1bfd7", +".L6 c #a1c5dd", +".L5 c #a1c8e5", +".o8 c #a278e6", +"##r c #a28dc5", +".Yg c #a29ac9", +"#zv c #a29dc6", +".Xh c #a2a0e1", +".Yq c #a2a0e9", +".Yl c #a2a1da", +".Yn c #a2a1db", +".VV c #a2a2ba", +".26 c #a2a4cb", +".0L c #a2a5c8", +"#FE c #a2a5e8", +".3i c #a2aadb", +"#FF c #a2abe6", +".X3 c #a2acf1", +"#1h c #a2adc1", +".vg c #a2b1e8", +".wn c #a2b1ec", +".Cc c #a2ccfe", +".PS c #a2cfec", +".y8 c #a395e4", +"#r9 c #a398c0", +".RE c #a399b4", +".Yt c #a39ce2", +".EY c #a39de7", +"#Fr c #a39fc4", +"#BO c #a3a0cf", +".UP c #a3a4e5", +"#Ki c #a3a5b2", +".X4 c #a3a6ed", +".EB c #a3b5dd", +".Ou c #a3b8cb", +"#KI c #a3bca9", +"#Js c #a3bcb8", +".C# c #a3c0f8", +".KO c #a3c6e2", +".KI c #a3cff2", +".7E c #a46872", +".o7 c #a476e3", +"##k c #a47c94", +".LJ c #a48c9a", +".GY c #a498a2", +"#aw c #a4a1cc", +".Yo c #a4a4e4", +".27 c #a4a7ca", +".ZC c #a4a7da", +".Zi c #a4a8f2", +"#wV c #a4a9bc", +".ZE c #a4a9e3", +".S. c #a4adbe", +"#c7 c #a4b0da", +".Zg c #a4b1ff", +".PF c #a4b5cf", +".L7 c #a4c7db", +"#OH c #a4e4b2", +"#bJ c #a58280", +".Pj c #a58296", +"#uE c #a592c9", +".EM c #a59cdd", +".Yf c #a59ec0", +".tY c #a59eee", +".Zs c #a5a3d4", +".uc c #a5a6e7", +"##v c #a5acd8", +"#RK c #a5aead", +".wo c #a5b9f8", +".Sl c #a5bcee", +".OA c #a5c3df", +".Cb c #a5cbf8", +"#aF c #a680af", +"#si c #a698cb", +".VD c #a699d1", +".yK c #a69ae4", +".Dy c #a69cd9", +".Bv c #a69fef", +".Dx c #a6a0e0", +".8V c #a6a1c9", +".zW c #a6a6e6", +"##i c #a6a7d3", +".12 c #a6a8db", +".3g c #a6a9e0", +".X1 c #a6abd5", +".UB c #a6b0b9", +".7Z c #a6b6f2", +".L4 c #a6cfef", +".o6 c #a775e4", +".qd c #a778de", +".Ai c #a79be3", +".4x c #a79de6", +".W4 c #a79fc4", +"#tf c #a7a6c8", +".xz c #a7a7e5", +".28 c #a7adcd", +".86 c #a7afde", +".vh c #a7b4e9", +".Q8 c #a7c8f3", +".OB c #a7c9ee", +".L2 c #a7caf0", +".Qv c #a8666a", +".Kv c #a86c6c", +".qe c #a874d8", +".LN c #a899a0", +".I# c #a89ba2", +"#tg c #a89cc0", +"#Em c #a8a0d9", +".Oe c #a8a2ae", +".DP c #a8a2e8", +"#GD c #a8a3c1", +".V5 c #a8a8e8", +".98 c #a8afdb", +"#ID c #a8b29a", +".QV c #a8b4ce", +"#zX c #a8c8bd", +".OC c #a8cbf5", +".Uc c #a99793", +".vt c #a9a8e4", +".VU c #a9a9c3", +"#GB c #a9b2c1", +".29 c #a9b2d1", +".17 c #a9b5e5", +".Sk c #a9bce7", +".Cj c #a9bdf0", +".C. c #a9c2ff", +"#ZS c #a9c8ca", +".Q7 c #a9c9ef", +".PR c #a9d7f1", +".RK c #aa7e7b", +"#ut c #aa9eb2", +".Xe c #aaa1e2", +"#bL c #aaa5bb", +".zX c #aaa5e5", +".Zw c #aaa6c7", +".wH c #aaa8e7", +".Zu c #aaa9cb", +".1R c #aaabc7", +"#x7 c #aaacc5", +".ZF c #aaafef", +"#xx c #aabcc8", +".Q6 c #aac8ea", +".L3 c #aad0f5", +".Vo c #ab90af", +".WC c #ab90b1", +".yL c #ab9fe7", +"#d5 c #aba0d8", +".yM c #aba0e4", +"#fc c #aba7d9", +".Si c #abb9de", +".Ty c #abb9e0", +".Q5 c #abc8e8", +".H9 c #ac979e", +".vm c #acaee7", +".0G c #acb0cd", +".vl c #acb1e9", +".Sj c #acbbe4", +".Dm c #acbdcf", +".B9 c #acbdff", +".XR c #ad8fb3", +"#ax c #ad99ca", +"#fi c #ad9bb3", +".CG c #ad9de4", +".WU c #ad9ec7", +".6y c #ada0d6", +".EN c #ada4e3", +".Y# c #ada5ca", +".Xg c #ada7e7", +".Zl c #ada8d0", +".X# c #adabda", +".vn c #adace6", +".QN c #adafaa", +".0E c #adafbe", +".Ti c #adb7c3", +".3k c #adbaee", +"#Gc c #adc1cc", +".Ni c #adcada", +".Xf c #aea5e6", +".Xc c #aea8e6", +".0M c #aeafce", +".Pt c #aeb5c5", +".vk c #aeb5ec", +".VT c #aeb7d6", +".4k c #aebbde", +".Qo c #aec3f8", +"#.. c #af8da5", +".8S c #af92a8", +"#ts c #afa2d0", +".X7 c #afa6d1", +".EX c #afa6e9", +"#BN c #afa8c9", +".vs c #afabe6", +".vo c #afabe8", +".IG c #afaef0", +".1Q c #afafd3", +".Qp c #afb0dc", +"#.j c #afb8e3", +".Dn c #afc4e1", +".Nk c #afcde5", +"#cU c #b097b4", +".0D c #b0afbf", +".vi c #b0baed", +".87 c #b0bbe8", +"#YE c #b0cdcb", +".Pe c #b17889", +".Qx c #b18086", +"#vW c #b19ac8", +"#Ep c #b19bf0", +".y7 c #b1a1e0", +"#Az c #b1aad3", +".xA c #b1ace4", +".W8 c #b1afe0", +".T7 c #b1b1d7", +".UO c #b1b2eb", +".B. c #b1b3f0", +".0P c #b1b5e5", +".16 c #b1bcea", +"#Hn c #b1bfca", +"#bI c #b29fb3", +".Ah c #b2a3e6", +".vr c #b2a6e6", +".vq c #b2a8e7", +".Ye c #b2a9c4", +".vp c #b2a9e8", +".Xd c #b2acec", +"#Ju c #b2cdba", +".Vk c #b396c4", +".xU c #b39fe7", +"#X7 c #b3a7b3", +".EQ c #b3a9de", +".QD c #b3c5d9", +"#2w c #b3c5f5", +".Vc c #b3edff", +".RL c #b4979c", +".5i c #b49dc7", +"#tr c #b49dcb", +".yN c #b4a8e6", +".Xb c #b4afe7", +".Zt c #b4b3db", +"#GC c #b4b6cd", +".S# c #b4bbcb", +".1U c #b4bbd7", +".Ck c #b4c0f0", +".Oz c #b4cce4", +".Ph c #b56365", +".LI c #b58a91", +"#B0 c #b59fc3", +"#AL c #b5a2c0", +"#nB c #b5a3d5", +".DA c #b5a7e2", +".Dz c #b5a7e4", +".EW c #b5a9e7", +".8Y c #b5ade0", +"#zl c #b5b0ea", +".Cl c #b5b7f0", +"#Hp c #b5c1a9", +".PI c #b5c1d9", +"#E0 c #b5c7d1", +".Ov c #b5c8d7", +".Pf c #b67281", +".MW c #b68892", +".N8 c #b68a99", +".y6 c #b6a6e4", +".zY c #b6a7ea", +".Y. c #b6acc5", +".EO c #b6ace8", +".wG c #b6aceb", +".Zy c #b6afd8", +"#AA c #b6afe5", +".UN c #b6b8eb", +"#aJ c #b6bbe5", +".RS c #b6c1df", +"#bU c #b6c3e3", +"#YF c #b6ced2", +"#ZU c #b6d2e0", +"#uF c #b79ee0", +".ER c #b7aadf", +".EP c #b7ace6", +".G0 c #b7b1bd", +".Um c #b7b1dd", +".Xa c #b7b3e5", +".WL c #b7b6d8", +".0N c #b7b7d3", +".1T c #b7bdd7", +".Q3 c #b7c5e2", +".PG c #b7c7e1", +"#vU c #b8a6da", +".EV c #b8a8e6", +".7H c #b8b3d3", +".S0 c #b8bbda", +"#iU c #b98a9e", +"#ay c #b98ea2", +".XM c #b994bd", +".ET c #b9a5e4", +".LM c #b9a7b5", +".LK c #b9a7c1", +".EU c #b9a7e5", +"#oM c #b9a9da", +"#d4 c #b9b4dc", +".Zn c #b9b5c3", +".SR c #b9b6e5", +".R3 c #b9b7b8", +".wp c #b9b7e8", +".13 c #b9bcef", +".3j c #b9c3f4", +".vj c #b9c3f6", +".QF c #b9c5d3", +".Q4 c #b9c7ea", +".PP c #b9d0f2", +"#1j c #b9daed", +".MX c #baa3b5", +".Bu c #baa8f2", +".zZ c #baabec", +".W3 c #bab2ca", +".97 c #bab2d7", +"#zj c #bab6db", +".Zo c #bab7ca", +".S7 c #babadc", +".Sh c #bac4e8", +".PH c #bac8e2", +"#hH c #bb8b97", +".Vt c #bb9fab", +"#pW c #bbabda", +".DB c #bbace5", +".Zx c #bbb5db", +".QG c #bbc1cd", +".Tx c #bbc3e7", +"#2k c #bbcacd", +".PO c #bbcfe8", +".Kw c #bc9399", +".5k c #bca5bf", +".yO c #bcafe7", +"#vJ c #bcb1c1", +".To c #bcbbcd", +".sj c #bcc1ff", +".QE c #bcccdc", +".Nj c #bcd8e4", +"#09 c #bcdcf1", +".MV c #bd7578", +".2Q c #bd8ea0", +".XU c #bd96b5", +".CF c #bda4e5", +"#uG c #bda5d9", +".DO c #bda6ea", +".xT c #bda6ee", +"#zw c #bdaac6", +".Ag c #bdabe7", +".SS c #bdafd0", +".ES c #bdb1e3", +".8T c #bdb6d5", +".W7 c #bdb7fd", +".V4 c #bdb9f4", +".Zd c #bdc0e1", +".Th c #bdc3cf", +".PQ c #bdd4fd", +".Vr c #be9da4", +".0d c #bea7d5", +"##s c #beacd2", +".wF c #beb0ee", +"#Eq c #beb0fd", +".VE c #beb2e0", +".Cm c #beb4f9", +".B# c #beb6f1", +".xC c #beb7eb", +".UM c #bec0f0", +".QM c #bec4c2", +".15 c #bec5f3", +".Pn c #becad8", +".X9 c #bfb3c7", +".Ba c #bfb4ec", +"#yh c #bfb6e1", +".xB c #bfb8ec", +"#08 c #bfd9e6", +".RJ c #c09090", +"#d7 c #c09199", +".LL c #c0afc2", +".MY c #c0b2c9", +"#Er c #c0b9fc", +"#fd c #c0bbe4", +".wq c #c0bdec", +".0C c #c0c0d8", +".Pp c #c0c9d0", +"#w9 c #c1abcf", +".y5 c #c1b0e7", +".yP c #c1b1e0", +".Z# c #c1b4c6", +"#w7 c #c1b4e2", +"#x9 c #c1b9e2", +".QJ c #c1d1e0", +".Qu c #c28493", +"#aG c #c2a1c0", +"#vV c #c2aae4", +".WG c #c2aeba", +".Co c #c2b3ec", +".M2 c #c2b5bc", +".0O c #c2c4f5", +"#KH c #c2d6cd", +"#Db c #c3acd6", +".DN c #c3aded", +".JS c #c3aee9", +"#AM c #c3afcb", +".DC c #c3b2e8", +".WV c #c3b5cf", +"#tv c #c3bfcd", +".WH c #c4adbd", +".Cp c #c4b3ea", +".XL c #c4bbe6", +".PJ c #c4c7d6", +".VS c #c4caea", +".Tv c #c4ccf1", +".QK c #c4d1d9", +".MU c #c57073", +".Y9 c #c5a7c1", +".DE c #c5b2e0", +".Z. c #c5b8cc", +".Vw c #c5c2df", +".FO c #c5c7dc", +".Tw c #c5cbed", +".Sg c #c5ceeb", +".Po c #c5cfd9", +".QW c #c5cfea", +"#Dc c #c6b0d7", +".DD c #c6b4e6", +".XW c #c6b5c7", +".z0 c #c6b8f3", +"#x8 c #c6bfde", +".Tg c #c6cad5", +".Cq c #c7b5e9", +".VM c #c7b7c1", +".Bb c #c7b9ee", +".Cn c #c7b9ff", +"#vK c #c7bace", +".z1 c #c7bdf2", +"#wW c #c7bed1", +".Yd c #c7bfd6", +".wr c #c7c1f1", +".RD c #c7c5f7", +".Ps c #c7c7d1", +".UF c #c7cacf", +"#r. c #c8b9e4", +"#wX c #c8bbd5", +"#Es c #c8c4ff", +".RU c #c8cadf", +".QL c #c8d2d4", +"#2l c #c8d9e3", +".PN c #c8d9e9", +".Pi c #c9868d", +".Ub c #c9aaa8", +".wE c #c9b2ea", +".DF c #c9b4df", +".wD c #c9b5ea", +"#yi c #c9b6d6", +".M1 c #c9bac1", +"#uu c #c9bacf", +".5m c #c9bfda", +"#zk c #c9c1f2", +".Od c #c9c4cb", +".R2 c #c9c7ca", +".VW c #c9c9e1", +".14 c #c9cdfd", +".Ts c #c9d2d7", +".Q2 c #c9d6e9", +".QI c #c9d8eb", +".Bt c #caabee", +".8W c #caadc9", +".wA c #cabde8", +".VF c #cabee6", +".wz c #cac0e5", +".6w c #cac2da", +".wy c #cac3e5", +".V3 c #cac7fe", +".QH c #caccd9", +"#IC c #cad2d4", +".Ow c #cadaea", +"#Ie c #cae7e2", +".Af c #cbb4e8", +".y4 c #cbb7e8", +".wC c #cbb7ea", +".2S c #cbb9df", +".wB c #cbbbea", +".wt c #cbbeea", +".W2 c #cbc0d0", +".Yb c #cbc1d9", +".ws c #cbc2ef", +"#cT c #cbc7fa", +".RV c #cbc8db", +".Zp c #cbc8e5", +".Pq c #cbcfd8", +".RT c #cbd2ec", +".Oy c #cbe0f3", +".Cr c #ccb8e9", +"#De c #ccc1eb", +".X8 c #ccc2db", +".GZ c #ccc4cf", +".wx c #ccc5e7", +".UL c #ccc7de", +".Tf c #ccccd4", +".RW c #ccd2e2", +".xS c #cdb6ec", +".M0 c #cdbdc8", +".2R c #cdbed3", +".IH c #cdbef7", +".0p c #cdbfd8", +".Yc c #cdc3db", +"#2y c #cdd7e3", +".CE c #ceafeb", +".DM c #ceb6f0", +".DG c #ceb7e3", +".I. c #cebdc5", +".XX c #cebdcd", +".wu c #cebde9", +".6x c #cebfdc", +".Uq c #cec0d1", +".Zm c #cec9df", +".0F c #ced0e7", +".RX c #ced1e2", +"#aA c #cfb8be", +"#B1 c #cfbadb", +".Bc c #cfbef2", +".Ob c #cfcad0", +".UK c #cfcade", +".Pr c #cfd2db", +"#G# c #cfe5f2", +".WF c #d0adc1", +".YZ c #d0bdeb", +".yQ c #d0bee8", +".WW c #d0c1d6", +".VG c #d0c1de", +".W1 c #d0c3cc", +".O# c #d0cedc", +".Wx c #d1b2de", +".xR c #d1baee", +"#Dd c #d1bfe7", +".MZ c #d1c3d4", +".UI c #d1d0d8", +"#yJ c #d1e6e1", +"#07 c #d1e9ed", +".6s c #d29ca9", +".37 c #d2b5c9", +".2V c #d2bdce", +"#w8 c #d2bde8", +".Vj c #d2beef", +".Uw c #d2c1d3", +".5l c #d2c5d6", +".Uv c #d2c7cd", +".QZ c #d2d5de", +".Q0 c #d2d7dd", +".Ox c #d2e3f5", +".XV c #d3bbd1", +".Cs c #d3bce8", +".Uy c #d3c7df", +".VZ c #d3cdef", +".Sc c #d3d6db", +".Tr c #d3d8db", +"#1i c #d3e6f7", +".CD c #d4b9e4", +".Jk c #d4bfc6", +".7I c #d4c0db", +".VH c #d4c3d6", +".z2 c #d4cbfa", +".V2 c #d4d1ff", +".Sd c #d4d9dc", +".Tu c #d4ddfa", +".xQ c #d5bfee", +"#yj c #d5c1dc", +".V0 c #d5cef7", +".V1 c #d5cef8", +".RY c #d5d8e9", +".Ab c #d5dee3", +".7J c #d6bde4", +".DL c #d6bef2", +".y3 c #d6c1ec", +"#zx c #d6c2db", +".Bd c #d6c4f4", +".39 c #d6cdea", +".Te c #d6d4e2", +".VR c #d6d9f8", +".Bs c #d7afeb", +".DH c #d7bbec", +".Ae c #d7bdea", +".wv c #d7c5ef", +".WZ c #d7caf5", +".Oc c #d7d2d8", +".UJ c #d7d3e1", +".Sf c #d7e0f1", +".xP c #d8c3ee", +".xD c #d8c4e9", +"#B2 c #d8c7e9", +"#uJ c #d8d3d9", +".PK c #d8deea", +".Tt c #d8e1f0", +"##l c #d9aaa2", +"#lh c #d9bcda", +".DI c #d9bdee", +".DK c #d9c1f1", +".Zb c #d9c8d0", +".Ux c #d9cadf", +".WY c #d9cbee", +".VY c #d9d6f1", +".R1 c #d9d8e0", +".0n c #dab6d0", +".CC c #dac0e7", +".DJ c #dac0ef", +".Ct c #dac1e9", +".Be c #dac7f4", +".38 c #dac8d4", +"#j6 c #dac9f5", +"#sj c #dacbf2", +".VN c #daccd9", +".UA c #daddee", +".Ud c #dbbdc7", +".xO c #dbc7ec", +".S8 c #dbd7f2", +".Oa c #dbd8e3", +"#j5 c #dcaec8", +".6t c #dcc2df", +".Ur c #dccbd5", +".W0 c #dccfd6", +".VP c #dcd7ee", +".Se c #dce5ec", +".PM c #dceaf5", +".VL c #ddd1e7", +"#sl c #ddd6e8", +".UH c #dddee2", +".sH c #deb8ff", +".0q c #debfe1", +".Za c #dec8dd", +".Bf c #dec8ef", +".xE c #decaed", +".xN c #decbe9", +".XY c #decddd", +".WX c #ded0e9", +".QY c #deddeb", +".tX c #dfcbff", +".SZ c #dfced4", +".Un c #dfd1ff", +".VO c #dfd4e5", +".2W c #dfdbf4", +".VQ c #dfdcf9", +".z6 c #dfdde8", +".0t c #dfe0fc", +".QX c #dfe6ff", +"#ZT c #dffcff", +"#bK c #e0c2c2", +".Cu c #e0c6eb", +".xF c #e0caee", +"##m c #e0cbda", +".xM c #e0cee8", +".1D c #e0d1f2", +".z4 c #e0d3f1", +".S9 c #e0d6ef", +".Sb c #e0e0ec", +".RZ c #e0e2f1", +".A# c #e0e7ed", +"#az c #e1b0a1", +".CB c #e1c7ea", +".y2 c #e1c9ed", +".0r c #e1cad4", +".T6 c #e1caf6", +".ww c #e1ccf7", +"#AN c #e1cde8", +".Cw c #e1ceec", +".1G c #e1cfdd", +".T# c #e1d6e7", +".z3 c #e1d6fe", +".Aa c #e1eaef", +".Q1 c #e1ebf5", +".1B c #e2b7cb", +".SX c #e2bfbd", +".Ad c #e2c6ee", +".yR c #e2cdf4", +".Cx c #e2cfeb", +".xL c #e2d0e8", +"#tt c #e2d4f7", +".Up c #e2d6ee", +"#B3 c #e2d8fd", +"#vY c #e2dde4", +"#gs c #e3b4bc", +".Bg c #e3c9ee", +".WI c #e3cedf", +"#gt c #e3ceed", +".Uu c #e3d7db", +".Ta c #e3d9f1", +".R0 c #e3e2f0", +"#Ga c #e3f0e7", +"#Jt c #e3fbee", +".Cv c #e4caed", +".Cy c #e4d0eb", +"#mu c #e4d1ef", +"#AO c #e4d4ee", +"#.a c #e4d5f4", +".yZ c #e4d7e8", +".T. c #e4d8e6", +".N6 c #e58b8d", +"#.# c #e5bbbf", +".JT c #e5c1f1", +"#mt c #e5cae9", +".Bq c #e5cde3", +".CA c #e5ceeb", +".Cz c #e5d1ec", +".Td c #e5e0f6", +".Uz c #e5e1f8", +".A. c #e5eaf0", +".5h c #e6bbcf", +"#uH c #e6d1f0", +"#nD c #e6d5f5", +".yS c #e6d7ec", +".Uo c #e6dcf7", +".VX c #e6e4fc", +".PL c #e6f0fa", +"#Gb c #e6f7f1", +".Bj c #e7e0f0", +".z9 c #e7eaf3", +".Bh c #e8cdee", +".xG c #e8d0f2", +".VI c #e8d6e4", +".Tp c #e8e8f4", +"#Ho c #e8f2d7", +".N7 c #e99ea3", +".Br c #e9baf0", +".Ac c #e9cbef", +".SY c #e9ccc6", +".z5 c #e9d9f3", +".Bk c #e9e1f0", +".Sa c #e9e6f7", +".z8 c #e9e9f3", +".Bi c #eacfee", +".y1 c #ead1ef", +".Bp c #ead3e7", +".VK c #eaddef", +".0o c #eaddf1", +".8X c #ebcadf", +"#oO c #ebdcfb", +"#xa c #ebe5ef", +".xK c #eccfee", +".Vu c #ecd0e6", +".xI c #ecd1f2", +".xH c #ecd3f3", +"#pX c #ecd5f2", +".yU c #ecdff3", +".Tb c #ece2fd", +".z7 c #eceaf5", +".1H c #eceaff", +"#zz c #eddff0", +".Bl c #ede3ee", +".Tc c #ede7ff", +".UG c #edeef2", +"#d8 c #eec5c9", +"#zy c #eedbee", +".yT c #eedff4", +".y0 c #efd5f2", +"#vX c #efdbf6", +".2U c #f0cfe0", +".xJ c #f0d3f2", +"#oN c #f0d7f7", +".Bo c #f0dbea", +".WJ c #f0e2f3", +".yY c #f0e3f4", +".yV c #f0e3f7", +".Bm c #f0e4ee", +".Tq c #f0f3f8", +"#nC c #f1d6f7", +".Uf c #f1e1fc", +".yX c #f1e4f6", +"#ra c #f1e7ff", +"#cW c #f2d0d1", +".Bn c #f2e2ed", +".2T c #f3c3ff", +".34 c #f3cfe9", +".0s c #f3e5f4", +".yW c #f3e6f8", +"#pY c #f3e6ff", +".X0 c #f3efff", +"#r# c #f4ddf7", +".1E c #f5cbfd", +".Ut c #f5e5e8", +"#AP c #f5ecff", +"#ym c #f5effd", +".Us c #f6e5eb", +"#yl c #f6e8f5", +".1F c #f7d8e7", +".VJ c #f7e6f6", +".XZ c #f7ebf7", +".WK c #f7f2ff", +"#yk c #f8e5f8", +"#tu c #f8e6f6", +".Vv c #f8eaff", +"#sk c #f9e6f9", +".1C c #f9ecff", +".Ue c #fbdbf2", +"#zA c #fbf3ff", +"#x. c #fce9fd", +"#uI c #fdeffc", +"#x# c #fdf0fa", +"#2x c #fefbff", +"#fg c #ffd0d6", +"#fh c #ffe0e5", +".Zc c #fff9ff", +"Qt.Qt#QtaQtbQtcQtdQteQtfQtgQthQtiQtjQtkQtlQtmQtnQtoQtpQtqQtrQtsQttQtuQtvQtwQtxQtyQtzQtAQtBQtCQtDQtEQtFQtGQtHQtIQtJQtKQtLQtMQtNQtOQtPQtQQtRQtSQtTQtUQtVQtWQtXQtYQtZQt0Qt1Qt2Qt3Qt4Qt5Qt6Qt7Qt8Qt9.#..##.#a.#b.#c.#d.#e.#f.#g.#h.#i.#j.#k.#l.#m.#n", +".#o.#p.#q.#r.#s.#t.#u.#v.#w.#x.#y.#z.#A.#B.#C.#D.#E.#F.#G.#H.#I.#J.#K.#L.#M.#N.#O.#P.#Q.#R.#S.#T.#U.#V.#W.#X.#Y.#Z.#0.#1.#2.#3.#4.#5.#6.#7.#8.#9.a..a..a#.aa.ab.ac.ad.ae.af.ag.ah.ai.aj.ak.al.am.an.ao.ap.ap.aq.ar.as.at.au.#h.av.aw.ax.ay.az.aA", +".aB.aC.aD.aE.aF.aG.aH.aI.aJ.aK.aL.aM.aN.aO.aP.aQ.aR.aS.aT.aU.aV.aW.aX.aY.aZ.a0.a1.a2.a3.a4.a5.a6.a7.a8.a9.b..b#.ba.bb.bc.bd.be.bf.bg.bh.bi.bj.bk.bl.bm.bn.bo.bp.bp.bq.br.bs.bt.bu.bv.bw.bx.by.by.bz.bA.bB.bB.bC.bD.bE.bF.bG.bH.bI.bJ.bK.bL.bM.bN", +".bO.bP.bQ.bR.bS.bT.bU.bV.bW.bX.bY.bZ.b0.b1.b2.b3.b4.b5.b6.b7.b8.b9.c..c#.ca.cb.cc.cd.ce.aW.cf.cg.ch.ci.cj.ck.cl.cm.cn.co.cp.cq.cr.cs.ct.cu.cv.cw.cx.cy.cz.cA.cB.cC.cD.cE.cF.cG.cH.cI.cJ.cK.cL.cM.cN.cO.cP.cQ.ax.cR.cS.cT.cU.cV.cW.cX.cY.cZ.c0.c1", +".c2.c3.c4.c5.c6.c7.c8.c9.d..d#.da.db.dc.dd.de.df.dg.dh.di.dj.dk.dl.dm.dn.do.dp.dq.dr.ds.dt.du.ac.dv.dw.dx.dy.dz.dA.dB.dC.cu.dD.dE.dF.dG.dH.dI.dJ.dK.dK.dL.dM.dN.dO.dP.dQ.dR.dS.dT.dU.dV.dW.dX.dX.dY.dZ.dZ.d0.d1.d2.c0.d3.d4.d5.d6.d7.d8.d9.e..e#", +".ea.eb.ec.ed.ee.ef.eg.eh.ei.ej.ek.el.em.en.eo.ep.eq.er.es.et.eu.ev.ew.ex.ey.ez.eA.eB.eC.eD.eE.eF.eG.eH.eI.eJ.eK.eL.eM.eN.eO.eP.eQ.eR.eS.eT.eU.eV.eW.eX.eY.eZ.e0.e1.e2.e3.e4.e5.e6.e7.e8.e9.f..f#.fa.fb.fb.fc.fd.fe.ff.fg.fh.fi.fj.fk.fl.fm.fn.fo", +".fp.fq.fr.fs.ft.fu.fv.fw.fx.fy.fz.fA.fA.fB.fC.fD.fE.fF.fG.fH.fI.fJ.fK.fL.fM.fN.fO.fP.fQ.fR.fS.fT.fU.fV.fW.fX.fY.fZ.f0.f1.cW.f2.f3.f4.f5.f6.f7.f8.f9.g..g#.ga.gb.gc.gd.ge.gf.gg.gh.gi.gj.gj.gk.gk.gl.gm.gn.go.gp.gq.gr.gs.gt.gu.gv.gw.gx.gy.gz.gz", +".gA.gB.gC.gD.gE.gF.gG.gH.gI.gJ.gK.gL.gM.gN.gO.gP.gQ.gR.gS.gT.gU.gV.gW.gX.gY.gZ.g0.g1.g2.g3.g4.g5.g6.g7.g8.bx.g9.f2.h..h#.ha.hb.hc.hd.he.hf.hg.hh.hi.hj.hk.hl.hm.hn.ho.hp.hq.ge.ge.hr.hs.ht.hu.hv.hw.hx.he.hy.hz.hA.hB.hC.hD.hE.hF.hG.hH.hI.hJ.hK", +".hL.hM.hN.hO.hP.hQ.fW.hR.hS.fR.hT.hU.hV.hW.hX.hY.hZ.h0.h1.h2.h3.h4.h5.h6.h7.h7.h8.h9.h8.i..i#.i..fQ.ia.ib.ic.id.ie.if.ig.ih.ii.ij.cC.cA.ik.cx.il.im.in.io.dV.ip.iq.ir.is.it.iu.iv.iw.gT.ix.iy.iz.gz.iA.iB.iC.iD.iE.iF.iG.iH.iI.iJ.iK.iL.iM.iN.iO", +".iP.iQ.iR.iS.d3.iT.iU.iV.iW.iX.iY.iZ.i0.i1.i2.i3.i4.i5.i6.i7.i8.i9.j..j#.ja.jb.jc.jd.fy.je.jf.jg.jh.ji.jj.jk.jl.jm.jn.jo.jp.jq.jr.js.jt.ju.jv.jw.jx.jy.jz.jA.jB.jC.jD.jD.jE.jF.jG.jH.jI.jJ.jK.jL.jM.jN.jO.jP.jQ.jR.jS.jT.jU.jV.jW.jX.jY.jZ.j0.j1", +".j2.j3.gR.j4.j5.j6.j7.j8.hL.hv.jt.jt.hv.gd.gf.j9.jP.k..k#.ka.kb.kc.kd.kd.ke.kf.kg.kh.ki.kj.kk.kl.km.fg.kn.ko.kp.kq.kr.ks.kt.ku.kv.kw.kx.ky.kz.kA.kB.kC.kD.kE.kF.kF.kG.kH.kI.kJ.kK.kL.kM.kN.jr.kO.kP.kQ.kR.kS.kT.kU.kV.kW.kX.kY.kZ.k0.k1.k2.k3.k4", +".k5.k6.k7.k8.k9.l..l#.jI.la.fE.lb.lc.ld.le.iD.lf.lg.lh.li.lj.lk.ll.lm.ln.lo.lp.gW.lq.lq.lr.ls.lt.lu.lv.lw.lx.ly.lz.lA.lB.lC.lD.lE.lF.lG.lH.lI.kT.lJ.lK.lL.lM.lN.lO.lP.lQ.lR.lS.lT.lU.lV.lW.lX.lY.lZ.l0.l1.l2.l3.l4.l5.l6.l7.l8.l9.m..m#.ma.mb.m#", +".mc.md.me.mf.mg.mh.mi.mj.fE.jq.mk.ml.jq.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.mA.b#.mB.mC.mD.mE.mF.mG.mH.mI.mJ.mK.mL.mM.mN.mO.mP.mQ.mR.mS.mT.mU.mV.mW.mX.mY.mZ.m0.m1.m2.m3.m4.m5.m6.m7.m8.m9.n..n#.na.nb.nc.nd.ne.nf.ng.nh.ni.nj.nk.nl.nm.nn", +".no.np.nq.nr.ns.nt.nu.nv.nw.nx.ny.nz.nA.c#.nB.nC.nD.nE.nF.nG.nH.nI.lI.nJ.nK.nL.nM.nN.nO.nP.nQ.nR.nS.nT.nU.nV.nW.nX.nY.nZ.n0.n1.n2.n3.n4.n5.n6.n7.n8.n9.o..o#.oa.ob.oc.od.ee.oe.of.og.oh.oi.oj.ok.ol.om.on.oo.op.oq.or.os.ot.ou.ov.ow.ox.oy.oz.oA", +".oB.oC.oD.oE.oF.oG.oH.oI.oJ.oK.oL.oM.oN.oO.oP.oQ.oR.oS.oT.oU.#G.oV.oV.oW.oX.oY.oZ.o0.o1.o2.o3.o4.o5.o6.o7.o8.o9.p..p#.pa.pb.pc.pd.pe.pf.pg.ph.pi.pj.pk.pl.pm.pn.po.po.pp.pq.pr.ps.pt.pu.pv.pw.px.py.pz.pA.pB.pC.pD.pE.pF.pG.pH.pI.pJ.pK.pL.pM.pN", +".e9.pO.pP.pQ.pR.hX.mp.pS.pT.pU.pV.pW.pX.pY.pZ.p0.p1.p2.p3.p4.p5.p6.p7.p8.p9.q..q#.qa.qb.qc.qd.qe.qf.qg.qh.qi.qj.qk.ql.qm.qn.qo.qp.qq.qr.qs.qt.qu.qv.qw.qx.qy.qz.qA.qB.qC.qD.qE.qF.qG.qH.qI.qJ.qK.qL.qM.qN.qO.qP.qQ.qR.qS.qT.qU.qV.qW.qX.qY.qZ.q0", +".q1.q2.q3.q4.q5.q6.q7.q8.q9.r..r#.ra.rb.rc.rd.re.rf.rg.rh.ri.rj.rk.rl.rm.rn.ro.rp.rq.rr.rs.rt.ru.rv.rw.rx.ry.rz.rA.rB.rC.rD.rE.rF.rG.rH.rI.rJ.rK.rL.rM.rN.rO.rP.rQ.rR.rS.rT.rU.rV.rW.rX.rY.rZ.r0.r1.r2.r3.r4.r5.r6.r6.r7.r8.r9.s..s#.sa.sb.sc.sd", +".se.sf.sg.sh.si.sj.sk.sl.sm.sn.so.sp.sq.sr.ss.st.su.sv.sw.sx.sy.sz.sA.sB.sC.sD.sE.sF.sG.sH.sI.sJ.sK.sL.sM.sN.sO.sP.sQ.sR.sS.sT.sU.sV.sW.sX.sY.sZ.s0.s1.s2.s3.s4.s5.s6.s7.s8.s9.t..t#.ta.tb.tc.td.te.tf.tg.th.ti.tj.tk.tl.tm.tn.to.tp.tq.tr.ts.tt", +".tu.tv.tw.tx.ty.tz.tA.tB.tC.tD.tE.tF.tG.tH.tI.tJ.tK.tL.tM.tN.tO.tP.tQ.tR.tS.tT.tU.tV.tW.tX.tY.tZ.t0.t1.t2.t3.t4.t5.t6.t7.t8.t9.t9.u..u#.ua.ub.ub.uc.ud.ue.uf.ug.uh.ui.uj.uk.ul.um.un.uo.up.uq.ur.us.ut.uu.uv.uw.ux.uy.uz.uA.uB.uC.uD.uE.uF.uG.uH", +".uI.uJ.uK.uL.uM.uN.uO.uP.uQ.uR.uS.uT.uU.uV.uW.uX.uY.uZ.u0.u1.u2.u3.u4.u5.u6.u7.u8.u9.v..v#.va.vb.vc.vd.ve.vf.vg.vh.vi.vj.vk.vl.vm.vn.vo.vp.vq.vr.vs.vt.vu.vv.vw.vx.vy.vz.vA.vB.vC.vD.vE.vF.vG.vH.vI.vJ.vK.vL.vM.tp.vN.vO.vP.uB.vQ.vR.vS.vS.vT.vU", +".vV.vW.vX.vY.vZ.v0.v1.v2.v3.v4.v5.v6.v7.v8.v9.w..w#.wa.wb.wc.wd.we.wf.wg.wh.wi.wj.wk.wl.wm.wn.wo.wp.wq.wr.ws.wt.wu.wv.ww.wx.wy.wz.wA.wB.wC.wD.wE.wF.wG.wH.wI.wJ.wK.wL.wM.wN.wO.wP.wQ.wR.wS.wT.wU.wV.wW.wX.wY.wZ.w0.w1.w2.w3.w4.w4.w5.w6.w7.w8.w8", +".w9.x..x#.xa.xb.xc.xd.xe.xf.xg.xh.xi.xj.xk.xl.xm.xn.xo.xp.xq.xr.xs.xt.xu.xv.xw.xx.xy.xz.xA.xB.xC.xD.xE.xF.xG.xH.xI.xJ.xK.xL.xM.xN.xO.xP.xQ.xR.xS.xT.xU.xV.xW.xX.xY.xZ.x0.x1.x2.x3.x4.x5.x6.x7.x8.x9.y..y#.ya.yb.yc.yd.ye.yf.yg.yg.yh.yi.yj.yk.yl", +".ym.yn.yo.yp.yq.yr.ys.yt.yu.yv.yw.yx.yy.yz.yA.yB.yC.yD.yE.yF.yG.yH.yI.yJ.yK.yL.yM.yN.yO.yP.yQ.yR.yS.yT.yU.yV.yW.yX.yY.yZ.y0.y1.y2.y3.y4.y5.y6.y7.y8.y9.z..z#.za.zb.zc.zd.ze.zf.zg.zh.zi.zj.zk.zl.zm.zm.zn.tm.zo.zp.zq.zr.zs.zt.zu.zv.zw.zx.zy.zz", +".zA.zB.zC.zD.zE.zF.zG.zH.zI.zJ.zK.zL.zM.zN.zO.zP.zQ.zR.zS.zT.zU.zV.zW.zX.zY.zZ.z0.z1.z2.z3.z4.z5.z6.z7.z8.z9.A..A#.Aa.Ab.Ac.Ad.Ae.Af.Ag.Ah.Ai.Aj.Ak.Al.Am.An.Ao.Ap.Aq.Ar.As.At.Au.Av.Aw.Ax.Ay.Az.AA.AB.AC.AD.AE.AF.AG.AH.AI.AJ.zv.AK.AL.AM.AN.AO", +".AP.AQ.AR.AS.AT.AU.AV.AW.AX.AY.AZ.A0.A1.A2.A3.A4.A5.A6.A7.A8.A9.B..B#.Ba.Bb.Bc.Bd.Be.Bf.Bg.Bh.Bi.Bj.Bk.Bl.Bm.Bn.Bo.Bp.Bq.Br.Bs.Bt.Bu.Bv.Bw.Bx.By.Bz.BA.BB.BC.xo.BD.BE.BF.BG.BH.BI.BJ.BK.BL.BM.BN.BO.BP.BQ.BR.BS.BT.BU.BV.BW.BW.BX.BX.BY.BZ.B0.B1", +".B2.B3.B4.B5.B6.B7.B8.B9.C..C#.Ca.Cb.Cc.Cd.Ce.Cf.Cg.Ch.Ci.Cj.Ck.Cl.Cm.Cn.Co.Cp.Cq.Cr.Cs.Ct.Cu.Cv.Cw.Cx.Cy.Cz.CA.CB.CC.CD.CE.CF.CG.CH.CI.CJ.CK.CL.CM.CN.CO.CP.CQ.CR.CS.CT.CU.CV.CW.CX.CY.CZ.C0.C1.C2.C3.C4.C5.C6.C7.C8.C9.BV.BV.D..D..B1.D#.D#.Da", +".Db.Dc.Dd.De.Df.Dg.Dh.Di.Dj.Dk.Dl.Dm.Dn.Do.Dp.Dq.Dr.Ds.Dt.Du.Dv.Dw.Dx.Dy.Dz.DA.DB.DC.DD.DE.DF.DG.DH.DI.DJ.DK.DL.DM.DN.DO.DP.DQ.DR.DS.DT.DU.DV.DW.DX.DY.DZ.D0.D1.D2.D3.D4.D5.D6.D7.D8.D9.E..E#.Ea.Eb.Ec.Ec.Ed.Ee.Ef.Eg.Eh.Ei.Ei.Ej.Ek.Ek.El.El.Em", +".En.Eo.Ep.Eq.Er.Es.Et.Eu.Ev.Ew.Ex.Ey.Ez.EA.EB.EC.ED.EE.EF.EG.EH.EI.EJ.EK.EL.EM.EN.EO.EP.EQ.ER.ES.ET.EU.EV.EW.EX.EY.EZ.E0.E1.E2.E3.E4.E5.E6.E7.E8.E9.F..F#.Fa.Fb.Fc.Fd.Fe.Ff.Fg.Fh.Fi.Fj.Fk.BR.Fl.Fm.Fn.Fo.Fp.Fq.Fr.Fs.Ft.Fu.Fu.Fv.Fw.Fx.Fy.Fy.Fz", +".FA.FB.FC.FD.FE.FF.FG.FH.FI.FJ.FK.FL.FM.FN.FO.FP.FQ.FR.FS.FT.FU.FV.FW.FX.FY.FZ.F0.F1.F2.F3.F4.F5.F6.F7.F8.F9.G..G#.Ga.Gb.rS.Gc.Gd.Ge.Gf.Gg.Gh.Gi.Gj.Gk.Gl.Gm.Gn.Go.Gp.Gq.Gr.Gs.Gt.Gu.Gv.Gw.Gx.Gy.Gz.GA.Gz.GB.GC.GD.GE.GF.GG.GH.GI.GJ.GJ.GJ.GK.GK", +".GL.GM.GN.GO.GP.GQ.GR.GS.GT.GU.GV.GW.GX.GY.GZ.G0.G1.G2.G3.G4.G5.G6.G7.G8.G9.H..H#.Ha.Hb.Hc.Hd.He.Hf.Hg.Hh.Hi.Hj.Hk.Hl.Hm.Hn.Ho.Hp.Hq.Hr.Hs.Ht.Hu.Hv.Hw.Hx.Hy.Hz.HA.HB.HC.HD.HE.HF.HG.HH.HI.HJ.HK.HL.HM.HN.HO.HP.HQ.HR.HS.HT.HT.HT.HU.HU.HV.HV.HV", +".HW.HX.HY.HZ.H0.H1.H2.H3.H4.H5.H6.H7.H8.H9.I..I#.Ia.Ib.Ic.Id.Ie.If.Ig.Ih.Ii.Ij.Ik.Il.Im.In.Io.Ip.Iq.Ir.Is.It.Iu.Iv.Iw.Ix.Iy.Iz.IA.IB.IC.IC.ID.IE.IF.IG.IH.II.IJ.IK.IL.IM.IN.IO.IP.IQ.IR.IS.IT.IU.IV.IW.IX.IY.IZ.I0.I1.I2.I0.I3.I3.I3.I4.I5.I6.I7", +".I8.I9.J..J#.Ja.Jb.Jc.Jd.Je.Jf.Jg.Jh.Ji.Jj.Jk.Jl.Jm.Jn.Jo.Jp.Jq.Jr.Js.Jt.Ju.Jv.Jw.Jx.Jy.Jz.JA.JB.JC.JD.JE.JF.JG.JH.JI.JJ.JK.JL.JM.JN.JO.JO.JP.JQ.JR.JS.JT.JU.JV.JW.JX.JY.JZ.J0.J1.J2.J3.J4.J5.J6.JQ.J7.J8.J9.K..K#.Ka.Kb.Kc.Kc.Kd.Kd.Ke.Kf.Kg.Kh", +".Ki.Kj.Kk.Kl.Km.Kn.Ko.Kp.Kq.Kr.Ks.Kt.Ku.Kv.Kw.Kx.Ky.Kz.KA.KB.KC.KD.KE.KF.KG.KH.KI.KJ.KK.KL.KM.KN.KO.KP.KQ.KR.KS.KT.KU.KV.KW.KX.KY.KZ.K0.K1.K2.K3.K4.K5.K6.K7.K8.K9.L..L#.La.Lb.Lc.Ld.Le.Lf.Lg.Lh.Li.Lj.Lk.K9.K9.Ll.Ll.Lm.Ln.Lo.Lp.Lq.Lr.Ls.Lt.L.", +".Lu.Lv.Lw.Lx.Ly.Lz.LA.LB.LC.LD.LE.LF.LG.LH.LI.LJ.LK.LL.LM.LN.LO.LP.LQ.LR.LS.LT.LU.LV.LW.LX.LY.LZ.L0.L1.L2.L3.L4.L5.L6.L7.L8.L9.M..M#.Ma.Mb.Mc.Md.Me.Me.Mf.Mg.Mh.Mi.Mj.Mk.Ml.Mm.Mn.Mo.Mp.Mq.Mr.Ms.Mt.Mu.Mv.Mw.Mx.My.My.Mz.MA.MB.MC.MD.ME.MF.MG.MH", +".MI.MJ.MK.ML.MM.MN.MO.MP.MQ.MR.MS.MT.MU.MV.MW.MX.MY.MZ.M0.M1.M2.M3.M4.M5.M6.M7.M8.M9.N..N#.Na.Nb.Nc.Nd.Ne.Nf.Ng.Nh.Ni.Nj.Nk.Nl.Nm.Nn.No.Iu.Np.Nq.Nr.Ns.Nt.Nu.Nv.Nw.Nx.BE.Ny.Nz.NA.Nv.NB.NC.ND.NE.NF.NG.NH.NI.NJ.NK.NK.NL.NM.NN.NO.NP.NQ.NR.NS.NT", +".NU.NV.NW.NX.NY.NZ.N0.N1.N2.N3.N4.N5.N6.N7.N8.N9.O..O#.Oa.Ob.Oc.Od.Oe.Of.Og.Oh.Oi.Oj.Ok.Ol.Om.On.Oo.Op.Oq.Or.Os.Ot.Ou.Ov.Ow.Ox.Oy.Oz.OA.OB.OC.OD.OE.OF.OG.OH.OI.OJ.OK.OL.OM.ON.OO.OP.OQ.OR.OS.OT.OU.OV.OW.OX.OY.OZ.O0.O1.O2.O3.O3.O3.O4.O5.O6.O6", +".O7.O8.O9.P..P#.Pa.Pb.Pc.Pd.Pe.Pf.Pg.Ph.Pi.Pj.Pk.Pl.Pm.Pn.Po.Pp.Pq.Pr.Ps.Pt.Pu.Pv.Pw.Px.Py.Pz.PA.PB.PC.PD.PE.PF.PG.PH.PI.PJ.PK.PL.PM.PN.PO.PP.PQ.PR.PS.PT.PU.PV.PW.PX.PY.PZ.P0.P1.P2.P3.P4.P5.P6.P7.P8.P9.Q..Q#.Qa.Qb.Qc.Qd.Qe.Qf.Qg.Qh.Qh.Qi.Qj", +".Qk.Ql.Qm.Qn.Qo.Qp.Qq.Qr.Qs.Qt.Qu.Qv.Qw.Qx.Qy.Qz.QA.QB.QC.QD.QE.QF.QG.QH.QI.QJ.QK.QL.QM.QN.QO.QP.QQ.QR.QS.QT.QU.QV.QW.QX.QY.QZ.Q0.A#.Q1.Q2.Q3.Q4.Q5.Q6.Q7.Q8.Q9.R..R#.Ra.Rb.Rc.Rd.Re.Rf.Rg.Rh.Ri.Rj.Rk.Rl.Rm.Rn.Ro.Rp.Rq.Rr.Rs.Rt.Ru.Rv.My.Rw.Rx", +".Ry.Rz.RA.RB.RC.RD.RE.RF.RG.RH.RI.RJ.RK.RL.RM.RN.RO.RP.RQ.RR.RS.RT.RU.RV.RW.RX.RY.RZ.R0.R1.R2.R3.R4.R5.R6.R7.R8.R9.S..S#.Sa.Sb.Sc.Sd.Se.Sf.Sg.Sh.Si.Sj.Sk.Sl.Sm.Sn.So.Sp.Sq.Sr.Ss.St.Su.Sv.Dp.Sw.Jx.Sx.Sy.Sz.SA.SB.SC.SD.SE.SF.SG.SH.SI.SJ.SK.SL", +".SM.SN.SO.SP.SQ.SR.SS.ST.SU.SV.SW.SX.SY.SZ.S0.S1.S2.S3.S4.S5.S6.S7.S8.S9.T..T#.Ta.Tb.Tc.Td.Te.Tf.Tg.Th.Ti.Tj.Tk.Tl.Tm.Tn.To.Tp.Tq.Tr.Ts.Tt.Tu.Tv.Tw.Tx.Ty.Tz.TA.TB.TC.TD.TE.TF.TG.TH.TI.TJ.TK.TL.TM.TN.TO.TP.TQ.TR.TS.TT.TU.TV.TW.TX.TY.TZ.T0.T1", +".T2.T3.T4.T5.T6.T7.T8.T9.U..U#.Ua.Ub.Uc.Ud.Ue.Uf.Ug.Uh.Ui.Uj.Uk.Ul.Um.Un.Uo.Up.Uq.Ur.Us.Ut.Uu.Uv.Uw.Ux.Uy.Uz.UA.UB.UC.UD.UE.UF.UG.UH.UI.UJ.UK.UL.UM.UN.UO.UP.UQ.UR.US.UT.UU.UV.UW.UX.UY.UZ.U0.U1.U2.U3.U4.U5.U6.U7.U8.U9.V..V#.Va.Vb.Vc.Vd.Ve.Vf", +".Vg.Vh.Vi.Vj.Vk.Vl.Vm.Vn.Vo.Vp.Vq.Vr.Vs.Vt.Vu.Vv.Vw.Vx.Vy.Vz.VA.VB.VC.VD.VE.VF.VG.VH.VI.VJ.VK.VL.VM.VN.VO.VP.VQ.VR.VS.VT.VU.VV.VW.VX.VY.VZ.V0.V1.V2.V3.V4.V5.V6.V7.V8.V9.W..W#.Wa.Wb.Wc.Wd.We.Wf.Wg.Wh.Wi.uq.Wj.qF.Wk.Wl.Wm.Wn.Wo.Wp.Wq.Wr.Ws.Wt", +".Wu.Wv.Ww.Wx.Wy.Wz.WA.WB.WC.WD.WE.WF.WG.WH.WI.WJ.WK.WL.WM.WN.WO.WP.WQ.WR.WS.WT.WU.WV.WW.WX.WY.WZ.W0.W1.W2.W3.W4.W5.W6.W7.W8.W9.X..X#.Xa.Xb.Xc.Xd.Xe.Xf.Xg.Xh.Xi.Xj.Xk.Xl.Xm.Xn.Xo.sN.Xp.Xq.Xr.Xs.Xt.Xu.Xv.Xw.Xx.Xy.Xz.XA.XB.XC.XD.XE.XF.XG.XH.XI", +".XJ.XK.XL.XM.XN.XO.XP.XQ.XR.XS.XT.XU.XV.XW.XX.XY.XZ.X0.X1.vg.X2.X3.X4.X5.X6.WR.X7.X8.X9.Y..Y#.Ya.Yb.Yc.Yd.Ye.Yf.Yg.Yh.Yi.Yj.Yk.Yl.Ym.Yn.Yo.Yp.Yq.Yr.Ys.Yt.Yu.Yv.Yw.Yx.Yy.Yz.YA.YB.YC.YD.YE.YF.YG.YH.YI.YJ.YK.YL.YM.YN.YO.YP.YQ.YR.YS.YT.YU.YV.YW", +".YX.YY.YZ.Y0.Y1.Y2.Y3.Y4.Y5.Y6.Y7.Y8.Y9.Z..Z#.Za.Zb.Zc.Zd.Ze.Zf.Zg.Zh.Zi.Zj.Zk.Zl.Zm.Zn.Zo.Zp.Zq.Zr.Zs.Zt.Zu.Zv.Zw.Zx.Zy.Zz.ZA.ZB.ZC.ZD.ZE.ZF.ZG.ZH.ZI.ZJ.ZK.ZL.ZM.ZN.ZO.ZP.ZQ.ZR.ZS.ZT.ZU.ZV.ZW.ZX.ZY.ZZ.Z0.Z1.Z2.Z3.Z4.Z5.Z6.Z7.Z8.Z9.0..0#.0a", +".0b.0c.0d.0e.0f.0g.0h.0i.0j.0k.0l.0m.0n.0o.0p.0q.0r.0s.0t.0u.0v.0w.0x.0y.0z.0A.0B.0C.0D.0E.0F.0G.0H.0I.0J.0K.X1.0L.0M.0N.0O.0P.0Q.0R.0S.0T.0U.0V.0W.0X.0Y.0Z.00.01.02.03.04.05.06.07.ZX.08.09.1..1#.1a.1b.1c.1d.1e.1f.1g.1h.1i.1j.1k.1l.1m.1n.1o", +".1p.1q.1r.1s.1t.1u.1v.1w.1x.1y.1z.1A.1B.1C.1D.1E.1F.1G.1H.1I.1J.1K.1L.1M.1N.1O.1P.1Q.1R.1S.1T.1U.1V.1W.1X.1Y.1Z.10.11.12.13.14.15.16.17.18.19.2..2#.2a.2b.2c.2d.2e.2f.2g.2h.2i.2j.2k.2l.2m.2n.2o.2p.2q.2r.2s.2t.2u.2v.2w.2x.2y.2z.2A.XF.2B.2C.2D", +".2E.2F.2G.2H.2I.2J.2K.2L.2M.2N.2O.2P.2Q.2R.2S.2T.2U.2V.2W.2X.2Y.2Z.20.21.22.23.24.25.26.27.28.29.3..3#.3a.3b.3c.3d.3e.3f.3g.3h.3i.3j.3k.3l.3m.3n.3o.3p.3q.3r.3s.3t.3u.3v.3w.3x.3y.3y.3z.3A.3B.3C.3D.3E.3F.3G.3H.3I.3J.3K.3L.2t.3M.3N.1l.3O.3P.3Q", +".3R.3S.3T.3U.3V.3W.3X.3Y.3Z.30.31.32.33.34.35.36.37.38.39.4..4#.4a.4b.4c.4d.4e.4f.4g.4h.4i.4j.4k.4l.4m.4n.4o.4p.4q.4r.4s.4t.4u.4v.4w.4x.4y.4z.4A.4B.4C.4D.4E.4F.4G.4H.4I.4J.4K.4L.4M.4N.4O.4P.4Q.4R.4S.4T.4U.4V.4W.4X.4Y.4Z.40.41.42.Av.43.44.45", +".46.47.48.49.5..5#.5a.5b.5c.5d.5e.5f.5g.5h.5i.5j.5k.5l.5m.5n.5o.5p.5q.5r.5s.5t.5u.5v.5w.5x.5y.5z.5A.5B.Hx.5C.5D.5E.5F.5G.5H.5I.5J.5K.5L.5M.5N.5O.5P.5Q.5R.5S.5T.5U.5V.5W.5X.5Y.5Z.50.51.52.53.54.3F.55.56.57.57.58.59.59.Xz.6..6#.6a.6b.6c.6d.6e", +".6f.6g.6h.6i.6j.6k.6l.6m.6n.6o.6p.6q.6r.6s.6t.6u.6v.6w.6x.6y.6z.6A.6B.6C.6D.6E.6F.6G.6H.6I.GP.6J.6K.6L.6M.6N.6O.6P.6Q.6R.6S.6T.6U.6V.6W.6X.6Y.6Z.60.61.62.63.64.65.66.67.68.69.7..7#.7a.7b.7c.7c.7d.7e.7f.3K.7g.7h.7i.7i.7j.7k.7l.7m.7n.7o.7p.7q", +".7r.7s.7t.7u.7v.7w.7x.7y.7z.7A.7B.7C.7D.7E.37.7F.7G.7H.7I.7J.7K.7L.7M.7N.7O.7P.7Q.7R.7S.7T.7U.7V.7W.7X.7Y.7Z.70.71.72.73.74.75.76.77.78.79.8..8#.8a.8b.8c.8d.8e.8f.8g.8h.8i.8j.8k.8l.8m.8n.8o.8p.8q.8r.8s.8t.8u.7N.8v.8v.8w.8x.8y.8z.8A.8B.8C.8D", +".8E.8F.8G.8H.8I.8J.8K.8L.8M.8N.8O.8P.8Q.8R.8S.8T.8U.8V.8W.8X.8Y.8Z.80.81.82.83.84.85.86.87.88.89.9..9#.9a.9b.9c.9d.9e.9f.9g.9h.9i.9j.9k.9l.9m.9n.9o.9p.9q.9r.9s.9t.9u.9v.9w.9x.9y.9z.9A.9B.9C.8p.9D.9D.9E.9F.9G.9H.9I.9J.9K.9L.9M.9N.9O.9P.9Q.9R", +".9S.9T.9U.9V.9W.9X.9Y.9Z.90.91.92.93.94.95.96.97.98.99#..#.##.a#.b#.c#.d#.e#.f#.g#.h#.i#.j#.k#.l#.m#.n#.o#.p#.q#.r#.s#.t#.u#.v#.w#.x#.y#.z#.A#.B#.C#.D#.E#.F#.G#.H#.I#.I#.J#.K#.L#.M#.N#.O#.P#.Q#.R#.S.7f#.T#.U#.V#.W#.W#.X.9G#.Y#.Z#.0#.1#.2#.3", +"#.4#.5#.6#.7#.8#.9##.#####a##b##c##d##e##f##g##h##i##j##k##l##m##n##o##p##q##r##s##t##u##v##w##x##y##z##A##B##C##D##E##F##G##H##I##J##K##L##M##N##O##P##Q##R##S##T##U##V##W##X##Y##Z##0##1##2##3##4##5##6##7##7##8##9#a.#a##aa#ab#ac#ad#ae#.0#af", +"#ag#ah#ai#aj#ak#al#am#an#ao#ap#aq#ar#as#at#au#av#aw#ax#ay#az#aA#aB#aC#aD#aE#aF#aG#aH#aI#aJ#aK#aL#aM#aN#aO#aP#aQ#aR#aS#aT#aU#aV#aW#aX#aY#aZ#a0#a1#a2#a3#a4#a5#a6#a7#a8#a9#b.#b##ba#bb#bc#bd#be#bf#bg.4S#bh#bi#bj.7f##8.8r#bk.54#bl#bm#bn#bo#bp#bq", +"#br#bs#bt#bu#bv#bw#bx#by#bz#bA#bB#bC#bD#bE#bF#bG#bH#bI#bJ#bK#bL#bM#bN#bO#bP#bQ#bR#bS#bT#bU#bV#bW#bX#bY#bZ#b0#b1#b2#b3#b4#b5#b6#b7#b2#b8#b9#c.#c##ca.eu#cb#cc#cd#ce#cf#c##cg#ch#ci#cj#ck.9K#cl#cm#cn#co#cp#cq#cr#cs#ct#cu#cv#cw#cx#cy#cz#cA#cB#cC", +"#cD#cE#cF#cG#cH#cI#cJ#cK#cL#cM#cN#cO#cP#cQ#cR#cS#cT#cU#cV#cW#cX#cY#cZ#c0#c1#c2#c3#c4#c5#c6#c7#c8#c9#d.#d##da#db#dc#dd#de#df#dg#dh#di#dj#dk.ph#dl#dm#dn#do#dp#dq#dr#ds#dt#du#du#dv#dw#dx#dy#dz#dA#dB#dC#dD#dE#dF#dG#dH#dI#dJ#dK#.m#dL#dM#cA#dN#dO", +"#dP#dQ#dR#dS#dT#dU#dV#dW#dX#dY#dZ#d0#d1#d2#d3#d4#d5#d6#d7#d8#d9#e.#e##ea#eb#ec#ed#ee#ef#eg#eh#ei#ej#ek#el#em#en#eo#ep#eq#er#es#et#eu#ev#ew#ex#ey.hQ#ez#eA#eB#eC#eD#eE#eF#eG#eH#eI#eJ#eK#eL#eM#eN#eO#eP#eQ#eR#eS#eT#eU#eV#cy#eW#dL#dM#eX#eY#eZ#eK", +"#e0#e1#e2#e3#e4#e5#e6#e7#e8#e9#f.#f##fa#fb#fc#fd#fe#ff#fg#fh#fi#fj#fk#fl#ee#fm#fn#fo#fp#fq#fr#fs#ft#fu#fv#fw#fx#fy#fz#fA#fB#fC#fD#fE#fF#fG#fH#fI#fJ#fK#fL#fM#fN#fO#fP#fQ#fR#fS#fT#fU#eH#fV#fW#fX#fY#fY#fZ#f0#f1#f2#f3#f4#f5#f5#f5#f6#f7#f8#f9#g.", +"#g##ga#gb#gc#gd#ge#gf#gg#gh#gi#gj#gk#gl#gm#gn#go#gp#gq#gr#gs#gt#gu#gv#gw#gx#gy#gz#gA#gB#gC#gD#gE#gF#gG#gH#gI#gJ#gK#gL#gL#gM#gN#gO#gP#gQ#gR#gS#gT#gU#gV#gW#gX#gY#gZ#g0#g1#g2#g3#g4#g5#g6#g7#g8#g9#h.#h##ha#hb#hc#hd#he#hf#hg#hh#hi#hj#hk#hl#hm#hn", +"#ho#hp#hq#hr#hs#ht#hu#hv#hw#hx#hy#hz#hA#hB#hC#hD#hE#hF#hG#hH#hI#hJ#hK#hL#hM#hN#hO#hP#hQ#hR#hS#hT#hU#hV#hW#gH#hX#hY#hZ#hR#h0#h1#h2#h3#h4#h5#h6#h7#h8#h9#i.#i##ia#ib#ic#id#ie#if#ig#ih#ii#ij#ik#il#im.hj#in#io#ip#iq#ir#is#it#iu#iv#iw#ix#iy#iz#iA", +"#iB#iC#iD#iE#iF#iG#iH#iI#iJ#iK#iL#iM#iN#iO#iP#iQ#iR#iS#iT#iU#iV#iW#iX#iY#iZ#i0#iZ#i1#i2#i3#i4#i5#i6#i7#i8#i9#j.#j##j##ja#jb#jc#jd#je#jf#jg#jh#ji#jj#jk#jl#jm#i.#jn#jo#jp#jk#jq#jr#js#jt#ju#jv#jw#jx#jy#jz#jA#jB#jC#jD#jE#jF#jG#jH#jI#jJ#jK#jL#jM", +"#jN#jO#jP#jQ#jR#jS#jT#jU#jV#jW#jX#hy#jY#jZ#j0#j1#j2#j3#j4#j5#j6#j7#j8#j9#k.#jo#k##ka#kb#kc#kd#ke#kf#kg#kh#ki#kj#kk#kl#km#kn#ko#kp#kq#kr#ks#kt#ku#kv#kw#kx#ky#kz#i.#kA#kB#kC#kD#kE#kF#kG#kH#kI#kJ#kK#kL#kM#kN#kO#kP#kQ#kR#kS#kT#kU#kV#kW#kX#kY#kZ", +"#k0#k1#k2#k3#k4#k5#k6#k7#k8#k9#l.#l##la#lb#lc#ld#le#lf#lg#lh.Cx#li#lj#lk#ll#lm#ln#lo#lp#lq#lr#ls#i3#lt#lu#lv#lw#lx#ly#lz#lA#lB#lC#lD#lE#lF#lG#lH#lI#lJ#lK#lK#lL#lM#lN#lO#lP#lQ#lR#lS#lT#lU#lV#lW#lX#lY#lZ#l0#l0#l1#l2#l3#l4#l5#l6#l7#l8#l9#m.#m#", +"#ma#mb#mc#md#me#mf#mg#mh#mi#mj#mk#ml#mm#mn#mo#mp#mq#mr#ms#mt#mu#mv#mw#mx#my#mz#mA#mB#mC#i1#mD#mE#mF#mG#mH#mI#ja#mJ#mK#mL#mM#mN#mO#mP#hW#mQ#mR#mS#mT#mU#mV#mV#mW#mX#mY#mZ#m0#m1#m2#m3#m4#m5#m6#m7#m8#m9#n.#n##na#n##nb#nc#nd#l4#ne#l6#nf#ng#nh#ni", +"#nj#nk#nl#nm#nn#no#np#nq#nr#ns#nt#nu#nv#nw#nx#ny#nz#nA#nB#nC#nD#nE#nF#nG#nH#nI#nJ#nK#nL#nM#nN#nO#nP#nQ#nQ#nR#nS#nT#nU#kb#nV#mV#nW#nX#nY#nZ#mE#n0#n1#n2#n3#n4#n5#aq#n6#n7#n8#n9#o.#o##oa#ob#oc#od#oe#of#og#oh#oi#oj#ok#ol#om#on#oo#op#oq#or#os#ot", +"#ou#ov#ow#ox#oy#oz#oA#oB#oC#oD#oE#oF#oG#oH#oI#oJ#oK#oL#oM#oN#oO#oP#oQ#oR#oS#oT#oU#oV#oW#oX#oY#oZ#o0#o1#o2#nQ#o3#o4#lq#o5#n6#o6#o7#o8#o9#p.#p##pa#pb#pc#o5#pd#pe#pf#nU#pg#ph#pi#pj#pk#pl#pm#pn#po#pp#pq#pr#ps#pt#pu#pv#pw#px#py#pz#pA#pB#pC#pD#pE", +"#pF#pG#pH#pI#pJ#pK#pL#pM#pN#pO#pP#pQ#oG#pR#pS#pT#pU#pV#pW#pX#pY#pZ#p0#p1#p2#p3#p4#p5#p6#p7#p8#p9#q.#q##qa#qb#n1#qc#qd#qe#qf#qg#qh#qi#qj#qk#ql#qm#qn#qo#qp#qq#qr#qs#qt#qu#qv#qw#qx#qy#qz#qA#qB#qC#qD#qE#qF#qG#qH#qI#qJ#qK#qL#qM#qN#qO#py#qP#qQ#qR", +"#qS#qT#qU#qV#qW#qX#qY#qZ#q0#q1#q2#q3#q4#q5#q6#q7#q8#q9#r.#r##ra#rb#rc#rd#re#rf#rg#rh#ri#rj#rk#rl#rm#rn#qd#ro#rp#rq#rr#rs#rt#ru#rv#rw#rx#ry#rz#fq#rA#rB#rA#rC#rD#rE#rF#rG#rH#rH#rI#rJ#rK#rL#rM#rN#rO#rP#rQ#rR#rS#rT#rU#rV#rW#rX#rY#rZ#r0#r1#r2#r3", +"#r4#r5#r6#r7#r8#r9#s.#s#.8M#sa#sb#sc#sd#se#sf#sg#sh#si#sj#sk#sl#sm#sn#so#sp#sq#sr#ss#st#su#sv#sw#sx#sy#sz#sA#sB#sC#sD#sE#sF#sG#sH#sI#sJ#sK#sL#sM#sN#sO#sP#sQ#sQ#sR#sR#sS#sT#sU#sU#sV#sW#sX#rV#rV#sY#sZ#s0#s1#s2#s3#s4#s5#s6#s7#s8#s9#t.#t##ta#tb", +"#tc#r4#td#te#tf#tg#th#ti#tj#tk#tl#tm#tn#to#tp#tq#tr#ts#tt#tu#tv#tw#tx#ty#tz#tA#tB#tC#tD#tE#tF#tG#tH#tI#tJ#tK#tL#tM#tN#kt#tO#tP#tQ#tR#tS#tT#tU#tV#tW#tX#tY#tZ#t0#t1#t2#t2#t3#t4#t5#t6#t7#t8#t9#u.#u##ua#ub#uc#ud#ue#uf#ug#uh#ui#uj#uk#ul#um#un#uo", +"#up#uq#ur#us#ut#uu#uv#uw#ux#uy#uz#uA#uB#uC#uD#uE#uF#uG#uH#uI#uJ#uK#uL#uM#uN#uO#uP#uQ#uR#uS#uT#uU#uV#uW#uX#uY#uZ#u0#u1#u2#u3#u4#u5#u6#u7#u8#u9#v.#v##va#vb#vc#vd#ve#vf#vg#vh#vi#vj#vk#vl#vm#vn#vo#vp#vq#vr#vs#vt#vu#vv#vw#vx#vy#vz#vA#vB#vC#vD#vE", +"#vF#vG#vH#vI#vJ#vK#vL#vM#vN#vO#vP#vQ#vR#vS#vT#vU#vV#vW#vX#uI#vY#vZ#v0#v1#v2#v3#v4#v5#v6#v7#v8#v9#w.#w##wa#wb#wc#wd#we#wf#wg#wh#wi#wj#wk#wl#wm#wn#wo#wp#wq#wr#qG#ws#wt#wu#wv#ww#wx#wy#wz#wA#wB#wC#wD#wE#wF#wG#wH#wI#wJ#wK#wL#wM#wN#wO#wP#wQ#qA#wR", +"#wS#wT#wU#wV#wW#wX#wY#wZ#w0#w1#w2#w3#w4#w5#w6#w7#w8#w9#x.#x##xa#xb#xc#xd#xe#xf#xg#xh#xi#xj#ss#xk#xl#xm#xn#xo#xp#xq#xr#xs#xt#xu#xv#xw#xx#xy#xz#xA#xB#n5#xC#xD#xE#xF#xG#xH#xI#xJ#xK#xL#xM#xN#xO#xP#xQ#xR#xS#xT#xU#xV#xW#xX#xY#xZ#x0#qK#rN#x1#x2#x3", +"#x4#x5#x6#x7#x8#x9#y.#y##ya#yb#yc#yd#ye#yf#yg#yh#yi#yj#yk#yl#ym#yn#yo#yp#hp#yq#yr#ys#yt#yu#yv#yw#yx#yy#yz#yA#yB#yC#yD#yE#yF#yG#yH#yI#yJ#yK#yL#yM#yN#yO#yP#yQ#yR#yS#yT#yU#yV#yW#yX#yY#yZ#y0#y1#y2#y3#y4#y5#y6#y7#y8#y9#z.#z##za#zb#zc#zd#pb#ze#zf", +"#zg#zh#zi#zj#zk#zl#zm#zn#zo#zp#zq#zr#zs#zt#zu#zv#zw#zx#zy#zz#zA#zB#zC#zD#zE#zF#zG#zH#zI#zJ#zK#zL#zM#zN#zO#zP#zQ#zR#zS#zT#zU#zV#zW#zX#zY#zZ#z0#z1#z2#z3#z4#z5#z6#z7#z8#z9#A.#A##Aa#Ab#Ac#Ad#Ae#Af#Ag#Ah#Ai#Aj#Ak#Al#Am#An#Ao#Ap#Aq#Ar#As#At#Au#Av", +"#Aw#Ax#Ay#Az#AA#AB#AC#AD#AE#w1#AF#AG#AH#AI#AJ#AK#AL#AM#AN#AO#AP#AQ#AR#AS#AT#AU#AV#AW#AX#AY#AZ#A0#A1#A2#A3#A4#A5#A6#A7#A8#A9#B.#B##Ba#Bb#Bc#Bd#Be#Bf#wg#Bg#Bh#Bi#Bj#Bk#Bl#Bm#Bn#Bo#Bp#Bq#Br#Bs#Bt#Bu#Bv#Bw#Bx#By#Bz#BA#BB#BC#BD#BE#BF#BG#BH#BI#BJ", +"#BK#BL#BM#BN#BO#BP#BQ#BR#BS#BT#BU#BV#iO#BW#BX#BY#BZ#B0#B1#B2#B3#B4#B5#B6#B7#B8#B9#C.#C##Ca#Cb#Cc#Cd#Ce#Cf#Cg#Ch#Ci#Cj#Ck#Cl#Cm#Cn#Co#Cp#Cq#Cr#Cs#Ct#Cu#Cv#Cw#Cx#Cy#Cz#CA#CB#CC#CD#CE#CF#CG#CH#CI#j9#CJ#qK#CK#CL#CM#c3#CN#CO#CP#CQ#CR#CS#CT#CU#CV", +"#CW#CX#CY#CZ#C0#C1#C2#C3#C4#C5#C6#C7#C8#C9#D.#D##Da#Db#Dc#Dd#De#Df#Dg#Dh#Di#Dj#Dk#Dl#Dm#Dn#Do#Dp#Dq#Dr#Ds#Dt#Du#Dv#Dw#Dx#Dy#Dz#DA#DB#DC#DD#DE#DF#DG#DH#DI#DJ#DK#DL#DM#DN#DO#DP#DQ#DR#DS#DT#DU#DV#pi#DW#ug#DX#DY#DZ#D0#D1#D2#D3#D4#D5#D6#D7#D8#D9", +"#E.#E##Ea#Eb#Ec#Ed#Ee#Ef#Eg#Eh#Ei#Ej#Ek#El#Em#En#Eo#Ep#Eq#Er#Es.Ym#Et#Eu#Ev#Ew#Ex#Ey#Ez#EA#EB#EC#ED#EE#EF#EG#EH#EI#EJ#EK#EL#EM#EN#EO#EP#EQ#ER#ES#ET#EU#EV#EW#EX#EY#EZ#E0#E1#E2#qy#E3#E4#E5#E6#E7#E8#E9#F.#F##tY#Fa#Fb#Fc#Fd#Fe#Ff#Fg#Fh#Fi#Fj#Fk", +"#Fl#Fm#Fn#Fo#Fp#Fq#Fr#Fs#Ft#Fu#Fv#Fw#Fx#Fy#Fz#FA#FB#FC#FD#FE#FF#FG#FH#FI#FJ#FK#FL#FM#FN#FO#FP#FQ#FR#FS#FT#FU#FV#FW#FX#FY#FZ#F0#F1#F2#F3#F4#F5#F6#F7#F8#F9#G.#G##Ga#Gb#Gc#Gd#Ge#Gf#Gg#Gh#Gi#Gj#Gk#Gl#Gm#Gn#Go#BE#Gp#Gq#Gr#Gs#Gt#Gu#Gv#Gw#Gx#Gy#Gz", +"#GA#GB#GC#GD#GE#GF#GG#GH#GI#GJ#GK#GL#GM#GN#GO#GP#GQ#GR#GS#GT#GU#GV#GW#GX#GY#GZ#G0#G1#G2#G3#G4#G5#G6#G7#G8#G9#H.#H##Ha#Hb#Hc#Hd#He#Hf#Hg#Hh#Hi#Hj#Hk#Hl#Hm#Hn#Ho#Hp#Hq#Hr#Hs#Ht#Hu#Hv#Hw#Hx#Hy#Hz#HA#kh#HB#HC#HD#HE#HF#HG#HH#HI#HJ#HK#HL#HM#HN#HO", +"#HP#HQ#HR#HS#HT#HU#HV#HW#HX#HY#HZ#H0#H1#H2#H3#H4#H5#H6#H7#H8#H9#I.#I##Ia#Ib#Ic#Id#Ie#If#Ig#Ih#Ii#Ij#Ik#Il#Im#In#Io#Ip#Iq#Ir#Is#It#Iu#Iv#Iw#Ix#Iy#Iz#IA#IB#IC#ID#IE#IF#IG#IH#II#IJ#IK#IL#IM#IN#IO#IP#IQ#IR#IS#IT#IU#IV#IW#IX#IY#IZ#I0#I1#I2#I3#I4", +"#I5#I6#I7#I8#I9#J.#J##Ja#Jb#Jc#Jd#Je#Jf#Jg#Jh#Ji#Jj#Jk#Jl#Jm#Jn#Jo#Jp#Jq#Jr#Js#Jt#Ju#Jv#Jw#Jx#Jy#Jz#JA#JB#JC#JD#JE#JF#JG#JH#JI#JJ#JK#JL#JM#JN#JO#JP#JQ#JR#JS#JT#JU#JV#JW#JX#ET#JY#JZ#J0#J1#J2#J3#J4#J5#J6#J7#J8#J9#K.#K##Ka#Kb#Kc#Kd#Ke#Kf#Kg#Kh", +"#Ki#Kj#Kk#Kl#Km#Kn#Ko#Kp#Kq#Kr#Ks#Kt#Ku#Kv#Kw#Kx#Ky#Kz#KA#KB#KC#KD#KE#KF#KG#KH#KI#KJ#KK#KL#KM#KN#KO#KP#KQ#KR#KS#KT#KU#KV#KW#KX#KY#KZ#K0#K1#K2#K3#K4#K5#K6#K7#K8#K9#L.#L##La#Lb#Lc#Ld#Le#Lf#Lg#Lh#Li#Lj#Lk#Ll#Lm#Ln#jq#Lo#Lp#Lq#Lr#Ls#Lt#Lu#Lv#Lv", +"#Lw#Lx#Ly#Lz#LA#LB#LC#LD#LE#LF#LG#LH#LI#LJ#LK#LL#LM#LN#LO#LP#LQ#LR#LS#LT#LU#LV#LW#LX#LY#LZ#L0#L1#L2#L3#L4#L5#L6#L7#L8#L9#M.#M##Ma#Mb#Mc#Md#Me#Mf#Mg#Mh#Mi#Mj#Mk#Ml#Mm#Mn#Mo#Mp#Mq#Mr#Ms#Mt#Mu#Mv#Mw#Mx#My#m0#Mz#MA#MB#MC#MD#ME#MF#MG#MH#MI#MJ#MJ", +"#MK#ML#MM#MN#MO#MP#MQ#MR#MS#MT#MT#MU#MV#MW#MX#MY#MZ#M0#M1#M2#M3#M4#M5#M6#M7#M8#M9#N.#N##Na#Nb#Nc#Nd#Ne#Nf#Ng#Nh#Ni#Nj#Nk#Nl#Nm#Nn#No#Np#Nq#Nr#Ns#Nt#Nu#Nv#Nw#Nx#Ny#Nz#NA#NB#NC#ND#NE#NF#NG#NH#NI#NJ#NK#NL#NM#NN#NO#NP#NQ#NR#NS#NT#NU#NV#NW#NX#NY", +"#NZ#N0#N1#N2#N3#N4#N5#N6#N7#N8#N9#O.#O##Oa#Ob#Oc#Od#Oe#Of#Og#Oh#Oi#Oj#Ok#Ol#Om#On#Oo#Op#Oq#Or#Os#Ot#Ou#Ov#Ow#Ox#Oy#Oz#OA#OB#OC#KM#OD#OE#OF#OG#OH#OI#OJ#OK#OL#OM#ON#OO#OP#OQ#OR#OS#OT#OU#OV#OW#OX#OY#OZ#O0#O1#O2#O3#O4#O5#O6#O7#h##O8#O9#P.#P##Pa", +"#Pb#MQ#Pc#Pd#Pe#Pf#Pg#Ph#Pi#Pj#Pk#Pl#Pm#Pn#Po#Pp#Pq#Pr#Ps#Pt#Pu#Pv#Pw#Px#Py#Pz#PA#PB#PC#PD#PE#PF#PG#PH#PI#PJ#PK#PL#PM#PN#PO#PP#PQ#PR#PS#PT#PU#PV#PW#PX#PY#PZ#P0#P1#P2#P3#P4#P5#P6#P7#P8#P9#Q.#Q##Qa#Qb.po#Qc#Qd#Qe#Qf#Qg#Qh#Qi#Qj#Qk#Ql#Qm#Qn#Qo", +"#Qp#Qq#Qr#Qs#Qt#Qu#Qv#Qw#Qx#Qy#Qz#QA#QB#QC.FI#QD#QE#QF#QG#QH#QI#QJ#QK#QL#QM#QN#QO#QP#QQ#QR#QS#QT#QU#QV#QW#QX#QY#QZ#Q0#Q1#Q2#Q3#Q4#Q5#Q6#Q7#Q8#Q9#R.#R##Ra#Rb#Rc#Rd#Re#Rf#Rg#Rh#Ri#Rj#Rk#Rl#Rm#Rn#Ro#Rp#Rq#Rr#Rs#Rt#Ru#Rv#Rw#Rx#Ry#Rz#RA#RB#RC#RD", +"#RE#RF#RG#RH#RI#RJ#RK#RL#RM#RN#RO#RP#RQ#RR#RS#RT#RU#RV#RW#RX#RY#RZ#R0#R1#R2#R3#R4#R5#R6#R7#R8#R9#S.#S##Sa#Sb#Sc#Sd#Se#Sf#Sg#Sh#Si#Sj#Sk#Sl#Sm#Sn#So#Sp#Sq#Sr#Ss#St#Su#Sv#Sw#Sx#Sy#Sz#SA#SB#SC#SD#SE#SF#SG#SH#SI#SJ#SK#SL#SM#SN#SO#SP#SQ#SR#SS#ST", +"#SU#SV#SW#SX#SY#SZ#S0#S1#S2#S3#S4#S5#RQ#S6#S7#S8#S9#T.#T##Ta#Tb#Tc#Td#Te#Tf#Tg#Th#Ti#Tj#Tk#Tl#QB#Tm#Tn#To#Tp#Tq#Tr#Ts#Tt#Tu#Tv#Tw#Tx#Ty#Tz#TA#TB#TC#TD#TE#TF#TG#TH#TI#TJ#TK#TL#TM#TN#TO#TP#TQ#TR#TS#TT#TU#TV#TW#TX#TY#TZ#T0#T1#T2#T3#T4#T5#T6#T7", +"#T8#T9#U.#U##Ua#Ub#Uc#Ud#Ue#Uf#Ug#Uh#Ui#Uj#Uk#Ul#Um#Un#Uo#Up#Uq#Ur#Us#Ut#Uu#Uv#Uw#Ux#Uy#Uz#UA#UB#UC#UD#UE#UF#UG#UH#UI#UJ#UK#UL#UM#UN#UO#UP#UQ#UR#US#UT#UU#UV#UW#UX#UY#UZ#U0#U1#U2#U3#U4#U5#U6#U7#U8#U9#V.#V##Va#Vb#Vc#Vd#Ve#Vf#Vg#Vh#Vi#Vj#Vk#Vl", +"#Vm#Vn#Vo#Vp#Vq#Vr#Vs#Vt#Vu#Tl#Vv#Vw#Vx#Vy#Vz#VA#VB#VC#VD#VE#VF#VG#VH#VI#VJ#VK#VL#VM#VN#VO#VP#VQ#VR#VS#VT#VU#VV#VW#VX#VY#VZ#V0#V1#V2#V3#V4#V5#V6#V7#V8#V9#W.#W##Wa#Wb#Wc#Wd#We#Wf#Wg#Wh#Wi#Wj#Wk#Wl#Wm#Wn#Wo#Wp#Wq#Wr#Ws#Wt#Wu#Wv#Ww#Wx#Wy#Wz#WA", +"#WB#WC#WD#WE#WF#WG#WH#WI#WJ#WK#WL#Vx#WM#WN#WO#WP#WQ#WR#WS#WT#WU#WV#WW#WX#WY#WZ#W0#W1#W2#W3#W4#W5#W6#W7#W8#W9#X.#X##Xa#Xb#Xc#Xd#Xe#Xf#Xg#Xh#Xi#Xj#Xk#Xl#Xm#Xn#Xo#Xp#Xq#Xr#Xs#Xt#Xu#Xv#Xw#DP#Xx#Xy#Xz#XA#XB#XC#XD#XE#XF#XG#XH#XI#XJ#XK#XL#XM#XN#XO", +"#XP#XQ#XR#Vp#XS#XT#XU#XV#XW#XX#XY#XZ#X0#X1#X2#X3#X4#X5#X6#X7#X8#X9#Y.#Y##Ya#Yb#Yc#Yd#Ye#Yf#Yg#Yh#Yi#Yj#Yk#Yl#Ym#Yn#Yo#Yp#Yq#Yr#Ys#Yt#Yu#Yv#Yw#Yx#Yy#Yz#YA#YB#YC#YD#YE#YF#YG#YH#YI#YJ#YK#YL#YM#YN#YO#YP#YQ#YR#YS#YT#YU#YV#YW#YX#YY#YZ#Y0#Y1#Y2#Y3", +"#Y4#Y5#Y6#Y7#Y8#Y9#Z.#Z##Za#Zb#WI#Zc#Zd#Ze#Zf#Zg#Zh#Zi#Zj#Zk#Zl#Zm#Zn#Zo#Zp#Zq#Zr#Zs#Zt#Zu#Zv#Zw#Zx#Zy#Zz#ZA#ZB#ZC#ZD#ZE#ZF#ZG#ZH#ZI#ZJ#ZK#ZL#ZM#ZN#ZO#ZP#ZQ#ZR#ZS#ZT#ZU#ZV#ZW#ZX#ZY#ZZ#Z0#Z1#Z2#Z3#Z4#Z5#Z6#Z7#Z8#Z9#0.#0##0a#0b#0c#0d#0e#0f#0g", +"#0h#0i#0j#0k#0l#0m#0n#0o#0p#0q#0r#0s#0t#0u#0v#0w#0x#0y#0z#0A#0B#0C#0D#0E#0F#0G#0H#0I#0J#0K#0L#0M#0N#0O#0P#0Q#0R#0S#0T#0U#0V#0W#0X#0Y#0Z#00#01#02#03#04#05#06#07#08#09#1.#1##1a#1b#1c#1d#1e#1f#1g#1h#1i#1j#1k#1l#1m#1n#1o#1p#1q#1r#1s#1t#1u#1v#1w", +"#1x#1y#1z#1A#1B#1C#1D#1E#1F#1G#1H#1I#1J#1K#1L#1M#1N#1O#1P#1Q#1R#1S#1T#1U#1V#1W#1X#1Y#1Z#10#11#12#13#14#15#16#17#18#19#2.#2##2a#2b#2c#2d#2e#2f#2g#2h#2i#2j#2k#2l#2m#2n#2o#2p#2q#2r#2s#2t#2u#2v#2w#2x#2y#2z#2A#2B#2C#2D#2E#2F#2G#2H#2I#2J#2K#2L#2M"}; + +static const char* const image_read_data[] = { +"16 16 241 2", +"#O c #001026", +"bK c #040e2b", +"#0 c #0c6bcb", +"ac c #0c6bce", +"#L c #0f6bca", +"bM c #10233d", +"#A c #122341", +"bN c #182359", +"#j c #1870c5", +"bJ c #19213b", +"#l c #212b4a", +"bL c #252a40", +"bA c #253551", +".R c #2779b6", +"#Z c #287fcd", +"bB c #293b4b", +".S c #29406a", +".B c #2a436a", +".8 c #2b313e", +".6 c #2b78d1", +"bC c #2f3a66", +"#K c #3284d6", +"bI c #333a50", +"bz c #343c53", +"#i c #348bdb", +".5 c #368bd9", +"bH c #393f5d", +"ab c #3987cd", +"ar c #3a6bbf", +"#k c #3c527b", +"#N c #3f5476", +"#y c #3f65b0", +"#4 c #40636c", +"#z c #424767", +"#3 c #425666", +"bn c #434e5e", +"ad c #448dd9", +"#m c #464e69", +"#x c #467ed1", +"#1 c #468ddc", +"as c #4892db", +"by c #4b576b", +"bP c #4e709d", +".7 c #505b80", +"aK c #515f6c", +".k c #524f45", +"aX c #525f6d", +"aw c #52606d", +".A c #555a62", +"ag c #556270", +"b. c #556372", +"bs c #58637f", +".Q c #59778b", +"bx c #5d6d7f", +".T c #5e627f", +"bO c #605a64", +"#M c #628dd2", +".C c #696974", +"aF c #6c9cdd", +"#w c #7295d6", +"#P c #747e8d", +"bw c #758797", +"bQ c #79928c", +"aS c #7ba6cd", +"b# c #7d828c", +"ah c #7d8891", +"ax c #7e828b", +"aY c #7e838d", +"aL c #7e848c", +"bo c #848990", +"aE c #8888cd", +"at c #89bde5", +"ae c #8cbde3", +"#2 c #90c0e9", +".c c #918967", +"bv c #92a8b2", +".e c #938869", +"aG c #93c4ee", +"bD c #9495ad", +"bd c #949bc1", +".r c #9692a8", +".q c #9699c9", +"#B c #979da4", +"am c #999ec4", +"#T c #999ec5", +"aO c #999fc3", +"#D c #9a9ec3", +".V c #9a9ec4", +"## c #9a9ec5", +"#8 c #9b9ec4", +"#o c #9b9ec5", +".l c #9c9db0", +".g c #9d9377", +"bu c #9fbfc4", +".v c #a199ac", +".G c #a1a5cc", +"aT c #a1d6dd", +".j c #a4936b", +".i c #a49687", +"br c #a6a6ac", +".t c #aba6b5", +"bm c #abb5bd", +".d c #aea176", +"#v c #afcdd7", +".f c #b0a06d", +"bG c #b0b0ba", +".D c #b0b2bf", +"#h c #b1d0d8", +"aR c #b2ceda", +".h c #b6a876", +"bt c #b8d8da", +".a c #bab2b4", +".b c #bba971", +"bR c #bbb7ca", +"a3 c #bde9d8", +"a4 c #bdead9", +".s c #beb39e", +".x c #bfb4b1", +"a1 c #bfebe0", +".4 c #c1dbde", +"#Y c #c1e2e0", +"bc c #c2c4c5", +"aq c #c2d0db", +"aP c #c2ebde", +"be c #c2f2e3", +".F c #c3c3c4", +"aj c #c3c3c5", +"#J c #c3dee1", +"#. c #c4c3c4", +"#S c #c4c3c5", +"al c #c4c4c4", +"bp c #c4c4c5", +"az c #c4c4c6", +"aZ c #c4c5c7", +"bl c #c4d3d2", +".u c #c5bdad", +"aN c #c5c3c6", +"a0 c #c5c4c4", +"#n c #c5c4c5", +"bb c #c5c4c6", +"aD c #c5d2e1", +"an c #c5eade", +"a2 c #c5f1de", +"Qt c #c6c6c5", +".o c #c6c6c9", +"bU c #c6c7c8", +"#6 c #c6c7c9", +"#R c #c6c9ca", +"aB c #c6ece3", +".p c #c7c6c5", +"bT c #c7c6c8", +".9 c #c7c7c9", +"ak c #c7c8c9", +"aA c #c8c6c8", +"#7 c #c8c7c9", +".E c #c8c7cb", +".# c #c8c8cd", +"aa c #c8e7dd", +"#9 c #c8ece1", +".U c #c9c8c9", +"bS c #c9c8ca", +"#5 c #c9c9c6", +".n c #c9c9c8", +"aH c #c9eae0", +"a5 c #c9f0da", +"#C c #cac7c9", +"#U c #caece0", +"au c #cbe5e3", +"ap c #cbeeda", +"ao c #cbf2e0", +"bf c #cbfee7", +".z c #ccc1b6", +"aQ c #ccf5df", +"bE c #cdccca", +"a. c #cdf2df", +"aC c #cdf6e1", +"#E c #ceede2", +"a6 c #cef0db", +".w c #cfc9c1", +"bF c #cfcfcc", +"ba c #cfcfcf", +"#p c #cfebe0", +"ay c #d0cece", +"aM c #d0cfcf", +"ai c #d1d1d1", +".H c #d1d6df", +"bk c #d1e8e1", +"#a c #d1ebe1", +"aU c #d1f1e1", +"#W c #d2efdf", +"#V c #d2f4e2", +"a7 c #d3f3de", +"bg c #d3ffed", +"#Q c #d4d0d0", +"aW c #d4eedc", +"#q c #d4f2dd", +"a# c #d4f2e2", +"bq c #d5d3d5", +".W c #d5f0e3", +"#r c #d5f1df", +"bj c #d5f1e9", +"#F c #d5f4e2", +"#H c #d6f1e2", +".y c #d7d2d9", +".m c #d7d7d7", +"aV c #d7f1de", +".X c #d7f3df", +"af c #d8ece2", +"#G c #d8f3e3", +"a8 c #d8f7e2", +"bh c #d8ffed", +".2 c #d9efdc", +"#b c #d9f4e2", +"#c c #daf1e1", +"#t c #dbefe0", +"bi c #dbfff0", +"#f c #dcefe1", +"aJ c #dcf1de", +".Z c #dcf1df", +"#s c #dcf2e1", +".Y c #dcf3df", +"#d c #ddf2e0", +".1 c #def0df", +"#X c #def4df", +"#e c #e0f1e0", +"aI c #e0f5df", +".0 c #e1f4e2", +"#I c #e4f6e0", +".L c #e5ece2", +".3 c #e5f5e0", +".J c #e6eae9", +"a9 c #e7ffeb", +"av c #e8f7e3", +".O c #e8f7ea", +"#u c #eafae1", +".N c #ebf4ea", +"#g c #ebf7e5", +".P c #ecf7e5", +".M c #eef7ee", +".I c #f0f4ed", +".K c #f0f6ed", +"Qt.#.a.b.c.d.e.f.g.h.i.j.k.l.m.n", +".o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D", +".E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T", +".U.F.V.W.X.Y.Z.0.1.2.3.4.5.6.7.8", +".9#.###a#b#c#d#e#f#g#h#i#j#k#l#m", +".9#n#o#p#q#r#s#t#u#v#w#x#y#z#A#B", +"#C.F#D#E#F#G#H#I#J#K#L#M#N#O#P#Q", +"#R#S#T#U#V#W#X#Y#Z#0#1#2#3#4#5#6", +"#7#.#8#9a.a#aaabacadaeafagahaiaj", +"akalamanaoapaqarasatauavawaxayaz", +"aAaz.VaBaCaDaEaFaGaHaIaJaKaLaMaz", +".EaNaOaPaQaRaSaTaUaVaW#taXaYayaZ", +".9a0##a1a2a3a4a5a6a7a8a9b.b#babb", +".9bcbdbebfbgbhbibjbkblbmbnbobabp", +"bqbrbsbtbubvbwbxbybzbAbBbCbDbEaZ", +"bFbGbHbIbJbKbLbMbNbObPbQbRbSbTbU"}; + +static const char* const image_cpu_data[] = { +"16 16 138 2", +"#C c #424244", +"#P c #454547", +"#Z c #48484a", +"#r c #4a4a43", +"#s c #4b4b4c", +"#B c #4c4c45", +"#7 c #4c4c4d", +"#D c #4d4d4e", +"#O c #54544c", +"#Y c #565650", +"#6 c #585852", +"#R c #5a5a59", +"#Q c #5d5d5e", +"#2 c #5e5e5e", +"#q c #61615e", +"#f c #636362", +"#1 c #636363", +"a# c #636365", +"#A c #646461", +"ab c #646463", +"#0 c #656567", +"#9 c #666667", +"#N c #6a6a68", +"ac c #6a6a69", +"#X c #6b6b69", +"af c #6d6d6d", +"#8 c #6d6d70", +"#t c #6e6e6e", +"#e c #6f6f64", +"#p c #717167", +".5 c #727268", +"aa c #737374", +".R c #747475", +".G c #757576", +"#z c #77776d", +"#5 c #777773", +".x c #787879", +"ae c #797979", +"#S c #7a7a7a", +"#M c #7c7c72", +"#W c #7d7d74", +".m c #808082", +".J c #81817d", +".k c #82827e", +".U c #82827f", +"a. c #828282", +"#g c #828284", +".s c #83837e", +"#T c #848487", +"#d c #8b8b84", +"#3 c #8c8c8c", +"#E c #8d8d8d", +".6 c #909091", +"#o c #94948c", +".l c #98989a", +"#H c #9a9a9b", +".u c #9b9b9b", +".4 c #9d9d9a", +"#G c #9d9d9d", +".Q c #9d9d9f", +".2 c #9d9da2", +"#4 c #9e9ea0", +".t c #9f9f9e", +".F c #9f9fa2", +".w c #9f9fa3", +"#y c #a0a096", +".P c #a2a2a4", +".3 c #a2a2a7", +".A c #a3a3a3", +".1 c #a3a3a6", +".v c #a4a4a7", +".B c #a5a5a3", +".E c #a5a5a8", +"#L c #a7a79d", +"#c c #a7a7a8", +".K c #a8a8a8", +"#w c #a9a9a9", +".0 c #ababac", +".D c #ababad", +".n c #acacad", +"#b c #acacae", +".O c #adadad", +".y c #aeaead", +".S c #afafb0", +".Z c #b0b0b0", +".N c #b1b1b0", +".C c #b1b1b1", +".Y c #b2b2b2", +".L c #b3b3b0", +"ah c #b3b3b3", +"#V c #b4b49f", +"#n c #b6b6b3", +"#a c #b8b8b8", +"#F c #b9b9b9", +"#m c #b9b9ba", +".M c #bababb", +".X c #bbbbbb", +".7 c #bdbdb5", +"## c #bebebe", +".V c #bfbfbd", +"#l c #c0c0c0", +".T c #c1c1c0", +".g c #c1c1c1", +".I c #c2c2c2", +".z c #c3c3c3", +"#x c #c3c3c5", +"#v c #c4c4c2", +".r c #c4c4c4", +".f c #c5c5c4", +".j c #c5c5c5", +".p c #c6c6c6", +".d c #c7c7c7", +".# c #c8c8c7", +".c c #c8c8c8", +"Qt c #c9c9c9", +"#I c #cacabf", +".a c #cacaca", +".W c #cacacb", +".b c #cbcbcb", +"ad c #cccccc", +"#k c #cdcdcd", +".h c #cecece", +"#. c #cfcfcf", +".e c #cfcfd0", +".q c #d0d0d0", +".i c #d0d0d1", +"#K c #d2d2d0", +".H c #d2d2d1", +".o c #d2d2d2", +"#j c #d5d5d4", +"ag c #d7d7d7", +"#U c #d9d9d0", +"#i c #dcdcd2", +".9 c #dcdcdd", +"#J c #dcdcde", +".8 c #dddddd", +"#u c #e7e7e9", +"#h c #ebebe4", +"QtQtQtQtQtQtQtQtQt.#.a.b.cQtQtQt", +"QtQtQtQtQtQtQt.d.a.e.f.g.h.dQtQt", +"QtQtQtQtQt.d.a.i.j.k.l.m.n.o.pQt", +"QtQtQt.d.a.q.r.s.t.u.v.w.x.y.o.p", +".c.d.b.i.z.s.A.B.C.D.E.w.F.G.y.H", +".b.q.I.J.K.L.g.M.N.O.E.P.w.Q.R.S", +".T.U.O.V.h.W.g.X.Y.Z.0.1.2.3.4.5", +".6.7.8.9#.Qt.j###a.C.n#b#c#d#e#f", +"#g#h#i.e#j#k.d#l#m#m#n#o#p#q#r#s", +"#t#u#v#w#x.o.c.W#v#y#z#A#B#C#D#E", +"#F#G#H.A#I#J#K#L#M#N#O#P#Q#f#R.j", +".q.I#S#T#U#V#W#X#Y#Z#0#1#2.d.zQt", +".d.b.o#3#4#5#6#7#8#1#9.p.IQt.a.c", +"Qt.c.a.ja.a#aaabac.p.IQt.b.cQtQt", +"QtQt.cad.daeaf.p.gQt.b.cQtQtQtQt", +"QtQtQt.d#kagah.b#k.c.cQtQtQtQtQt"}; + +static const char* const image_port_data[] = { +"16 16 158 2", +" c None", +"! c black", +"# c #9BE3A4", +"$ c #84DBAF", +"% c #50C1B7", +"& c #5AC27E", +"' c #3AA8BD", +"( c #92DFA7", +") c #91E278", +"* c #A6EC93", +"+ c #9FE888", +", c #7ED856", +"- c #51C229", +". c #199D84", +"0 c #0D8BEA", +"1 c #73D086", +"2 c #6BCF3F", +"3 c #97E57D", +"4 c #BDF7B8", +"5 c #B2F2AE", +"6 c #90E183", +"7 c #58C52D", +"8 c #18A288", +"9 c #0081E7", +": c #018256", +"; c #30AD34", +"< c #5FC933", +"= c #85DC61", +"> c #9EE89A", +"? c #99E581", +"@ c #A4EAC6", +"A c #59C5D7", +"B c #129FC1", +"C c #018C75", +"D c #008200", +"E c #007459", +"F c #429DE1", +"G c #0C8AB0", +"H c #42BA21", +"I c #60C933", +"J c #6CCF40", +"K c #70D158", +"L c #75D4E6", +"M c #3CB7FF", +"N c #0497CC", +"O c #008E00", +"P c #007D00", +"Q c #016D10", +"R c #003262", +"S c #2987D8", +"T c #0279CF", +"U c #20A71E", +"V c #34B31A", +"W c #3EB81F", +"X c #3DB8C8", +"Y c #2DB0FF", +"Z c #269CF1", +"[ c #4AA5CE", +"] c #72B4B0", +"^ c #70A9AA", +"_ c #166D29", +"` c #073D5B", +"a c #247ACE", +"b c #0069CF", +"c c #027EB4", +"d c #09955C", +"e c #10A017", +"f c #0A9E35", +"g c #1D90EB", +"h c #AFCEE9", +"i c #A9CDED", +"j c #B0DDFC", +"k c #A5D0F3", +"l c #9BC3E1", +"m c #4C6F92", +"n c #2777C9", +"o c #0057BD", +"p c #0067CD", +"q c #0072D8", +"r c #00826E", +"s c #008B00", +"t c #3A9068", +"u c #80A6D8", +"v c #A8CCEC", +"w c #B8DAF2", +"x c #CDF0FF", +"y c #C5EBFF", +"z c #B9E3FD", +"{ c #4F6888", +"| c #3083C9", +"} c #0045AB", +"~ c #0051B7", +" ! c #005BC1", +"!! c #0063AD", +"#! c #007800", +"$! c #418874", +"%! c #91BAE5", +"&! c #A8D1F3", +"'! c #B3D8F3", +"(! c #91B7E4", +")! c #82ACE2", +"*! c #33435B", +"+! c #1157B5", +",! c #013CA2", +"-! c #0044AA", +".! c #0048AE", +"0! c #096811", +"1! c #03565C", +"2! c #355CA1", +"3! c #8EB6E2", +"4! c #A2CDF2", +"5! c #81A9DD", +"6! c #ABCCEB", +"7! c #C8E5F6", +"8! c #4F5F70", +"9! c #185BBE", +":! c #1743A9", +";! c #154699", +"! c #0E3B9E", +"?! c #355BB5", +"@! c #8EB5E7", +"A! c #81ABE1", +"B! c #5C7699", +"C! c #9BB7CE", +"D! c #C7E8FC", +"E! c #5E748E", +"F! c #1F53A1", +"G! c #3066C8", +"H! c #4466BB", +"I! c #4E67CD", +"J! c #3B60C6", +"K! c #2E51AD", +"L! c #102652", +"M! c #0B0E13", +"N! c #A5C4E0", +"O! c #9AC2E9", +"P! c #00244A", +"Q! c #001D41", +"R! c #000E21", +"S! c #29364A", +"T! c #2C3A4F", +"U! c #5C7797", +"V! c #6F8FB6", +"W! c #9BBAD7", +"X! c #B2DAFC", +"Y! c #83AAD5", +"Z! c #B5DEFF", +"[! c #A9CFF3", +"]! c #A7CEF3", +"^! c #A2C8EC", +"_! c #7EA7D5", +"`! c #546F90", +"a! c #0C1016", +"b! c #99BEE6", +"c! c #94C2F3", +"d! c #577294", +" # $ % & ' ", +" ( ) * + , - . 0 ", +" 1 2 3 4 5 6 7 8 9 : ", +" ; < = > ? @ A B C D E ", +"F G H I J K L M N O P Q R ", +"S T U V W X Y Z [ ] ^ _ ` ", +"a b c d e f g h i j k l m ", +"n o p q r s t u v w x y z { ", +"| } ~ !!!#!$!u %!&!'!(!)!*! ", +" +!,!-!.!0!1!2!3!4!5!6!7!8! ", +" 9!:!;!!?!@!A!B!C!D!E! ", +" F!G!H!I!J!K!L!M!! N!O! ", +" P!Q!R!S!T!U!V!W!X!Y! ", +" i Z![!]!^!_!`!a! ", +" b!c!d! ", +" "}; + +// 32*32*24b +static const char* const image_ai32_data[] = { +"32 32 178 2", +" c None", +"! c white", +"# c #FCFCFC", +"$ c #E8E8E8", +"% c #DCDCDC", +"& c #F0F0F0", +"' c #B0ACAC", +"( c #B8B4B4", +") c #D0D0D0", +"* c #C8C4C0", +"+ c #B8B8B8", +", c #F4F0F0", +"- c #B0A8A8", +". c #DCE0DC", +"0 c #F8F8F8", +"1 c #BCBCBC", +"2 c #F4F4F4", +"3 c #F0F4DC", +"4 c #F8F8F4", +"5 c #C4BCC4", +"6 c #E4E0E8", +"7 c #F8F8F0", +"8 c #A4E030", +"9 c #B0D480", +": c #B8B4A0", +"; c #D4E8B0", +"< c #F4F8F4", +"= c #E4ECC4", +"> c #80D418", +"? c #6CA438", +"@ c #7CC818", +"A c #84D044", +"B c #DCDCE0", +"C c #FCFCF8", +"D c #E8ECE0", +"E c #ACB8A4", +"F c #8C8488", +"G c #88B85C", +"H c #90AC88", +"I c #F8F0F0", +"J c #F4E0E0", +"K c #F0D8D8", +"L c #F8F4F4", +"M c #C0B8B8", +"N c #D4D0D8", +"O c #E8BCB8", +"P c #CC5C54", +"Q c #C02428", +"R c #B41014", +"S c #B40C10", +"T c #CC5858", +"U c #E4ACA8", +"V c #E4DCDC", +"W c #C4BCBC", +"X c #F8ECE8", +"Y c #C8605C", +"Z c #B00000", +"[ c #B40000", +"] c #B80000", +"^ c #C00008", +"_ c #C00000", +"` c #C44444", +"a c #F0D4D4", +"b c #D0D4CC", +"c c #CCD4D0", +"d c #C03834", +"e c #A80000", +"f c #B80008", +"g c #BC0004", +"h c #C00004", +"i c #C4000C", +"j c #CC0008", +"k c #C80000", +"l c #C41418", +"m c #BC6C6C", +"n c #C87070", +"o c #D44C50", +"p c #D43C44", +"q c #D83C40", +"r c #D85860", +"s c #C86860", +"t c #B80004", +"u c #C80008", +"v c #900008", +"w c #C00010", +"x c #D00008", +"y c #D00000", +"z c #D80008", +"{ c #D80010", +"| c #D84048", +"} c #F0D0D0", +"~ c #B00808", +" ! c #B40004", +"!! c #B00810", +"#! c #780010", +"$! c #B80010", +"%! c #880810", +"&! c #B80018", +"'! c #E00020", +"(! c #E00010", +")! c #D83840", +"*! c #E8E4E8", +"+! c #C87878", +",! c #E00018", +"-! c #D80020", +".! c #E80018", +"0! c #D07080", +"1! c #C05050", +"2! c #980010", +"3! c #800008", +"4! c #D00010", +"5! c #E00008", +"6! c #D01030", +"7! c #D8D0D0", +"8! c #C04848", +"9! c #D86880", +":! c #A89898", +";! c #902020", +"! c #A03040", +"?! c #981018", +"@! c #D80018", +"A! c #C89098", +"B! c #E8A098", +"C! c #F8F8E8", +"D! c #C85850", +"E! c #C08080", +"F! c #D0B8A8", +"G! c #B02830", +"H! c #F0F0E0", +"I! c #E07068", +"J! c #C06878", +"K! c #F0F8F8", +"L! c #C01010", +"M! c #D04038", +"N! c #E04040", +"O! c #E05850", +"P! c #D83838", +"Q! c #B85870", +"R! c #E8F0F0", +"S! c #D0A8A0", +"T! c #B06078", +"U! c #B03030", +"V! c #A88090", +"W! c #F0F8F0", +"X! c #C8A8A8", +"Y! c #B81840", +"Z! c #B0B0B8", +"[! c #B87880", +"]! c #986878", +"^! c #E0E8E8", +"_! c #B06870", +"`! c #B00008", +"a! c #A03850", +"b! c #FCF8F8", +"c! c #A88080", +"d! c #A02848", +"e! c #98A0A0", +"f! c #B8B0B0", +"g! c #A04848", +"h! c #D00018", +"i! c #C80020", +"j! c #983050", +"k! c #D0D8D8", +"l! c #A89090", +"m! c #A04048", +"n! c #A82038", +"o! c #886070", +"p! c #A8B0B0", +"q! c #A07880", +"r! c #985058", +"s! c #A02038", +"t! c #905058", +"u! c #907880", +"v! c #A0A8A8", +"w! c #C0C8C8", +"x! c #B8C0C0", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! $ % ! # ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! & ' % # ! # ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # # # ( ) & ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! * + & # ! # ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! , - . 0 ! # ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! ! ) 1 2 # # ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 3 4 5 6 # ! # ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ! # ! 7 8 9 : ; < ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! # # ! # # ! = > ? @ A B ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! # # ! ! ! ! # C ! D E F G H 6 ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! # # ! ! I J K L ! ! ! # $ M N B # ! # ! ! ! ! ! ! ! ! ", +"! ! ! ! # ! ! O P Q R S Q T U 0 ! V W 0 ! # # # # ! ! ! ! ! ! ! ", +"! ! ! # ! X Y Z [ ] ] ^ _ _ ] ` a b c ! ! ! ! ! ! ! # ! ! ! ! ! ", +"! ! # # X d e f g g h ^ ^ i j k l m n o p q p r U # ! # ! ! ! ! ", +"! ! # ! s e f t t h h u u i v w x u y y z { { { { | K ! # ! ! ! ", +"! # ! } ~ t !t g ^ ^ u ^ u !!#!$!{ !!%!&!'!'!'!'!(!)!*!! # ! ! ", +"# # ! +!e f !t h ^ h u %!f { w i $!%!&!{ ,!-!,!,!'!.!0!0 ! # ! ", +"# # ! 1!Z f ^ ^ ^ ^ ^ x 2!3!x z z 4!5!{ $!w ,!,!'!'!.!6!7!! # ! ", +"# ! # 8!Z f ^ ^ ^ u u h 9!:!;!2!!?!$!@!'!'!'!'!.!,!A!# # ! ", +"# # # 1![ f ^ ^ ^ i h ^ B!C!D!E!F!G!H!I!(!'!,!,!'!'!'!,!J!K!! # ", +"! # ! n Z ^ ^ ^ ^ ^ ^ h L!M!h N!O!x P!N!@!'!@!,!'!'!'!.!Q!R!! # ", +"# # ! S!e t g h g ^ ^ ^ h _ u k k 4!{ { ,!@!@!-!,!'!'!.!T!R!! # ", +"# # ! $ U!_ ^ ^ g g g h ^ u u 4!4!{ -!@!,!@!@!'!,!'!.!'!V!W!! # ", +"! # # # X!!!^ ^ g g h h ^ u j j 4!4!@!@!{ @!@!@!,!'!.!Y!Z!# ! ! ", +"! ! ! ! K![!Z h g ^ g h u u u 4!4!@!{ @!@!@!,!,!'!.!'!]!. ! # # ", +"! ! # # ! ^!_!`!_ ^ g h h u u 4!4!@!@!@!-!,!,!'!'!,!a!+ b!! # ! ", +"! ! ! # ! # ^!c!=!] h ^ u u u u 4!4!{ @!@!'!'!,!,!d!e!& ! # ! ! ", +"! ! ! ! # ! ! R!f!g!!!h j j 4!4!4!h!@!,!,!,!,!i!j!e!$ ! # ! ! ! ", +"! ! ! ! ! ! ! ! 0 k!l!m!=!$!u x x { ,!@!@!i!n!o!p!$ ! ! ! ! ! ! ", +"! ! ! ! ! ! ! # ! ! & k!' q!r!>!s!n!n!a!t!u!v!k!0 ! # ! ! ! ! ! ", +"! ! ! ! ! ! ! ! # # ! ! 0 R!% w!+ ' Z!x!c $ 0 ! ! # ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! # # # ! ! ! ! # # ! ! ! ! # ! ! ! ! ! ! ! ! "}; + +static const char* const image_di32_data[] = { +"32 32 192 2", +" c None", +"! c white", +"# c #FCFCFC", +"$ c #F4F4B8", +"% c #F0F0BC", +"& c #F8F8FC", +"' c #FCFCF8", +"( c #F0F07C", +") c #F4F030", +"* c #F0F038", +"+ c #ECEC74", +", c #F0F0E8", +"- c #ECEC9C", +". c #F0F010", +"0 c #F8F818", +"1 c #F8F810", +"2 c #E8E870", +"3 c #F0F0F4", +"4 c #F0F0D4", +"5 c #E8E028", +"6 c #F8F820", +"7 c #D8D8A8", +"8 c #E0E050", +"9 c #E8E8E8", +": c #F0E8C0", +"; c #F0F068", +"< c #F0F0D8", +"= c #E8E858", +"> c #F0F058", +"? c #D0D078", +"@ c #F0F0F8", +"A c #F8F8F0", +"B c #E8E068", +"C c #F0F018", +"D c #F0F020", +"E c #E0E030", +"F c #C8C840", +"G c #B0B058", +"H c #A8A070", +"I c #B8B8A0", +"J c #F8F8F8", +"K c #F0F0D0", +"L c #E0E070", +"M c #E0D858", +"N c #E0E038", +"O c #F0E818", +"P c #D0C020", +"Q c #C0A828", +"R c #A08030", +"S c #805838", +"T c #703850", +"U c #704878", +"V c #B0A8B8", +"W c #D8D8E0", +"X c #E0E0E8", +"Y c #D8D028", +"Z c #E8E008", +"[ c #E8E018", +"] c #A08830", +"^ c #785830", +"_ c #887068", +"` c #887080", +"a c #785080", +"b c #683078", +"c c #601870", +"d c #501860", +"e c #581868", +"f c #784880", +"g c #B8B828", +"h c #B0B048", +"i c #A0A060", +"j c #989870", +"k c #603848", +"l c #502058", +"m c #481058", +"n c #602078", +"o c #D0D0E0", +"p c #706068", +"q c #707070", +"r c #E0D8E0", +"s c #702070", +"t c #582060", +"u c #681870", +"v c #C0C0B0", +"w c #B0B0B0", +"x c #C0C0C8", +"y c #907890", +"z c #501858", +"{ c #602870", +"| c #381840", +"} c #804890", +"~ c #887888", +" ! c #200030", +"!! c #603860", +"#! c #A078A0", +"$! c #702078", +"%! c #704870", +"&! c #702080", +"'! c #703880", +"(! c #E8E0E8", +")! c #502850", +"*! c #481050", +"+! c #783088", +",! c #782880", +"-! c #601070", +".! c #582860", +"0! c #908090", +"1! c #905090", +"2! c #783090", +"3! c #681880", +"4! c #9870A8", +"5! c #887088", +"6! c #481850", +"7! c #584860", +"8! c #502858", +"9! c #582068", +":! c #602868", +";! c #684868", +"! c #682078", +"?! c #802890", +"@! c #782890", +"A! c #702880", +"B! c #D0C8D8", +"C! c #482848", +"D! c #D0B8D0", +"E! c #988098", +"F! c #A898A8", +"G! c #805878", +"H! c #803880", +"I! c #782088", +"J! c #B0A0B0", +"K! c #381040", +"L! c #602070", +"M! c #702870", +"N! c #701878", +"O! c #782888", +"P! c #802898", +"Q! c #803890", +"R! c #E0E0E0", +"S! c #401048", +"T! c #602068", +"U! c #B8B0C0", +"V! c #685068", +"W! c #682070", +"X! c #782080", +"Y! c #802888", +"Z! c #882898", +"[! c #802090", +"]! c #A888B0", +"^! c #882890", +"_! c #883098", +"`! c #F0F8F0", +"a! c #F0E0E8", +"b! c #802088", +"c! c #9030A0", +"d! c #9868B0", +"e! c #E8F0E8", +"f! c #502060", +"g! c #9038A0", +"h! c #A038B0", +"i! c #A060B8", +"j! c #E0E8E0", +"k! c #603068", +"l! c #9038A8", +"m! c #A038B8", +"n! c #681878", +"o! c #702088", +"p! c #902898", +"q! c #9838A8", +"r! c #A088A8", +"s! c #C8C0C8", +"t! c #9840B0", +"u! c #501058", +"v! c #9058A0", +"w! c #D0D0D0", +"x! c #601868", +"y! c #781878", +"z! c #803090", +"{! c #A098A8", +"|! c #F0F0F0", +"}! c #9890A0", +"~! c #601060", +" # c #882090", +"!# c #D0D8D0", +"## c #C0B8C0", +"$# c #807080", +"%# c #B8B8B8", +"&# c #A098A0", +"'# c #A0A0A8", +"(# c #D8E0D8", +"! ! ! ! ! ! ! ! ! ! ! # ! # $ % & ! # ! ! ! ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! # ! ' ( ) * + , ! # ! ! ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! # ! - . 0 0 1 2 3 ! # # ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! # ! 4 5 0 6 6 0 6 7 # ! ! # # ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! # # # 2 . 6 6 6 0 0 8 9 # : ; ; < ! ! ! ! ! ! ! ", +"! ! ! ! ! ! # ! # ! 4 5 0 0 0 0 0 0 6 = > 6 0 0 ? @ ! # ! ! ! ! ", +"! ! ! ! ! # ! ! # A B C D C 0 6 6 6 6 D E F G H I J ! # ! ! ! ! ", +"! ! ! ! # ! K L M N C 0 6 6 O P Q R S T U V W X & ! ! ! ! ! ! ! ", +"! ! ! # ! < Y Z [ [ Y Q ] ^ _ ` a b c d e f X ! ! ! ! ! ! ! ! ! ", +"! ! # ! # ? g h i j k l m n o p q r s t l u b o ! # ! ! ! ! ! ! ", +"! ! ! ! J v w x 9 y z { | } ~ !!!#!$!%!#!&!&!'!(!! # ! ! ! ! ! ", +"! ! ! ! # # ! ! r )!t { | *!c +!,!-!.!0!1!&!2!3!4!J ! # ! ! ! ! ", +"! ! ! ! ! ! # ! 5!6!.!{ b 7!8!9!:!;!!+!?!@!A!B!! # # ! ! ! ", +"! ! ! ! ! # ! (!C!l :!{ n D!E!F!G!#!H!&!2!+!?!?!I!4!' ! ! ! ! ! ", +"! ! ! ! ! # ! J!K!.!9!{ L!{ M!H!+!N!A!2!@!O!@!P!?!Q!R!! # ! ! ! ", +"! ! ! ! # # ! ~ S!9!T!L!{ c c c A!$!,!A!+!@!@!?!?!O!U!! # # ! ! ", +"! ! ! ! ! ! ! V!S!l 9!W!>!c c c $!N!X!,!,!A!O!Y!Z![!]!# ! ! ! ! ", +"! ! ! ! ! ! J !!z .!L!>!>!c c u $!X!X!,!$!$!,!^!_!Z!4!`!! ! ! ! ", +"! ! ! ! # ! a!8!t L!>!>!$!>!&!&!&!X!b!?!Y!Y!_!_!_!c!d!e!! ! ! ! ", +"! ! ! ! # ! (!.!f!9!>!W!u u &!&!&!?!?!b!?!_!_!_!g!h!i!j!! ! # ! ", +"! ! ! ! ! ! , k!9!L!L!c c u &!N!&!?!X!X!O!P!Z!_!l!m!i!R!! # ! ! ", +"! ! ! ! ! ! J %!z n L!u $!N!n!n!>!&!I!I!I!Z!c!_!l!m!i!R!! # # ! ", +"! ! ! ! ! ! ! G!e $!W!>!$!$!$!u $!&!o!Y!?!^!p!_!g!h!4!9 ! ! ! ! ", +"! ! ! ! # # ! E!e $!$!X!,!$!s >!$!o!@!?!^!^!?!_!g!q!r!A ! # ! ! ", +"! ! ! ! ! # ! s!t W!>!O!Y!X!X!$!&!I!b!^!^!?!?!_!g!t!U!! ! ! ! ! ", +"! ! ! ! ! ! ! J %!u!u N!X!b!X!X!&!I!b!?!?!?!?!_!l!v!w!! # # ! ! ", +"! ! ! ! ! # # ! x 6!x!$!X!X!X!y!X!b![!@!^!Z!Z!^!z!{!A ! # ! ! ! ", +"! ! ! ! ! ! # ! # r!*!x!s X!N!N!X!X!I!P!^!^!^!X!5!R!! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! |!}!l u!~!N!N!X!X!b! #[!I!'!y !#! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! # ! J ##$#!!:!x!>!>!>!'!a y %#e!! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! # ! ! |!w!%#{!}!&#'#%#(#|!! ! # ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! # # ! ! ! ! ! ! ! ! ! ! # # ! ! ! ! ! ! ! ! "}; + +static const char* const image_pi32_data[] = { +"32 32 217 2", +" c None", +"! c white", +"# c #FFFFF8", +"$ c #F8F8E8", +"% c #D0D8D8", +"& c #E8F0E0", +"' c #F8F8F8", +"( c #C0D8B0", +") c #B8D0A0", +"* c #C8D0C0", +"+ c #70B850", +", c #C0D0B8", +"- c #F8F8F0", +". c #78B858", +"0 c #88B860", +"1 c #A0C888", +"2 c #A8B898", +"3 c #88C878", +"4 c #70A848", +"5 c #C0B8B8", +"6 c #80C868", +"7 c #78A860", +"8 c #98B868", +"9 c #A8C890", +": c #58B030", +"; c #A8C088", +"< c #A0C088", +"= c #88B060", +"> c #88A070", +"? c #90C870", +"@ c #60B840", +"A c #709850", +"B c #A0A0A0", +"C c #F0F8F8", +"D c #FFF8FF", +"E c #B8C8B0", +"F c #68A840", +"G c #60B830", +"H c #98C878", +"I c #B8C8A0", +"J c #68C048", +"K c #78B050", +"L c #98A080", +"M c #80C060", +"N c #789858", +"O c #989888", +"P c #A8D890", +"Q c #B8B8A8", +"R c #78A848", +"S c #60B838", +"T c #78B850", +"U c #68C050", +"V c #78B860", +"W c #78C060", +"X c #60C048", +"Y c #68B840", +"Z c #689840", +"[ c #68B040", +"] c #70B048", +"^ c #70A840", +"_ c #78B048", +"` c #80A068", +"a c #A8A8A8", +"b c #E0A0A0", +"c c #B03828", +"d c #983010", +"e c #A02810", +"f c #A02808", +"g c #983828", +"h c #A05848", +"i c #A04840", +"j c #A05048", +"k c #982008", +"l c #A82010", +"m c #B02818", +"n c #B84838", +"o c #E8C0C0", +"p c #A81000", +"q c #981008", +"r c #A00810", +"s c #B00810", +"t c #A80000", +"u c #B05058", +"v c #C04038", +"w c #B80000", +"x c #A81010", +"y c #A80800", +"z c #B80808", +"{ c #C04838", +"| c #FFF8F8", +"} c #C88070", +"~ c #982010", +" ! c #901808", +"!! c #981810", +"#! c #901810", +"$! c #A01808", +"%! c #A00808", +"&! c #400800", +"'! c #881010", +"(! c #C00810", +")! c #881800", +"*! c #882018", +"+! c #801810", +",! c #A01008", +"-! c #B02018", +".! c #781810", +"0! c #801008", +"1! c #C83020", +"2! c #A81008", +"3! c #981010", +"4! c #A80810", +"5! c #C80010", +"6! c #882810", +"7! c #803018", +"8! c #A02008", +"9! c #882010", +":! c #701810", +";! c #B01808", +"! c #C00800", +"?! c #C00008", +"@! c #B80810", +"A! c #C82038", +"B! c #E0E0E0", +"C! c #B86850", +"D! c #782010", +"E! c #783020", +"F! c #902810", +"G! c #881810", +"H! c #601818", +"I! c #782018", +"J! c #783028", +"K! c #682018", +"L! c #B81000", +"M! c #C80008", +"N! c #C00818", +"O! c #D80018", +"P! c #E080A0", +"Q! c #F8FFFF", +"R! c #882818", +"S! c #782818", +"T! c #903018", +"U! c #802810", +"V! c #A82008", +"W! c #700808", +"X! c #B88898", +"Y! c #E00018", +"Z! c #B84060", +"[! c #C09898", +"]! c #782008", +"^! c #983018", +"_! c #A03018", +"`! c #A82810", +"a! c #B02008", +"b! c #B01008", +"c! c #A81808", +"d! c #981808", +"e! c #C80000", +"f! c #D00018", +"g! c #C81830", +"h! c #E0C0C0", +"i! c #B08078", +"j! c #B02808", +"k! c #D80010", +"l! c #C81028", +"m! c #A06858", +"n! c #882008", +"o! c #B80820", +"p! c #C81020", +"q! c #E00818", +"r! c #986050", +"s! c #D01028", +"t! c #A87068", +"u! c #702818", +"v! c #B80800", +"w! c #C0C8C8", +"x! c #C80018", +"y! c #D80818", +"z! c #883828", +"{! c #982810", +"|! c #A88090", +"}! c #902008", +"~! c #B04058", +" # c #C8D0D0", +"!# c #A82808", +"## c #B82040", +"$# c #A898A0", +"%# c #902818", +"&# c #C81030", +"'# c #987888", +"(# c #B89090", +")# c #B81030", +"*# c #986078", +"+# c #B09098", +",# c #902828", +"-# c #B81800", +".# c #A82040", +"0# c #A01810", +"1# c #B01800", +"2# c #B01018", +"3# c #984058", +"4# c #984038", +"5# c #A81810", +"6# c #982038", +"7# c #906880", +"8# c #A07880", +"9# c #903838", +":# c #981820", +";# c #884858", +"<# c #A098A0", +"=# c #A88890", +"># c #905058", +"?# c #883850", +"@# c #988090", +"A# c #A89098", +"B# c #B8B8C0", +"! ! ! ! ! ! # ! ! ! ! ! ! $ # ! % & ! ' ! ! ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! # ' ( & ! ) % * + , ! ! - & - ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! # $ ! ! ' . 0 & 1 2 3 4 5 # ( 6 7 * ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! - 8 0 ( ' 9 : ; < = + > * ? @ A B C ! # ! ! ! ! ! ! ! ", +"! ! ! ! ! D E F G H I + + 0 J K L M @ N O ) P ? ; C ! ! ! ! ! ! ", +"! ! ! ! ! ! ' Q R S . T U + U . V U + 7 W X Y Z B C ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ' * 0 [ ] + ] ^ ] ] T _ _ R K ` a & ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! b c d e f g h i j k e l l m n o ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! o n p q r s t b $ u % v w x x r y z { o ! ! ! ! ! ! ", +"! ! ! ! | } ~ !!!#!$!!!%!o O &!B b t !!'!#!z z w (!b ! ! ! ! ! ", +"! ! ! ! } )!*!~ !!!!#!+!,!-!.!0!v 1!2!.!'!3!z 4!x z 5!b ! ! ! ! ", +"! | ! o 6!7!e ~ 8!9!~ :!!!;!!?!4!@!5!A!B!! ! ! ", +"! ! ! C!D!E!F!F!~ e ~ G!H!D!I!J!K!+!2!L!L!!=!=!?!@!N!Y!Z!C ! ! ", +"' ! [!]!^!_!`!a!V!9!V!8!V!b!v n c!8!d!;!b!L!>!e!?!f!Y!Y!g!h!! | ", +"' ! i!D!^!U!F!`!6!j!V!V!c!8! !p c!c!;!b!L!>!z ?!k!O!O!Y!l!5 ! | ", +"| ! m!n!_!F!e 6!F!j!V!9!8!V!V!V!c!c!;!b!L!>!4!@!k!o!p!q!l!5 ! | ", +"# ! r!6!T!9!`!8!V!j!V!9!~ V!8!V!;!c!;!L!>!>!M!f!O!O!O!q!s!5 ! | ", +"' ! t!D!u!F!`!a!a!a!V!8!8!V!c!V!c!;!;!v!?!(!M!5!O!Y!q!q!A!w!! | ", +"' ! [!D!^!`!e V!a!8!8!#!9!;!V!c!;!;!L!>!M!4!x!5!O!Y!q!y!Z!B!! D ", +"' ! % z!{!e F!V!a!V!V!8!8!c!V!;!V!;!v!>!e!?!M!5!f!y!y!l!|!C ! ! ", +"! ! Q!t!}!`!j!a!a!V!8!V!V!V!V!#!V!;!L!L!>!e!M!M!O!q!Y!~! #! ! ! ", +"! ! ! % g !#a!a!V!8!8!V!V!V!V!$!;!;!L!>!>!>!M!k!k!Y!##$#C ! ! ! ", +"! ! ! ! [!%#V!`!!!c!V!V!V!V!V!;!;!L!L!L!>!>!M!M!k!&#'#& ! ! ! ! ", +"! ! ! ! Q!(#~ V!a!V!e U!8!;!;!;!;!b!L!L!>!>!M!M!)#*#% ! ! ! ! ! ", +"! ! ! ! ! C +#,#V!j!8!k 8!8!V!V!$! !-#L!>!>!?!.#'#% ! ! ! ! ! ! ", +"! ! ! ! ! ! Q!5 j 0#;!a!V!8!8!V!c!8!;!1#L!2#3#a & ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! B!+#4#$!8!V!V!8!c!V!V!5#6#7#w!' ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ' % 8#9#!!d!8!8!0#:#;#<#B!! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! C #=#>#,#*!?#@# #' ! ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ! ' B!5 A#B#C ! ! ! ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! ! ' ! ! ! ! ! ! ' ! ! ! ! ! ! ! ! ! ! ! ! "}; + +static const char* const image_comm32_data[] = { +"32 32 198 2", +" c None", +"! c white", +"# c #F8F8F8", +"$ c #F4F4F4", +"% c #FCFCFC", +"& c #E4E0E0", +"' c #A49CA0", +"( c #484048", +") c #D8D8D8", +"* c #584850", +"+ c #181018", +", c #C0C0C0", +"- c #B0B0B0", +". c #A8A8A8", +"0 c #D8D0D0", +"1 c #180810", +"2 c #282028", +"3 c #605858", +"4 c #080008", +"5 c #686068", +"6 c #989090", +"7 c black", +"8 c #D0C8C8", +"9 c #605050", +": c #100810", +"; c #201018", +"< c #505050", +"= c #908888", +"> c #181010", +"? c #100808", +"@ c #201820", +"A c #201818", +"B c #606060", +"C c #100008", +"D c #E0D8D8", +"E c #707070", +"F c #E8F0E8", +"G c #705868", +"H c #401030", +"I c #180010", +"J c #282020", +"K c #808088", +"L c #F8F0F0", +"M c #E0D0D8", +"N c #984070", +"O c #900858", +"P c #901860", +"Q c #781050", +"R c #480838", +"S c #180818", +"T c #E8E8E8", +"U c #B0A8A8", +"V c #A09098", +"W c #807878", +"X c #B0A8B0", +"Y c #B880A0", +"Z c #801850", +"[ c #880850", +"] c #881058", +"^ c #981060", +"_ c #800850", +"` c #B84090", +"a c #403038", +"b c #281820", +"c c #404040", +"d c #787878", +"e c #888080", +"f c #484040", +"g c #D8B8C8", +"h c #780040", +"i c #901058", +"j c #600838", +"k c #681048", +"l c #801050", +"m c #601040", +"n c #A82078", +"o c #B84888", +"p c #B03870", +"q c #683058", +"r c #983068", +"s c #581040", +"t c #400828", +"u c #280018", +"v c #200010", +"w c #282830", +"x c #303038", +"y c #E0E0E0", +"z c #D0A8B8", +"{ c #A04870", +"| c #A01068", +"} c #701048", +"~ c #B01078", +" ! c #A80868", +"!! c #A00868", +"#! c #B02878", +"$! c #A81868", +"%! c #781048", +"&! c #A01870", +"'! c #A81870", +"(! c #A01868", +")! c #983870", +"*! c #A89898", +"+! c #F0F0F0", +",! c #B888A0", +"-! c #701040", +".! c #A80870", +"0! c #981860", +"1! c #A81068", +"2! c #A81070", +"3! c #F0E8F0", +"4! c #882860", +"5! c #980858", +"6! c #500830", +"7! c #480828", +"8! c #801058", +"9! c #681040", +":! c #900058", +";! c #903868", +"! c #700840", +"?! c #A01060", +"@! c #580838", +"A! c #B090A0", +"B! c #F0E0E8", +"C! c #680838", +"D! c #B06890", +"E! c #F0E8E8", +"F! c #880050", +"G! c #981068", +"H! c #C01080", +"I! c #B80870", +"J! c #C878A8", +"K! c #780048", +"L! c #901060", +"M! c #980860", +"N! c #680840", +"O! c #B81078", +"P! c #C01078", +"Q! c #802058", +"R! c #900860", +"S! c #580830", +"T! c #B00870", +"U! c #881050", +"V! c #A03878", +"W! c #D0D0D0", +"X! c #B080A0", +"Y! c #B01878", +"Z! c #801858", +"[! c #C02080", +"]! c #987890", +"^! c #980868", +"_! c #C82090", +"`! c #C098B0", +"a! c #B01068", +"b! c #800848", +"c! c #D01888", +"d! c #C05898", +"e! c #A00860", +"f! c #B81080", +"g! c #C01888", +"h! c #B81878", +"i! c #B05090", +"j! c #E0E8E0", +"k! c #B098A8", +"l! c #B01070", +"m! c #B81070", +"n! c #A81878", +"o! c #903070", +"p! c #F0F8F0", +"q! c #B08098", +"r! c #986888", +"s! c #D8E0E0", +"t! c #600830", +"u! c #901050", +"v! c #B088A0", +"w! c #883868", +"x! c #780840", +"y! c #C00878", +"z! c #982870", +"{! c #B8B8B8", +"|! c #987088", +"}! c #805878", +"~! c #884870", +" # c #A06888", +"!# c #A08898", +"## c #D8E0D8", +"$# c #883068", +"%# c #804870", +"&# c #B00868", +"'# c #981868", +"(# c #887888", +")# c #A098A0", +"*# c #A088A0", +"+# c #988898", +",# c #C8C8C8", +"-# c #D0D8D8", +".# c #C0C8C0", +"! ! ! ! # $ # % ! ! % ! ! ! % ! ! ! & ' ! % ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! % % ! ! ! ! % ! ' ( ) * + , ! % ! ! ! ! ! ! ! ! ! ", +"! ! ! ! - . ) ! ! % % % % ! 0 1 2 3 1 4 5 % % ! ! ! ! ! ! ! ! ! ", +"! % % ! 6 7 4 3 8 ! ! ! % ! 9 : 2 ; + : < $ ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! # = > 7 ? ( ' # ! 0 ; @ @ A A : B $ ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! # - < > 4 C ( D = ? @ A @ A : E # % % % % % % % % ! ! ", +"! ! ! ! ! ! % F - G H I 2 2 + J A @ @ : K # % ! ! ! ! ! ! ! ! ! ", +"! ! ! ! % ! ! L M N O P Q R S : + : > + . ! ! T 0 U V 6 W X # % ", +"! ! ! ! % % Y Z [ O ] ^ _ ` W a b c ; : d e f A C 7 7 7 : 5 T ! ", +"! ! ! % ! g h O i j k l m n o p q T r s t u v b w x < d - y # ! ", +"! ! ! % z { O | } } ~ ] } ~ !!!#!p $!%!&!'!(!)!*!8 y +!% ! ! ! ", +"! % ! ,!h O -!Q %!%!.!| m } %!0!1!.!i m 2!^ %!0!$!o 3!! % % ! ! ", +"% ! # 4!5!l 6!Q 7!8!| 2!^ ] 8!s k Z m P 1!1!] 9!'!:!,!% % % ! ! ", +"% ! % ;!:!%!!%!1!1!~ | 8!l ^ | ?!| ?!@!(!2!A!% ! ! ! ! ", +"% ! B!N :!i l C!9!i j | !!!2! !.!!!!!| 1!%!i ] 9!| D!# ! % ! ! ", +"% E!4!F!O j } 7!G!%!9!2!!!!!!!!!| | 2!] ^ ^ } H!-!] I!J!% ! % ! ", +"! g K!L!j @!] t O ^ @!i M!!!!!| 1!| .!i } i N!O!-!(!P!#!y ! % % ", +"! & Q!R!@!!9!~ b!8!'!n c!d!+!! % ! ", +"! D Z!:!^ 6!>!e!!!!l f!g!P h!i!j!! % % ", +"% % k!Q!M![ 7!j !!L!m j } | l!| L!2!m!O!m!} n!h!h!Z o!V p!! % ! ", +"% % % q!:!!![ 7!!! !1!%!^ 1!^ 1!O!m!l %!>!Q H!i %!P r!s!! ! ! ! ", +"! % ! `!F!M!G!j t!9! !i @!>!i %!u!U!-!Q Q 1!a!%!(!P!v!% ! % ! ! ", +"! % ! T w!:!M!G!G!} x!1!] &!O!2!l l | y!m!x!} ] O!z!{!% ! % ! ! ", +"! % ! ! 0 |!}!P T!| C!9!L!l!l 2!O!U!j i >!8!Y!)!~!V T ! % ! ! ! ", +"! ! ! ! ! p!F #:! !.!2!~ l!U!j C!Q ^ %!8!l!'!!###$ ! ! ! ! ! ! ", +"! ! ! ! % ! ! & r!$#%#0!&#&#&!L!^ a! !'#1!| ~!W!! ! % ! ! ! ! ! ", +"! ! ! ! ! % % ! +!W!##k!)!o!(#|!'#L!%#)#*#+#,## % % ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! ! ! ! # -#.#T +!X +#, # # # ! ! ! ! ! ! ! ! ! ! ", +"! ! ! ! ! ! ! ! % % % % ! ! ! ! ! % ! ! % ! % ! ! ! ! ! ! ! ! ! "}; + +static const char* const image_fs32_data[] = { +"32 32 351 2", +" c None", +"! c black", +"# c #97C9FB", +"$ c #95C6F8", +"% c #93C4F5", +"& c #D8EBFE", +"' c #86C7FE", +"( c #60B9FF", +") c #B7DDFE", +"* c #D1E7FE", +"+ c #D8E9FD", +", c white", +"- c #E4F2FE", +". c #35ABFE", +"0 c #71C1FD", +"1 c #B9D4F2", +"2 c #BDD7F6", +"3 c #EBF3FD", +"4 c #F8FBFE", +"5 c #ECF5FF", +"6 c #AAC9EC", +"7 c #A6C6EF", +"8 c #FCFEFF", +"9 c #F6FAFF", +": c #9FCFFF", +"; c #C4E2FF", +"< c #EAF4FF", +"= c #F5F9FE", +"> c #96B4D7", +"? c #9CBEE9", +"@ c #EFF6FE", +"A c #F6FBFF", +"B c #F0F8FF", +"C c #ABD5FF", +"D c #B6DAFF", +"E c #A5D2FF", +"F c #C8E3FF", +"G c #E9F2FC", +"H c #7C99C0", +"I c #92B3E1", +"J c #DDEAFA", +"K c #BADDFF", +"L c #AFD7FF", +"M c #B4D9FF", +"N c #AAD4FF", +"O c #C5E2FF", +"P c #EBF5FF", +"Q c #7691B5", +"R c #959A8A", +"S c #CBDEF5", +"T c #EAF5FF", +"U c #C7E3FF", +"V c #A3D1FF", +"W c #B3D9FF", +"X c #A8D3FF", +"Y c #AED6FF", +"Z c #ADD6FF", +"[ c #A8D4FF", +"] c #C2E0FF", +"^ c #C5D9F3", +"_ c #516685", +"` c #D2A624", +"a c #ECD89D", +"b c #F2E5BD", +"c c #D7D5C4", +"d c #ADCAEF", +"e c #DAEDFF", +"f c #E3F2FF", +"g c #CCE6FF", +"h c #9ECEFF", +"i c #BADCFF", +"j c #A7D3FF", +"k c #B0D8FF", +"l c #C8E4FF", +"m c #BAD1EF", +"n c #F2E3B7", +"o c #FFFEC8", +"p c #FFFFB1", +"q c #F7F9A3", +"r c #8FAFD8", +"s c #9DCEFF", +"t c #D5EAFF", +"u c #DDEFFF", +"v c #D1E8FF", +"w c #BBDDFF", +"x c #99CCFF", +"y c #B7DBFF", +"z c #AAD5FF", +"{ c #A1B9DE", +"| c #D9B23F", +"} c #FFFAE4", +"~ c #FFFF99", +" ! c #E8EAA1", +"!! c #92B3DD", +"#! c #D3EAFF", +"$! c #B4DAFF", +"%! c #B8DCFF", +"&! c #A1D0FF", +"'! c #CBE6FF", +"(! c #D7ECFF", +")! c #BCDEFF", +"*! c #87A5D4", +"+! c #F2DFAC", +",! c #FFFCB6", +"-! c #FFFB95", +".! c #E7E198", +"0! c #89ABDE", +"1! c #A4D1FF", +"2! c #AED7FF", +"3! c #A0D0FF", +"4! c #B5DAFF", +"5! c #9CCEFF", +"6! c #B2D9FF", +"7! c #D1E9FF", +"8! c #C1E0FF", +"9! c #9AC9FC", +":! c #6A81AA", +";! c #F2DEA8", +"! c #CECA9D", +"?! c #8EB6E9", +"@! c #A9D4FF", +"A! c #A6D2FF", +"B! c #CBE0EF", +"C! c #C9D1BF", +"D! c #B6B78F", +"E! c #B0A672", +"F! c #B1902F", +"G! c #BB9E48", +"H! c #A77D00", +"I! c #F2DCA2", +"J! c #FFF6A3", +"K! c #FFF892", +"L! c #FFEB85", +"M! c #CDC296", +"N! c #8DB4E7", +"O! c #A4D2FF", +"P! c #AEC3BF", +"Q! c #B5BD9F", +"R! c #B8B580", +"S! c #C2B160", +"T! c #CFC180", +"U! c #DFBF60", +"V! c #E6CC80", +"W! c #EFDFAF", +"X! c #F2E6BF", +"Y! c #FCF9EF", +"Z! c #AF8300", +"[! c #EFD590", +"]! c #FFF09C", +"^! c #FFF08A", +"_! c #FFDE78", +"`! c #B3AC9C", +"a! c #91BBEE", +"b! c #ACD5FF", +"c! c #B2D3EF", +"d! c #C6A940", +"e! c #ECD99F", +"f! c #FBFEFF", +"g! c #F0FDFF", +"h! c #E9FCFF", +"i! c #E2FCFF", +"j! c #B8DFFF", +"k! c #E6F2F9", +"l! c #FFFFF6", +"m! c #E2C66C", +"n! c #624900", +"o! c #E6C365", +"p! c #FFE893", +"q! c #FFE781", +"r! c #FFE680", +"s! c #FFD771", +"t! c #ABA6A0", +"u! c #9EB9C6", +"v! c #C5B260", +"w! c #F5ECCF", +"x! c #E0F3FF", +"y! c #BCE2FF", +"z! c #A0D3FF", +"{! c #BDF0FF", +"|! c #C0F3FF", +"}! c #AADDFF", +"~! c #BFDFF8", +" # c #FFFFEE", +"!# c #FCF9DF", +"## c #BC900F", +"$# c #E6C262", +"%# c #FFE59E", +"&# c #FFDF79", +"'# c #FCDA71", +"(# c #F2CE5B", +")# c #E6BD3D", +"*# c #DFB42E", +"+# c #E6C25C", +",# c #E2C670", +"-# c #E9D28F", +".# c #F9F2DF", +"0# c #E4F7FF", +"1# c #ABDEFF", +"2# c #9BCEFF", +"3# c #B5E8FF", +"4# c #B9ECFF", +"5# c #AEE1FF", +"6# c #ACCCE2", +"7# c #F9FCE4", +"8# c #FFFFE2", +"9# c #E6CC71", +":# c #6A5000", +";# c #E6C15D", +"<# c #FFDF95", +"=# c #FFD56F", +"># c #F2C653", +"?# c #DFBD57", +"@# c #FFFFF0", +"A# c #FFFFE6", +"B# c #FFFBC9", +"C# c #CCE4EA", +"D# c #B1E4FF", +"E# c #B3E6FF", +"F# c #AFE2FF", +"G# c #A1D0F8", +"H# c #F2DC89", +"I# c #FFFFDB", +"J# c #C99F1C", +"K# c #130E00", +"L# c #E6BF5A", +"M# c #FFDA8D", +"N# c #FFCE68", +"O# c #DFB643", +"P# c #FFFFF9", +"Q# c #FFFFCD", +"R# c #FFFFB7", +"S# c #FFFFA8", +"T# c #FFFCA1", +"U# c #F9EE92", +"V# c #ACD2E8", +"W# c #A5D8FF", +"X# c #ACDFFF", +"Y# c #9ACDFF", +"Z# c #E6E6A6", +"[# c #FFD873", +"]# c #FFFFCF", +"^# c #ECD982", +"_# c #826200", +"`# c #DCB036", +"a# c #FED787", +"b# c #FDCA62", +"c# c #F7C456", +"d# c #FFFFD9", +"e# c #FFFF9C", +"f# c #FFFB96", +"g# c #F9E68A", +"h# c #A0CEF7", +"i# c #A3D6FF", +"j# c #A6D9FF", +"k# c #9CCFFF", +"l# c #D2DAB8", +"m# c #FFF590", +"n# c #FFD973", +"o# c #FFFFC8", +"p# c #D6AC26", +"q# c #241B00", +"r# c #D9AB29", +"s# c #FCD788", +"t# c #F8C557", +"u# c #E7B437", +"v# c #FFFDB6", +"w# c #FFFC96", +"x# c #FFF18B", +"y# c #ECDB92", +"z# c #A0CDF6", +"{# c #BFD3CC", +"|# c #FFE882", +"}# c #FFD872", +"~# c #FFFFBC", +" $ c #F2E68D", +"!$ c #8E6A00", +"#$ c #D2A732", +"$$ c #FCD78A", +"%$ c #F3C04E", +"&$ c #DFB239", +"'$ c #FFFEF8", +"($ c #FFF791", +")$ c #ECD58B", +"*$ c #B3CFDB", +"+$ c #F9DC80", +",$ c #FFF58F", +"-$ c #FFFFB2", +".$ c #D9B32D", +"0$ c #342700", +"1$ c #D3A830", +"2$ c #FBD483", +"3$ c #ECB941", +"4$ c #FFFAD3", +"5$ c #FFE27C", +"6$ c #FFD16B", +"7$ c #F9F294", +"8$ c #A47B00", +"9$ c #D0A223", +":$ c #FAD17B", +";$ c #DFAC26", +"<$ c #FFF3B4", +"=$ c #FFED87", +">$ c #FFD46E", +"?$ c #DFBF3C", +"@$ c #513D00", +"A$ c #C49300", +"B$ c #FAD178", +"C$ c #D7A720", +"D$ c #FFE98A", +"E$ c #FCD86F", +"F$ c #B88A00", +"G$ c #BF8F00", +"H$ c #FFD581", +"I$ c #FFF6D6", +"J$ c #F5D565", +"K$ c #E9C347", +"L$ c #DCB027", +"M$ c #C99B10", +"N$ c #503C00", +"O$ c #EFC154", +"P$ c #FFEAAA", +"Q$ c #FCDA70", +"R$ c #F2CD5A", +"S$ c #E6BC3C", +"T$ c #D9AB1F", +"U$ c #AE8200", +"V$ c #8E6B00", +"W$ c #5F4700", +"X$ c #251C00", +"Y$ c #E2B43B", +"Z$ c #FFDA7B", +"[$ c #F9D064", +"]$ c #ECC148", +"^$ c #E2B533", +"_$ c #D6A516", +"`$ c #785A00", +"a$ c #533E00", +"b$ c #DFBC57", +"c$ c #FFF7E4", +"d$ c #F5C959", +"e$ c #E9BA3E", +"f$ c #DCAC23", +"g$ c #C9990E", +"h$ c #9A7300", +"i$ c #6C5100", +"j$ c #453400", +"k$ c #DCB950", +"l$ c #DFB94D", +"m$ c #161000", +" # $ % % % ", +" & ' ( ( ) * ", +" + , - . 0 , , 1 ", +" 2 , , , 3 4 5 5 , 6 ", +" 7 8 8 8 8 8 9 : ; < = > ", +" ? @ A A A A B C D E F B G H ", +" I J B B B B B K L L M N O P J Q ", +" R S T T T T T U V W X Y Z [ ] T ^ _ ", +" ` a b c d e f f f f g h i h i j k C j l f m ", +" n o p q r s t u u v s w x w s y E L z u u u { ", +" | } ~ ~ ~ !!!E #!#!E $!s $!s %!s $!&!'!(!(!(!)!*! ", +" +!,!~ ~ ~ -!.!0!1!)!z 1!2!3!2!s 4!5!6!5!7!7!8!9!:! ", +" ;!!?!@!w E A![ V L 5!L x 8!B!C!D!E!F!G!H! ", +" I!J!K!K!K!K!K!L!M!N!N M &!O!P!Q!R!S!T!U!V!W!X!, , Y!Z! ", +" [!]!^!^!^!^!^!^!_!`!a!b!c!d!e!X!Y!f!g!h!i!j!k!l!l!m!n! ", +" o!p!q!q!q!q!q!q!r!s!t!u!v!w!x!y!z!{!|!|!}!~! # #!###! ", +" $#%#&#&#&#'#(#)#*#+#,#-#.#0#1#2#3#4#4#5#6#7#8#8#9#:# ", +" ;#<#=#=#>#?#W!.#, @#A#B#C#}!D#5#E#E#F#G#H#I#I#I#J#K# ", +" L#M#N#N#O#P#Q#R#S#S#S#T#U#V#W#X#X#1#Y#Z#[#]#]#^#_# ", +" `#a#b#c#,#d#e#e#e#e#e#e#f#g#h#i#j#k#l#m#n#o#o#p#q# ", +" r#s#t#u#w!v#w#w#w#w#w#w#w#x#y#z#k#{#|#w#}#~# $!$! ", +" #$$$%$&$'$($($($($($($($($($L!)$*$+$,$($s!-$.$0$ ", +" 1$2$3$,#4$x#x#x#x#x#x#x#x#x#x#5$6$L!x#x#=#7$8$! ", +" 9$:$;$X!<$=$=$=$=$=$=$=$=$=$=$=$r!=$=$=$>$?$@$ ", +" A$B$C$, D$|#|#|#|#|#|#|#|#|#|#|#|#|#|#|#E$F$! ", +" G$H$U!I$5$5$5$5$5$5$5$5$5$5$5$5$5$J$K$L$M$N$ ", +" O$W!P$_!_!_!_!_!_!_!_!Q$R$S$T$U$V$W$X$! ", +" Y$, Z$}#}#}#}#[$]$^$_$8$`$a$K#! ", +" b$c$>$d$e$f$g$h$i$j$! ! ", +" k$l$U$V$W$X$! ", +" m$! ", +" "}; + +// 16*16*24b +static const char* const image_ai_data[] = { +"16 16 166 2", +" c None", +"! c white", +"# c #FEFEFF", +"$ c #FEFEFE", +"% c #FEFDFD", +"& c #F9F9F8", +"' c #D6D5D5", +"( c #FDFDFD", +") c #FEFFFF", +"* c #FEFFFE", +"+ c #FDFDFC", +", c #FEFEFD", +"- c #D5D4D3", +". c #E3E3E3", +"0 c #FFFFFE", +"1 c #FFFEFF", +"2 c #FFFEFE", +"3 c #F1EDF3", +"4 c #CECCCE", +"5 c #FEFBFB", +"6 c #FDFAFB", +"7 c #FCFAF9", +"8 c #EAF9CF", +"9 c #CAD5B3", +": c #EBEDE6", +"; c #BCD592", +"< c #76A837", +"= c #C7D8B2", +"> c #FEFCFC", +"? c #FCFDFB", +"@ c #FDFCFB", +"A c #E8B4B2", +"B c #DB8B8C", +"C c #E4A8A8", +"D c #F9EEEE", +"E c #EEF3FA", +"F c #CCD2D4", +"G c #F3FFFF", +"H c #FEFDFC", +"I c #FCFAFA", +"J c #F6E3E1", +"K c #C23B3A", +"L c #B50000", +"M c #BA0000", +"N c #BD0000", +"O c #CA2123", +"P c #D69291", +"Q c #E4AFAE", +"R c #F0A5A8", +"S c #EDB1B3", +"T c #F9F3F3", +"U c #FCF9F9", +"V c #C64848", +"W c #AE0000", +"X c #BD040A", +"Y c #C30309", +"Z c #C4010A", +"[ c #AB0008", +"] c #C20006", +"^ c #B70008", +"_ c #D20009", +"` c #DA000C", +"a c #DE2837", +"b c #F1D8DA", +"c c #FDFAFA", +"d c #EFD8D7", +"e c #B20407", +"f c #BA0206", +"g c #C00006", +"h c #C40009", +"i c #A30916", +"j c #C00009", +"k c #C0000A", +"l c #B20012", +"m c #CC051A", +"n c #E20523", +"o c #E6000D", +"p c #DE4A5D", +"q c #F8FCFC", +"r c #FEF9FA", +"s c #E9C8C7", +"t c #B50105", +"u c #C30008", +"v c #C70007", +"w c #D58580", +"x c #BA5655", +"y c #C04C50", +"z c #CB5557", +"{ c #D40116", +"| c #E4021F", +"} c #E6011D", +"~ c #D90C2A", +" ! c #E6DADE", +"!! c #F1E7E7", +"#! c #B61216", +"$! c #BF0104", +"%! c #BF0108", +"&! c #C00005", +"'! c #C91213", +"(! c #D01B20", +")! c #D51C24", +"*! c #DF1A29", +"+! c #DE011A", +",! c #DB001C", +"-! c #E3001D", +".! c #DB0829", +"0! c #DCCBD1", +"1! c #FDF8F8", +"2! c #FDFFFF", +"3! c #C8787A", +"4! c #B80000", +"5! c #BF050B", +"6! c #BE0106", +"7! c #C20003", +"8! c #C90007", +"9! c #D1000D", +":! c #D90012", +";! c #D80015", +"! c #C82644", +"?! c #E2EAEB", +"@! c #FCFCFC", +"A! c #F1F4F4", +"B! c #B84E52", +"C! c #B70000", +"D! c #C20002", +"E! c #C7030A", +"F! c #CB030F", +"G! c #D20315", +"H! c #D60318", +"I! c #DA031E", +"J! c #E7001A", +"K! c #D40018", +"L! c #BB939F", +"M! c #FBFFFF", +"N! c #EFF6F5", +"O! c #BC8082", +"P! c #B21317", +"Q! c #C20001", +"R! c #CC0004", +"S! c #D3000C", +"T! c #DB0011", +"U! c #DB0012", +"V! c #C40823", +"W! c #AF7987", +"X! c #F0FAF8", +"Y! c #FFFDFE", +"Z! c #FCFDFC", +"[! c #FCFFFF", +"]! c #D8D0D2", +"^! c #BB8489", +"_! c #B44C57", +"`! c #B63244", +"a! c #B73B50", +"b! c #B16471", +"c! c #C1B6BB", +"d! c #F4FDFB", +"e! c #FDFEFD", +"f! c #FDFCFC", +"g! c #ECFFFF", +"h! c #D6EFED", +"i! c #D9F4F1", +"j! c #F5FFFF", +"k! c #FFFCFC", +"l! c #FCFDFD", +"! ! ! ! ! ! # $ % $ & ' $ ( ( ! ", +"! ! ! ! ! ) * $ + , - . ! ( $ ! ", +"! 0 ! ) 1 ! 2 ( ! 3 4 ! $ $ $ ! ", +"2 $ $ $ 5 6 7 ( 8 9 : $ ( $ ! ! ", +"$ $ % ! ! ! ! ! ; < = > ? ( $ ! ", +") % ! @ A B C D E F G ! ) H ! $ ", +"I $ J K L M N O P Q R S T ! % * ", +"U ( V W X Y Z [ ] ^ _ ` a b 2 c ", +"! d e f g h i j k l m n o p q r ", +"$ s t j u v w x y z { | } ~ !! ", +"0 !!#!$!%!&!'!(!)!*!+!,!-!.!0!* ", +"1!2!3!4!5!6!7!8!9!:!;!!?!2 ", +"@!% A!B!C!D!E!F!G!H!I!J!K!L!M!c ", +"$ ( ! N!O!P!Q!R!S!T!U!V!W!X!Y!Z!", +"2 $ ( ! [!]!^!_!`!a!b!c!d!2 e!$ ", +"$ ! * f!1!! ! g!h!i!j!! k!l!) ) "}; + +static const char* const image_di_data[] = { +"16 16 171 2", +" c None", +"! c #FFFFFE", +"# c #FEFEFE", +"$ c #FFFEFE", +"% c #FEFFFF", +"& c #FEFDFC", +"' c #FBFBE8", +"( c #F1F16E", +") c #F6F6E2", +"* c white", +"+ c #FDFDF5", +", c #FEFEF8", +"- c #FEFEFD", +". c #FEFEFF", +"0 c #FEFEFA", +"1 c #FDFDFD", +"2 c #F1F170", +"3 c #F7F70F", +"4 c #EFEF58", +"5 c #F5F3F9", +"6 c #FDFEFF", +"7 c #F2EFBF", +"8 c #F0EE13", +"9 c #FDFC1E", +": c #FEFE0E", +"; c #F5F792", +"< c #FDFCAB", +"= c #F2F068", +"> c #F5F4E8", +"? c #FFFEFF", +"@ c #FCFCE9", +"A c #F5F3B8", +"B c #F6F744", +"C c #FBFA11", +"D c #F3EB1D", +"E c #E2D721", +"F c #C6B52D", +"G c #C8C156", +"H c #D0D183", +"I c #EAEAE2", +"J c #FEFFFE", +"K c #FDFDFB", +"L c #F6F6E9", +"M c #CFCB43", +"N c #CCC92F", +"O c #AB9633", +"P c #94714E", +"Q c #9A8B74", +"R c #8B6A7F", +"S c #5B176B", +"T c #66337F", +"U c #E0D7F1", +"V c #FCFCFD", +"W c #FDFDFC", +"X c #EFEEE6", +"Y c #D7D8C7", +"Z c #B4A9BD", +"[ c #45115E", +"] c #4E1E67", +"^ c #623473", +"_ c #733E7D", +"` c #845984", +"a c #79337E", +"b c #783988", +"c c #ECE8EE", +"d c #FEFDFE", +"e c #795C7B", +"f c #52175D", +"g c #744A7B", +"h c #7E5381", +"i c #79467B", +"j c #86548B", +"k c #7B328E", +"l c #731C88", +"m c #AD88B8", +"n c #FDFBFD", +"o c #FDFCFD", +"p c #DEDADD", +"q c #4C2253", +"r c #5F216C", +"s c #6B2C79", +"t c #76397E", +"u c #7A2E81", +"v c #742385", +"w c #772D8D", +"x c #7F2690", +"y c #8A439A", +"z c #F3F3F4", +"{ c #FCFBFC", +"| c #C6BAC5", +"} c #471950", +"~ c #652672", +" ! c #651C72", +"!! c #5E146D", +"#! c #701A78", +"$! c #772581", +"%! c #73287F", +"&! c #82298D", +"'! c #832E93", +"(! c #DED6E2", +")! c #FBFAFB", +"*! c #BBA9BA", +"+! c #4F165A", +",! c #682376", +"-! c #681C73", +".! c #6D1D7C", +"0! c #792186", +"1! c #7F258C", +"2! c #802A8E", +"3! c #893099", +"4! c #9034A6", +"5! c #D7C5DD", +"6! c #FAF9FC", +"7! c #C4B4C4", +"8! c #551860", +"9! c #661F72", +":! c #691C73", +";! c #6C1B79", +"! c #822793", +"?! c #8D329D", +"@! c #993AAE", +"A! c #D3C0DA", +"B! c #FAF9FB", +"C! c #DAD2DA", +"D! c #631F6A", +"E! c #74217D", +"F! c #76217E", +"G! c #6C1D75", +"H! c #701F7D", +"I! c #7E248E", +"J! c #892591", +"K! c #8A3099", +"L! c #9540A5", +"M! c #DBD4DE", +"N! c #FEFDFD", +"O! c #F9F9F9", +"P! c #754677", +"Q! c #65106E", +"R! c #84298B", +"S! c #78217E", +"T! c #772083", +"U! c #83258E", +"V! c #852C94", +"W! c #862496", +"X! c #9759A7", +"Y! c #F1F4F2", +"Z! c #CEC7D0", +"[! c #581C5F", +"]! c #67106E", +"^! c #751779", +"_! c #781A80", +"`! c #7E1E8F", +"a! c #811E90", +"b! c #7B2B84", +"c! c #C3B8C6", +"d! c #D0CBD1", +"e! c #805F84", +"f! c #733879", +"g! c #773681", +"h! c #83478D", +"i! c #96709D", +"j! c #CBC7CC", +"k! c #FEFFFD", +"l! c #FDFDFE", +"m! c #E2EAE2", +"n! c #D2D9D4", +"o! c #E4EFE4", +"p! c #FCFBFD", +"q! c #FDFEFE", +"! # $ % & ! ' ( ) * + , - # * * ", +". ! . - 0 1 2 3 4 5 . 6 * # # . ", +"! # # . * 7 8 9 : ; < = > ? 1 $ ", +"# # * @ A B C D E F G H I J 1 # ", +"K # L M N O P Q R S T U * V # # ", +"W * X Y Z [ ] ^ _ ` a b c d 1 # ", +"% # . * e f g h i j k l m * n # ", +"# o ! p q r s t u v w x y z $ 1 ", +"# { # | } ~ !!!#!$!%!&!'!(!* )!", +"J )!* *!+!,!-!.!0!1!2!3!4!5!# 6!", +"# { # 7!8!9!:!;!!?!@!A!. B!", +"$ o * C!D!E!F!G!H!I!J!K!L!M!* )!", +"# 1 N!O!P!Q!R!S!T!U!V!W!X!Y!# 1 ", +"$ # { * Z![!]!^!_!`!a!b!c!* o # ", +"? * # 1 * d!e!f!g!h!i!j!k!l!- J ", +"! # . # )!* * m!n!o!* * p!q!$ # "}; + +static const char* const image_pi_data[] = { +"16 16 199 2", +" c None", +"! c #FEFEFF", +"# c #FFFFFE", +"$ c #FEFEFE", +"% c white", +"& c #FDFFFE", +"' c #F4F8F0", +"( c #F7F9F4", +") c #DFEED6", +"* c #BEDBB1", +"+ c #FDFFFA", +", c #F6FAF5", +"- c #FDFDFE", +". c #FEFFFF", +"0 c #FDFDFD", +"1 c #DEE9CB", +"2 c #F4F5EC", +"3 c #AACC91", +"4 c #BFD1AB", +"5 c #93BD7B", +"6 c #A7BC93", +"7 c #C5E0B6", +"8 c #9FBA8C", +"9 c #FBF6FB", +": c #FFFEFE", +"; c #FDFDFC", +"< c #FEFEFD", +"= c #B2C698", +"> c #83BF62", +"? c #88CA70", +"@ c #71C152", +"A c #6FB750", +"B c #81BE6C", +"C c #69B551", +"D c #8ABD7D", +"E c #9DC885", +"F c #DEDFD4", +"G c #FEFDFD", +"H c #FEFFFE", +"I c #B2AB83", +"J c #7A7E2A", +"K c #7F873A", +"L c #88954E", +"M c #80863B", +"N c #897C39", +"O c #867B31", +"P c #A39F82", +"Q c #F7FEFF", +"R c #FDFCFB", +"S c #FCF6F5", +"T c #C88377", +"U c #A9231C", +"V c #9F0000", +"W c #C84450", +"X c #B0888E", +"Y c #C06463", +"Z c #AB0504", +"[ c #9B090F", +"] c #C11C22", +"^ c #DF8183", +"_ c #FDFCFC", +"` c #FBFAF9", +"a c #FFFDFD", +"b c #B46F60", +"c c #860D00", +"d c #961C0D", +"e c #89190E", +"f c #9F251C", +"g c #8E170C", +"h c #A52B23", +"i c #8E150F", +"j c #99120F", +"k c #B20505", +"l c #B20000", +"m c #DC6F7C", +"n c #FDFFFF", +"o c #FDF8F8", +"p c #E2C5BF", +"q c #7E240F", +"r c #942C16", +"s c #A0240D", +"t c #902010", +"u c #7F160C", +"v c #A75751", +"w c #872016", +"x c #A41006", +"y c #B80C03", +"z c #B50909", +"{ c #BF0712", +"| c #CD0C1F", +"} c #EED4D9", +"~ c #B7867C", +" ! c #872008", +"!! c #9E2B14", +"#! c #9C240E", +"$! c #A3200B", +"%! c #A61B0A", +"&! c #B13C2D", +"'! c #A9210E", +"(! c #AC1505", +")! c #B80D03", +"*! c #BE0306", +"+! c #CF0617", +",! c #D80011", +"-! c #DA99A3", +".! c #AA7164", +"0! c #871F07", +"1! c #9A2A13", +"2! c #A7250B", +"3! c #A3220B", +"4! c #9C1E0C", +"5! c #A31802", +"6! c #AA1A06", +"7! c #B31404", +"8! c #BD0603", +"9! c #C6010E", +":! c #D3061A", +";! c #D70012", +"! c #841E08", +"?! c #A82911", +"@! c #AF2107", +"A! c #9C200D", +"B! c #9F1C0C", +"C! c #AC1D09", +"D! c #AC1907", +"E! c #BA0A02", +"F! c #BC020A", +"G! c #CD0112", +"H! c #DF0317", +"I! c #D4061C", +"J! c #D4AFB8", +"K! c #DBCAC7", +"L! c #97270F", +"M! c #AA250D", +"N! c #AA200A", +"O! c #A21F0B", +"P! c #A71E09", +"Q! c #A41C09", +"R! c #AB1907", +"S! c #BB0A02", +"T! c #C20203", +"U! c #CD0410", +"V! c #DF0010", +"W! c #BF374D", +"X! c #E8EDEF", +"Y! c #FCFAFA", +"Z! c #B98079", +"[! c #A31400", +"]! c #AA210E", +"^! c #A2210E", +"_! c #AA1908", +"`! c #B21505", +"a! c #B81003", +"b! c #C20904", +"c! c #D40004", +"d! c #C10C24", +"e! c #CCBCC4", +"f! c #FCF9FA", +"g! c #FCFCFC", +"h! c #F5F7F9", +"i! c #B1736F", +"j! c #A31903", +"k! c #9F1A03", +"l! c #A3210D", +"m! c #AC1E0A", +"n! c #A61809", +"o! c #B71604", +"p! c #BD0000", +"q! c #AE1C2C", +"r! c #C1A7B1", +"s! c #FBFFFF", +"t! c #FDFCFD", +"u! c #FDFEFD", +"v! c #FAFFFF", +"w! c #CBAEAF", +"x! c #A63F35", +"y! c #9A1603", +"z! c #9F1802", +"{! c #A41702", +"|! c #9E1309", +"}! c #A3525C", +"~! c #D5D5DA", +" # c #FEFCFC", +"!# c #FDFEFE", +"## c #FEFDFC", +"$# c #EBEEF0", +"%# c #BD9C9D", +"&# c #A04E48", +"'# c #973E3E", +"(# c #B79EA5", +")# c #EEF7F8", +"*# c #FDFBFC", +"+# c #FFFEFF", +",# c #FBF8F8", +"-# c #EFFBFE", +".# c #DDE8EB", +"0# c #FBFAFA", +"! # $ % & ' ( ) * % + , - $ $ . ", +"$ $ 0 1 2 3 4 5 6 7 8 9 % 0 $ : ", +"0 ; < = > ? @ A B C D E F $ 0 $ ", +". G H % I J K L M N O P Q G 0 H ", +"R G S T U V W X Y Z [ ] ^ _ G G ", +"` a b c d e f g h i j k l m n o ", +"% p q r s t u v w x y z { | } # ", +"$ ~ !!!#!$!%!&!'!(!)!*!+!,!-!. ", +"% .!0!1!2!3!4!5!6!7!8!9!:!;!!?!@!A!B!C!D!E!F!G!H!I!J!. ", +"% K!L!M!N!O!P!Q!R!S!T!U!V!W!X!a ", +"Y!. Z![!]!^!P!_!`!a!b!c!d!e!% f!", +"g!G h!i!j!k!l!m!n!o!p!q!r!s!t!u!", +"$ G : v!w!x!y!z!{!|!}!~!% #$ $ ", +"% % !###% $#%#&#'#(#)#% *#$ % +#", +"$ $ % u!,#% % -#.#% a 0#+#. $ H "}; + +static const char* const image_comm_data[] = { +"16 16 200 2", +" c None", +"! c white", +"# c #FEFEFE", +"$ c #F5F5F5", +"% c #FCFCFC", +"& c #F1EEEF", +"' c #CFC9CA", +"( c #8D8789", +") c #ECECED", +"* c #FDFDFD", +"+ c #FFFFFE", +", c #FAFAFA", +"- c #B5B1B3", +". c #A39FA0", +"0 c #FEFDFD", +"1 c #80777A", +"2 c #3F343A", +"3 c #231920", +"4 c #BEBDBF", +"5 c #FBFBFB", +"6 c #FFFEFF", +"7 c #CDCBCC", +"8 c #332D31", +"9 c #333133", +": c #9EA19F", +"; c #E0E0DD", +"< c #281C22", +"= c #1B1218", +"> c #140910", +"? c #B1AEB1", +"@ c #F9FEFC", +"A c #8E7683", +"B c #49042D", +"C c #532E44", +"D c #181619", +"E c #120B11", +"F c #151317", +"G c #D4D7D7", +"H c #FEFDFC", +"I c #E7E2E3", +"J c #D6D3D3", +"K c #E0DFE0", +"L c #B76994", +"M c #962264", +"N c #860F54", +"O c #931D68", +"P c #793961", +"Q c #5A4552", +"R c #4A263A", +"S c #6D5964", +"T c #493F44", +"U c #2E2F2E", +"V c #353033", +"W c #9A989B", +"X c #FDFCFC", +"Y c #F7F1F3", +"Z c #B66F96", +"[ c #80004B", +"] c #730A47", +"^ c #8D105F", +"_ c #7E1355", +"` c #9E1466", +"a c #B7357F", +"b c #8F1C5D", +"c c #820450", +"d c #7E1755", +"e c #AC7D99", +"f c #EAEAEB", +"g c #E2CCD7", +"h c #82004A", +"i c #670F40", +"j c #700F4A", +"k c #960E60", +"l c #930F60", +"m c #851059", +"n c #790A4C", +"o c #8B115B", +"p c #A7176C", +"q c #820F4F", +"r c #A3206F", +"s c #ECEBEC", +"t c #FCFBFB", +"u c #BC7FA3", +"v c #830750", +"w c #6A0D42", +"x c #780C4C", +"y c #810D51", +"z c #A50B6A", +"{ c #A60C6D", +"| c #A20D69", +"} c #A30C68", +"~ c #910E58", +" ! c #851254", +"!! c #8A0D57", +"#! c #DB9FC3", +"$! c #FCF8FA", +"%! c #F8FBF8", +"&! c #9B3A75", +"'! c #68013D", +"(! c #6C0E45", +")! c #800B4F", +"*! c #830D54", +"+! c #A10B69", +",! c #A10B68", +"-! c #A90C6E", +".! c #920C5A", +"0! c #760D49", +"1! c #991164", +"2! c #99085E", +"3! c #B9478C", +"4! c #F4FCF8", +"5! c #FFFBFE", +"6! c #FDFEFD", +"7! c #AE5F8D", +"8! c #7D004C", +"9! c #740F4C", +":! c #770C4A", +";! c #860C55", +"! c #AC0A6B", +"?! c #820D4F", +"@! c #8C0E59", +"A! c #981360", +"B! c #A3106B", +"C! c #C97FB0", +"D! c #FBFEFD", +"E! c #FEF8FC", +"F! c #F7FBF9", +"G! c #9A3672", +"H! c #78014A", +"I! c #770D48", +"J! c #7F0B4F", +"K! c #831053", +"L! c #920E5E", +"M! c #9C0D63", +"N! c #7F0D4C", +"O! c #900D5A", +"P! c #8B0E56", +"Q! c #9B1768", +"R! c #AC1271", +"S! c #BF639E", +"T! c #FBFFFD", +"U! c #FEF9FD", +"V! c #D2C0CB", +"W! c #910B5D", +"X! c #700A44", +"Y! c #8C0C5A", +"Z! c #850E53", +"[! c #890D55", +"]! c #9D0D62", +"^! c #A00D66", +"_! c #930D5A", +"`! c #8B0F59", +"a! c #A9176B", +"b! c #90175E", +"c! c #C1ADBC", +"d! c #FEFFFE", +"e! c #FBFAFB", +"f! c #FDFCFD", +"g! c #FBFDFB", +"h! c #A14D80", +"i! c #870054", +"j! c #810D50", +"k! c #870E53", +"l! c #871259", +"m! c #9E1365", +"n! c #8C1054", +"o! c #8B1055", +"p! c #91135B", +"q! c #8B0C56", +"r! c #9F3578", +"s! c #EDEDED", +"t! c #FEFDFE", +"u! c #EDF2F0", +"v! c #C1A3B5", +"w! c #9A1668", +"x! c #880957", +"y! c #A9096A", +"z! c #8B0754", +"{! c #8B0852", +"|! c #870850", +"}! c #8E0055", +"~! c #A75D8D", +" # c #D7D8D9", +"!# c #D4CDD3", +"## c #C2A1B6", +"$# c #A85085", +"%# c #A46A90", +"&# c #9B3170", +"'# c #A96C93", +"(# c #B285A3", +")# c #E1DEDF", +"*# c #FEFFFF", +"+# c #FCFDFC", +",# c #FBF9FA", +"-# c #EFFFF9", +".# c #D7E4DD", +"0# c #F3FFFA", +"1# c #FAFBFB", +"! # ! ! # $ % & ' ( ) ! * # # + ", +", # - . 0 ! ! 1 2 3 4 # 5 * 0 6 ", +", # 7 8 9 : ; < = > ? ! ! ! ! # ", +"! * ! @ A B C D E F G H I J K # ", +"* ! ! L M N O P Q R S T U V W ! ", +"X Y Z [ ] ^ _ ` a b c d e f ! 0 ", +"! g h i j k l m n o p q r s * t ", +"* u v w x y z { | } ~ !!!#!# $!", +"%!&!'!(!)!*!+!,!-!.!0!1!2!3!4!5!", +"6!7!8!9!:!;!!?!@!A!B!C!D!E!", +"F!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!", +"! V!W!X!Y!Z![!]!^!_!`!a!b!c!d!e!", +"f!g!h!i!j!k!l!m!n!o!p!q!r!s!6 % ", +"X t!u!v!w!x!y!z!{!|!}!~! #* # # ", +"d!t!! ! !###$#%#&#'#(#)#! f!# ! ", +"# *#+#,#! ! -#*#.#0#! ! 1#d!! # "}; + +static const char* const image_fs_data[] = { +"16 16 55 1", +" c None", +"! c black", +"# c #7394C4", +"$ c #5CB7FF", +"% c #7090C0", +"& c white", +"' c #CC9933", +"( c #CB9832", +") c #6C8CBC", +"* c #FAFDFF", +"+ c #B4DAFF", +", c #30A7FD", +"- c #6987B7", +". c #F2F9FF", +"0 c #CBE8FF", +"1 c #FFFF99", +"2 c #6581B1", +"3 c #EAF6FF", +"4 c #FFF791", +"5 c #FFF48E", +"6 c #617DAD", +"7 c #E2F3FF", +"8 c #C99630", +"9 c #FFEB85", +": c #5E79A9", +"; c #B0BAB6", +"< c #B3801A", +"= c #C7942E", +"> c #FFE07A", +"? c #DDEBF0", +"@ c #A3700A", +"A c #C5922C", +"B c #FFD46E", +"C c #BBBFCD", +"D c #AEDAFF", +"E c #A06D07", +"F c #C28F29", +"G c #FFCC66", +"H c #9E6B05", +"I c #C08D27", +"J c #9C6903", +"K c #BD8A24", +"L c #BF8C26", +"M c #9A6701", +"N c #BA8721", +"O c #B8851F", +"P c #D0AC57", +"Q c #D3A03A", +"R c #996600", +"S c #B5821C", +"T c #B07D17", +"U c #AE7B15", +"V c #AB7812", +"W c #A8750F", +"X c #A5720C", +" #######$ ", +" %&&&&&&$$ ", +" '()*++++*,,, ", +" '&&-......00- ", +"'&1123++++++32! ", +"(4556777777776! ", +"89'':;;;;;;;;:< ", +"=>'&?&&&&&&&&?@ ", +"AB'1C?DDDDDD?CE!", +"FG(1C????????CH!", +"IGA1C????????CJ!", +"KGL1CCCCCCCCCCM!", +"NGO1BPPPPPPPQ1R!", +" S +/*------------------------------------------------------------------------------------- + 平台无关的INI文件读函数(字符串),和同类API相比,只是参数类型从const char*变成char* + 返回值类型从DWORD改成int,这里返回值的意义从读取字节个数(同名API返回DWORD类型)变成 + 了读取成功与否标志(int类型),但并不影响使用 +-------------------------------------------------------------------------------------*/ +int QGetPrivateProfileString( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + char* lpszDefault, //缺省字符串 + char* lpszReturnedString, //结果字符串 + u_32 nSize, //结果字符串长度 + char* lpszFileName, //ini文件名 + char* lpszRemarkInLineStr, //行内注释符 + char chContinueLineChar //续行符号 +) +{ + FILE* IniFile = NULL; + BOOL bSecFoundFlag = FALSE; + BOOL bKeyFoundFlag = FALSE; + BOOL bEOF = FALSE; + char szLineBuf[MAX_LINE_BUF_LENGTH]; //行缓冲区 + char szKeyItemBuf[MAX_LINE_BUF_LENGTH*4]; //最终内容缓冲区(因键所在行可能因使用续行符而占据多行) + char *lpszFileText = NULL; //放置INI文件全部内容的字符串 + char *lpszLineBegin = NULL; //一行开始指针 + char *lpszTmp = NULL; + i_32 lFileSize = 0; + int iPos, iRetVal; + + BOOL bLineContinue = FALSE; //2002.10.3 续行标志 + + /*--------------------------------------------------------------------------------- + + char szLineEndStr[3]; //行末尾换行符号 + memset(szLineEndStr, 0, 3); + + #ifdef OS_UNIX + strcpy(szLineEndStr, "\n"); //UNIX文本文件行末只有一个换行符'\n' + #else + strcpy(szLineEndStr, "\r\n"); //Windows文本文件行末有一个回车符'\r',一个换行符'\n' + #endif + + ----------------------------------------------------------------------------------*/ + + IniFile = fopen(lpszFileName, "rb"); //二进制可读方式打开(文件必须存在) + if(!IniFile) + { + //qDebug("fopen error, %s", lpszFileName); + return FILE_OPEN_ERROR; + } + + fseek(IniFile, 0, SEEK_END); //定位到文件尾部 + lFileSize = ftell(IniFile); //获取文件尾指针位置(该值=文件总长=文件指针位置最大值+1) + + lpszFileText = new char[lFileSize+1]; + memset(lpszFileText, 0, lFileSize+1); + + fseek(IniFile, 0, SEEK_SET); //重新定位到开头 + fread(lpszFileText, 1, lFileSize, IniFile); //将文件所有内容全部读入字符串 + fclose(IniFile); //读入全部内容后立即关闭文件 + + lpszLineBegin = lpszFileText; + + //段搜索 + + /*---------------------------------------------------------------------------- + + //while(!feof(IniFile)) + while(!bEOF) + { + //ReadLineFromFile(IniFile, szLineBuf, MAX_LINE_BUF_LENGTH); //读取一行 + + memset(szLineBuf, 0, MAX_LINE_BUF_LENGTH); + + lpszTmp = strstr(lpszLineBegin, szLineEndStr); //搜索换行符号来定位行末 + + if(lpszTmp != NULL) + { + strncpy(szLineBuf, lpszLineBegin, min(MAX_LINE_BUF_LENGTH-1, lpszTmp-lpszLineBegin)); + lpszLineBegin = lpszTmp + strlen(szLineEndStr); + } + else //最后一行 + { + strncpy(szLineBuf, lpszLineBegin, min(MAX_LINE_BUF_LENGTH-1, lpszFileText+lFileSize-lpszLineBegin)); + bEOF = TRUE; + } + + StrTrimAll(szLineBuf); + + if( szLineBuf[0] == ';' || szLineBuf[0] == 0 ) continue; //注释行和空行不处理 + + //将一行尾部可能存在的";"注释部分剔除(这样key=value的value中不能含有;否则将被当成注释而删除 + lpszTmp = strchr(szLineBuf, ';'); + if(lpszTmp != NULL) *lpszTmp = 0; + + StrTrimAll(szLineBuf); //zl 2002.9.19 ";"和有用内容间必有空格或TAB字符,必须删除这些分割字符 + + iPos = strlen(szLineBuf) - 1; + + if(szLineBuf[0] == '[' && szLineBuf[iPos] == ']') //该行是一个段 + { + szLineBuf[iPos] = 0; //去掉"["和"]",便于比较 + lpszTmp = &szLineBuf[1]; + if( strcmp(lpszTmp, lpszSectionName) == 0 ) //指定的段找到了 + { + bSecFoundFlag = TRUE; + break; + } + } + } + + ----------------------------------------------------------------------------*/ + + //zl 2002.9.23 新的段搜索算法(直接在包含整个ini文件内容的字符串中定位段名) + + char szFindStr[MAX_LINE_BUF_LENGTH]; //搜索字符串 + sprintf(szFindStr, "[%s]", lpszSectionName); + + while(!bEOF) + { + lpszTmp = strstr(lpszLineBegin, szFindStr); + + if( lpszTmp != NULL ) //找到段名,继续验证其是否合法 + { + lpszLineBegin = lpszTmp + strlen(szFindStr); //计算新的查找起始位置 + + if( lpszLineBegin > (lpszFileText + lFileSize -1) ) bEOF = TRUE; + + if( lpszTmp == lpszFileText ) //"[xxx]"是文件的开头内容,为合法段名 + { + bSecFoundFlag = TRUE; + break; + } + + /*---------------------------------------------------------------------------- + 从'['向前查找,如果遇到换行符0xA,表明是合法段名,如果是空格或tab字符(ASC码9) + 则继续向前搜索,如果是此外的其它任何字符,该段名都判为非法, ']'后面的内容不 + 予处理 + ----------------------------------------------------------------------------*/ + + lpszTmp--; + + while( lpszTmp >= lpszFileText ) + { + if( *lpszTmp == 0xA ) + { + bSecFoundFlag = TRUE; + break; + } + else if( *lpszTmp == ' ' || *lpszTmp == 9 ) + lpszTmp--; + else + break; + } + + if( bSecFoundFlag ) break; //退出外循环 + } + else + break; //没找到段名,退出 + + } + + if( !bSecFoundFlag ) + { + iRetVal = SECTION_NOT_FOUND; + goto func_end; + } + + //继续键搜索(定位段后,对于所属键的查找为逐行读取扫描方式,键可能占用多行) + + while(!bEOF) + { + if( !bLineContinue ) + memset(szKeyItemBuf, 0, sizeof(szKeyItemBuf)); //关键,控制多行连接 + + memset(szLineBuf, 0, MAX_LINE_BUF_LENGTH); + + //zl 2002.9.27 为保证提取一行的操作与平台文件格式无关,只查找换行符(0x0A),这和fgets()类似 + lpszTmp = strchr(lpszLineBegin, 0x0A); + + if(lpszTmp != NULL) + { + strncpy(szLineBuf, lpszLineBegin, min(MAX_LINE_BUF_LENGTH-1, lpszTmp-lpszLineBegin)); //从字符串中提取一行 + + /* 读windows文本文件时,每行尾部多一个回车符(0x0D),必须去掉,否则后面连续出错 */ + if( szLineBuf[strlen(szLineBuf)-1] == 0x0D ) + szLineBuf[strlen(szLineBuf)-1] = 0; + + lpszLineBegin = lpszTmp + 1; //1表示"0x0A"一个字符 + } + else //最后一行 + { + strncpy(szLineBuf, lpszLineBegin, min(MAX_LINE_BUF_LENGTH-1, lpszFileText+lFileSize-lpszLineBegin)); + bEOF = TRUE; + } + + StrTrimAll(szLineBuf); + + //全注释行和空行不处理 + if( szLineBuf[0] == ';' || szLineBuf[0] == 0 ) + { + if( bLineContinue && strlen(szKeyItemBuf) > 0 ) //2002.10.7 如果前面是续行,则继续处理szKeyItemBuf已有内容而不是continue重新读入一行,否则当前行(空行或注释行)上面的一个续行的全部内容将丢失 + bLineContinue = FALSE; + else + { + bLineContinue = FALSE; + continue; + } + } + else + { + //2002.10.3 判断续行,续行符为行末最后的一个非空格或TAB字符,缺省为'\' + if( szLineBuf[strlen(szLineBuf)-1] == chContinueLineChar ) + { + bLineContinue = TRUE; + szLineBuf[strlen(szLineBuf)-1] = 0; //去掉续行符 + StrTrimAll(szLineBuf); + + strcat(szKeyItemBuf, szLineBuf); + continue; + } + else //无续行字符行 + { + bLineContinue = FALSE; + strcat(szKeyItemBuf, szLineBuf); + } + } + + //将一行尾部可能存在的行内注释部分(缺省行内注释符是";")剔除 + + //lpszTmp = strchr(szLineBuf, ';'); + lpszTmp = strstr(szKeyItemBuf, lpszRemarkInLineStr); //2002.10.3 可以任意指定行内注释符 + + if(lpszTmp != NULL) *lpszTmp = 0; + + StrTrimAll(szKeyItemBuf); //zl 2002.9.19 ";"和有用内容间必有空格或TAB字符,必须删除这些分割字符 + + iPos = strlen(szKeyItemBuf)-1; + + if(szKeyItemBuf[0] == '[' && szKeyItemBuf[iPos] == ']') //又到了一个段,说明指定段下的指定key没有找到 + { + iRetVal = KEY_NOT_FOUND; + goto func_end; + } + + lpszTmp = strchr(szKeyItemBuf, '='); //定位'=' + if(lpszTmp == NULL) continue; //不含等号的非段行被视为无效行 + + *lpszTmp = 0; //为便于操作,在'='位置将szLineBuf从中间截断, 将szLineBuf分成key和value两个部分 + StrTrimAll(szKeyItemBuf); //此时szLineBuf是key + + if(strcmp(szKeyItemBuf, lpszKeyName) == 0) //找到了指定key + { + lpszTmp++; + StrTrimAll(lpszTmp); //lpszTmp++是key对应的value + + if( strlen(lpszTmp) < nSize ) + strcpy(lpszReturnedString, lpszTmp); //返回key对应的value + else + strncpy(lpszReturnedString, lpszTmp, strlen(lpszTmp)); + + iRetVal = 1; //1表示正确 + bKeyFoundFlag = TRUE; + + break; + } + } + + if( !bKeyFoundFlag ) iRetVal = KEY_NOT_FOUND; + +func_end: + + delete [] lpszFileText; + + //如果出错同时缺省参数不为NULL,则返回缺省参数 + if( iRetVal < 0 && lpszDefault != NULL ) + { + if( strlen(lpszDefault) < nSize ) + strcpy(lpszReturnedString, lpszDefault); + else + strncpy(lpszReturnedString, lpszDefault, strlen(lpszDefault)); + } + + return iRetVal; +} + +/*------------------------------------------------------------------------------------- + 平台无关的INI文件读函数(整数),和同类API相比,只是参数类型从const char*变成char*, + 返回值类型从UINT改成int +-------------------------------------------------------------------------------------*/ +int QGetPrivateProfileInt( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + int nDefault, //缺省值 + char* lpszFileName, //ini文件名 + char* lpszRemarkInLineStr, //行内注释符 + char chContinueLineChar //续行符号 +) +{ + int iRet, iResult; + char szNumStr[256]; //数字字符串 + + iRet = QGetPrivateProfileString( + lpszSectionName, //段名 + lpszKeyName, //键名 + NULL, //缺省字符串 + szNumStr, //结果字符串 + 256, //结果字符串长度 + lpszFileName, //INI文件名 + lpszRemarkInLineStr, //行内注释符 + chContinueLineChar //续行符号 + ); + + //qDebug(lpszFileName); + + if(iRet < 0) return nDefault; //出错则返回缺省值 + + StrTrimAll(szNumStr); + + /*-------------------------------------------------------------------------------- + 因原先未考虑ini中用"0x1801"这种16进制字符串,导致转换时出错,因为atoi不认识16进制串 + 2002.9.18 加入非十进制字符串识别支持,目前只支持16进制,字符串格式为"0x数字" + --------------------------------------------------------------------------------*/ + + BOOL bIsHexFlag = FALSE; + + if( strlen(szNumStr) > 2 ) + { + if( szNumStr[0] == '0' && szNumStr[1] == 'x' ) bIsHexFlag = TRUE; + } + + if( bIsHexFlag ) + iRet = sscanf(&szNumStr[2], "%x", &iResult); //16进制 + else + iRet = sscanf(szNumStr, "%d", &iResult); //10进制 + + if( iRet != 1 ) //如数字字符串合法的话,应只转换一个field,故返回值不为1表示出错,此时返回缺省值 + return nDefault; + else + return iResult; //正确返回 + +} + + +/*------------------------------------------------------------------------------------- + 平台无关的INI文件写函数,和同类API相比,只是参数类型从const char*改成了char* + 目前该函数尚未对段搜索部分进行优化 +-------------------------------------------------------------------------------------*/ +BOOL QWritePrivateProfileString( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + char* lpszString, //要写入的字符串 + char* lpszFileName //INI文件名 +) +{ + FILE* IniFile; + char szLineBuf[MAX_LINE_BUF_LENGTH]; + char *lpszFrontBlock = NULL, *lpszRearBlock = NULL; //装入前后两块文件各自所占的内存区指针 + char *lpszTmp = NULL; + i_32 lPrePos = 0, lCurPos = 0; //前一次读取及本次读取的文件指针位置 + bool bSecFoundFlag = FALSE; + bool bKeyFoundFlag = FALSE; + bool bMeetAnotherBlock = FALSE; //遇到另外一个段 + i_32 lEndPos; + int iPos; + + char szLineEndStr[3]; //行末尾换行符号 + + #ifdef OS_UNIX + strcpy(szLineEndStr, "\n"); //UNIX文本文件行末只有一个换行符'\n' + #else + strcpy(szLineEndStr, "\r\n"); //Windows文本文件行末有一个回车符'\r',一个换行符'\n' + #endif + + IniFile = fopen(lpszFileName, "r+b"); //二进制方式打开,可读可写(但文件必须存在) + if(!IniFile) return false; + + fseek(IniFile, 0, SEEK_END); //定位到文件尾部 + lEndPos = ftell(IniFile); //计算文件尾部指针位置(该值=文件总长=文件指针位置最大值+1) + + fseek(IniFile, 0, SEEK_SET); //重新定位到开头 + + //先找指定的section + while(!feof(IniFile)) + { + lPrePos = lCurPos; //保留上次文件指针位置 + + ReadLineFromFile(IniFile, szLineBuf, MAX_LINE_BUF_LENGTH); //读取一行 + + lCurPos = ftell(IniFile); //当前文件指针位置 + + StrTrimAll(szLineBuf); + + if( szLineBuf[0] == ';' || szLineBuf[0] == 0 ) continue; //注释行和空行不处理 + + //将一行尾部可能存在的";"注释部分剔除(这样key=value的value中不能含有;否则将被当成注释而删除 + lpszTmp = strchr(szLineBuf, ';'); + if(lpszTmp != NULL) *lpszTmp = 0; + + StrTrimAll(szLineBuf); //zl 2002.9.19 ";"和有用内容间必有空格或TAB字符,必须删除这些分割字符 + + iPos = strlen(szLineBuf) - 1; + + if(szLineBuf[0] == '[' && szLineBuf[iPos] == ']') //该行是一个段 + { + szLineBuf[iPos] = 0; //去掉"["和"]",便于比较 + lpszTmp = &szLineBuf[1]; + if( strcmp(lpszTmp, lpszSectionName) == 0 ) //指定的段找到了 + { + bSecFoundFlag = TRUE; + break; + } + } + } + + //[情况一]:如果未找到指定段,则指定key肯定也不存在,因此即要新建section也要新建key, + // 这些内容就直接追加到文件尾部,同时约定在文件尾部新建一个段时,默认在前面 + // 追加换行符号以确保和前面的其它内容不在一行 + if( !bSecFoundFlag ) + { + char szNewSection[2048]; + memset(szNewSection, 0, 2048); + + //生成新的段字符串 + sprintf(szNewSection, "%s[%s]%s%s = %s%s", szLineEndStr, lpszSectionName, szLineEndStr, lpszKeyName, lpszString, szLineEndStr); + + fseek(IniFile, 0, SEEK_END); + fwrite(szNewSection, sizeof(char), strlen(szNewSection), IniFile); + + goto func_end; + } + + //找到指定段后,再继续找指定key + while(!feof(IniFile)) + { + lPrePos = lCurPos; //保留上次文件指针位置 + + ReadLineFromFile(IniFile, szLineBuf, MAX_LINE_BUF_LENGTH); //读取一行 + + lCurPos = ftell(IniFile); //保留当前文件指针位置 + + StrTrimAll(szLineBuf); + if( szLineBuf[0] == ';' || szLineBuf[0] == 0 ) continue; //注释行和空行不处理 + + //将一行尾部可能存在的";"注释部分剔除(这样key=value的value中不能含有;否则将被当成注释而删除 + lpszTmp = strchr(szLineBuf, ';'); + if(lpszTmp != NULL) *lpszTmp = 0; + + StrTrimAll(szLineBuf); //zl 2002.9.19 ";"和有用内容间必有空格或TAB字符,必须删除这些分割字符 + + iPos = strlen(szLineBuf)-1; + + if(szLineBuf[0] == '[' && szLineBuf[iPos] == ']') + { + bMeetAnotherBlock = TRUE; //又到了一个段,说明指定段下的指定key没有找到 + break; + } + + lpszTmp = strchr(szLineBuf, '='); //定位'=' + if(lpszTmp == NULL) continue; //不含等号的非段行被视为无效行 + + *lpszTmp = 0; //为便于操作,在'='位置将szLineBuf从中间截断, 将szLineBuf分成key和value两个部分 + StrTrimAll(szLineBuf); //此时szLineBuf是key + + /* 找到了指定key */ + + if(strcmp(szLineBuf, lpszKeyName) == 0) //该比较大小写敏感 + { + char szKeyValBlock[2048]; + memset(szKeyValBlock, 0, 2048); + + //重新组织key = value对,实现修改目的 + sprintf(szKeyValBlock, "%s = %s%s", szLineBuf, lpszString, szLineEndStr); + + //注意:这里和下面的段前插入内容不同,这里是要将原有的key=value对去掉, + //代之以新对,因此lPrePos和lCurPos之间的文件内容(即原有key=value对)不要, + //该操作是替换而不是插入 + + lpszRearBlock = new char[lEndPos-lCurPos+1]; + memset(lpszRearBlock, 0, lEndPos-lCurPos+1); + fread(lpszRearBlock, sizeof(char), lEndPos-lCurPos, IniFile); //从当前位置开始读其后面的文件内容(长度为lEndPos-lCurPos, 注意lEndPos是end结尾符号的位置,等于文件长度,比最大有效文件指针位置大1) + + lpszFrontBlock = new char[lPrePos+1]; + memset(lpszFrontBlock, 0, lPrePos+1); + fseek(IniFile, 0, SEEK_SET); + fread(lpszFrontBlock, sizeof(char), lPrePos, IniFile); //从头部开始读其后面的文件内容(长度为lPrePos,因为文件指针从0开始,lPrePos位置前的文件长度就是lPrePos) + + //先关闭文件再用可写方式打开以清空原有内容,最后依次写文件的各个部分,如要不关闭 + //打开文件而是直接清空文件内容,因unix和windows中设置文件长度的调用不同,比较麻烦 + fclose(IniFile); + + IniFile = fopen(lpszFileName, "wb"); //可写方式打开(如文件已存在,其所有内容被清空) + if(!IniFile) return FALSE; + + fwrite(lpszFrontBlock, sizeof(char), lPrePos, IniFile); + fwrite(szKeyValBlock, sizeof(char), strlen(szKeyValBlock), IniFile); + fwrite(lpszRearBlock, sizeof(char), lEndPos-lCurPos, IniFile); + + delete [] lpszFrontBlock; + delete [] lpszRearBlock; + + bKeyFoundFlag = TRUE; + break; + } + } + + //如果在指定段下未找到指定key,则要新建key=value对 + if( !bKeyFoundFlag ) + { + char szKeyBlock[2048]; + memset(szKeyBlock, 0, 2048); + + if(bMeetAnotherBlock) //遇到了另外一个段,此时要在该段前面插入新建的key=value对 + { + sprintf(szKeyBlock, "%s = %s%s", lpszKeyName, lpszString, szLineEndStr); + + //以下以lPrePos为界线将文件拆成两部分,和上面替换操作中lPrePos和lCurPos间内容 + //不要不同,这里是插入而不是替换, 因此直接以lPrePos为界将文件分开,进行插入操作 + + fseek(IniFile, lPrePos, SEEK_SET); //定位到lPrePos(这里lPrePos是另一个段的开始字符,如"[") + + lpszRearBlock = new char[lEndPos-lPrePos+1]; + memset(lpszRearBlock, 0, lEndPos-lPrePos+1); + fread(lpszRearBlock, sizeof(char), lEndPos-lPrePos, IniFile); //从当前位置开始读其后面的文件内容(长度为lEndPos-lPrePos) + + lpszFrontBlock = new char[lPrePos+1]; + memset(lpszFrontBlock, 0, lPrePos+1); + fseek(IniFile, 0, SEEK_SET); + fread(lpszFrontBlock, sizeof(char), lPrePos, IniFile); //从头部开始读其后面的文件内容(长度为lPrePos) + + //先关闭文件再用可写方式打开以清空原有内容,最后依次写文件的各个部分,如要不关闭 + //打开文件而是直接清空文件内容,因unix和windows中设置文件长度的调用不同,比较麻烦 + fclose(IniFile); + + IniFile = fopen(lpszFileName, "wb"); //可写方式打开(如文件已存在,其所有内容被清空) + if(!IniFile) return FALSE; + + fwrite(lpszFrontBlock, sizeof(char), lPrePos, IniFile); + fwrite(szKeyBlock, sizeof(char), strlen(szKeyBlock), IniFile); + fwrite(lpszRearBlock, sizeof(char), lEndPos-lPrePos, IniFile); + + delete [] lpszFrontBlock; + delete [] lpszRearBlock; + + } + else //如果连一个段都没有碰到,则肯定已到了文件尾部, 追加key=value块到尾部即可 + { + fseek(IniFile, 0, SEEK_END); + + /* 如当前位置前已有换行符号则无需另行增加,此举可防止新增部分和上面一行连在一起 */ + if( IfBeforeHasRet(IniFile) ) + sprintf(szKeyBlock, "%s = %s%s", lpszKeyName, lpszString, szLineEndStr); + else + sprintf(szKeyBlock, "%s%s = %s%s", szLineEndStr, lpszKeyName, lpszString, szLineEndStr); + + fwrite(szKeyBlock, sizeof(char), strlen(szKeyBlock), IniFile); + } + } + +func_end: + fclose(IniFile); + + return true; +} + +//辅助函数,判断文件中当前指针位置前面是否有换行符号,使用该函数前必须确保文件已经打开并将文件指针定位到应有的位置 +bool IfBeforeHasRet(FILE* pFile) +{ + char szTmp[3]; + bool bBeforeHasRet = FALSE; + i_32 lOldPos; + + memset(szTmp, 0, 3); + + lOldPos = ftell(pFile); //保存文件当前指针位置 + + /* 读当前位置前面的两个字节, 因为windows下是回车换行两个字节 */ + fseek(pFile, -2, SEEK_CUR); + fread(szTmp, sizeof(char), 2, pFile); + + #ifdef OS_UNIX + if( szTmp[1] == 0x0a ) bBeforeHasRet = TRUE; + #else + if( szTmp[0] == 0x0d && szTmp[1] == 0x0a ) bBeforeHasRet = TRUE; + #endif + + fseek(pFile, lOldPos, SEEK_SET); //恢复原先的文件指针位置 + + return bBeforeHasRet; + +} + +/*-----------------------------------工具函数----------------------------------*/ + +//从指定文件中读取一行 +int ReadLineFromFile(FILE* IniFile, char* lpszLineBuf, int iLen) +{ + int iPos; + + /*----------------------------------------------------------------------------- + + 注意:如果文件以t即text方式打开,则回车换行两个字符在input时被当作一个字符处理, + 因此fgets()得到的一行字符串尾部只有一个换行符而没有回车符,而如果是binary + 方式打开则一行字符尾部同时有回车换行两个字符,打开方式的不同直接影响fgets + 读入一行后删除行尾部控制字符的操作,如果是text方式,只要删除换行符号即可, + 如果是binary方式,则要删掉两个控制字符。以下对两个控制字符是否存在都进行 + 判断,可以同时适应text和binary两种模式,也就能同时适应Windows下和Unix两种 + 不同格式的文本文件(unix文本文件行末只有一个换行符,即0A,没有回车符) + + 后续记录: fopen()中打开模式里的"t"是微软自己定义的,Ansi C 只支持 "b"模式 + + ----------------------------------------------------------------------------*/ + + if(fgets(lpszLineBuf, iLen, IniFile) != NULL) //fgets()函数遇到第一个换行符(0x0A)后结束(包括换行符),然后在尾部追加一个NULL后返回,因此换行符总是倒数第二个字符 + { + iPos = strlen(lpszLineBuf) - 1; + + if( lpszLineBuf[iPos-1] == 0x0D ) lpszLineBuf[iPos-1] = 0; //删除尾部可能存在的回车符(0x0D) + if( lpszLineBuf[iPos] == 0x0A ) lpszLineBuf[iPos] = 0; //删除尾部可能存在的换行符(0x0A) + } + else + return -1; + + return 0; //0表示正确 +} + +/*---------------------------------------------------------------------------- + +//从指定字符串中读取一行 +int ReadLineFromString(char* lpszText, char* lpszLineBuf, int iLen) +{ + int iPos; + + if(fgets(lpszLineBuf, iLen, IniFile) != NULL) //fgets()函数遇到第一个换行符(0x0A)后结束(包括换行符),然后在尾部追加一个NULL后返回,因此换行符总是倒数第二个字符 + { + iPos = strlen(lpszLineBuf) - 1; + + if( lpszLineBuf[iPos-1] == 0x0D ) lpszLineBuf[iPos-1] = 0; //删除尾部可能存在的回车符(0x0D) + if( lpszLineBuf[iPos] == 0x0A ) lpszLineBuf[iPos] = 0; //删除尾部可能存在的换行符(0x0A) + } + else + return -1; + + + return 0; //0表示正确 +} + +---------------------------------------------------------------------------*/ + +//删除字符串的左侧空格, 2002.9.19增加删除TAB字符(ASC码为9)功能 +void StrTrimLeft(char* szBuf) +{ + char *szBak = NULL; + char *p = szBuf; + + if(!szBuf) return; + + while(*p == ' ' || *p == 9) { p++; } + //qDebug("StrtrimLeft:p=%s",p); + if(p != szBuf) //头部有空格或TAB字符 + { + szBak = _strdup(p); //strcpy()中如source和dest重合(overlap),则copy结果不可预料,故另设一个缓冲区临时存放这个头部没有空格的字符串 + strcpy(szBuf, szBak); //strcpy()肯定不会溢出,因p是szBuf的一个子集,同时strcpy会拷贝结尾的null,因此无须人工截断szBuf + free(szBak); + } + +} + +//删除字符串的右侧空格, 2002.9.19增加删除TAB字符(ASC码为9)功能 +void StrTrimRight(char* szBuf) +{ + char *szBak = NULL; + int iPos = strlen(szBuf)-1; //最后一个非NULL字符的下标 + + if(!szBuf) return; + + char *p = &szBuf[iPos]; + + while(*p == ' ' || *p == 9) { p--; } + + if(p != &szBuf[iPos]) //尾部有空格 + { + p++; + *p = 0; //直接尾部截断,比删除头部空格还简单 + } +} + +//删除左右两边所有空格 +void StrTrimAll(char* szBuf) +{ + StrTrimRight(szBuf); + StrTrimLeft(szBuf); +} + +//获取指定文件的长度 +i_32 GetFileSize(char* lpszFileName) +{ + FILE* pFile; + + pFile = fopen(lpszFileName, "rb"); //二进制方式 + if(pFile == NULL) return -1; + + fseek(pFile, 0, SEEK_END); //定位到文件尾部 + i_32 lFileSize = ftell(pFile); //获取文件指针当前位置(此时文件指针指向EOF结束标志)[文件指针是从0开始计数的] + + fclose(pFile); + + return lFileSize; +} + diff --git a/Profile_Hash.cpp b/Profile_Hash.cpp new file mode 100644 index 0000000..e0ec191 --- /dev/null +++ b/Profile_Hash.cpp @@ -0,0 +1,1869 @@ +/***************************************************************************** + * + * Copyright (C) 1999-2001 SCADA Technology Control Co., Ltd. All rights reserved. + * + * 配置文件处理与哈希索引处理的有关的头文件 + * + * m.j.y 2001/12/07 + * + * + * + * $Name: $ + * + * $Revision: 1.2 $ + * + * $Date: 2006/08/04 03:37:33 $ + * + * $State: Exp $ + * + * $Log: Profile_Hash.cpp,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.1.2.1 2006/07/28 07:54:02 zhuzhenhua + * no message + * + * Revision 1.5 2003/07/14 02:22:38 scada + * 使用def文件导出函数,而不是使用SCADA_API. + * + * Revision 1.4 2003/01/02 03:14:50 scada + * trim substitution line + * + * Revision 1.3 2002/12/04 07:47:09 scada + * for NT + * + * Revision 1.2 2002/09/24 05:58:34 harold + * take acount __OS_SOLARIS__ where __OS__ occur, set errno to 0 before use it + * + * Revision 1.1.1.1 2002/08/21 07:16:39 harold + * temporarily import + * + * Revision 1.21 2002/06/03 10:06:27 mhorse + * 更改了AddNode函数 + * + * Revision 1.20 2002/03/20 03:40:21 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 13:43:21 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 08:17:11 harold + * no message + * + * Revision 1.19 2002/03/06 01:27:52 harold + * *** empty log message *** + * + * Revision 1.18 2002/02/25 07:30:21 harold + * no message + * + * Revision 1.17 2002/01/25 09:11:19 harold + * no message + * + * Revision 1.16 2002/01/23 02:38:06 harold + * test_function + * + * Revision 1.15 2002/01/22 08:51:42 harold + * modify2002-01-22-16:46 + * + * Revision 1.14 2002/01/21 06:15:49 harold + * 修改了函数返回值及参数 + * + * Revision 1.13 2002/01/21 05:55:25 mhorse + * 修改了函数返回值及参数 + * + * Revision 1.11 2002/01/18 12:57:15 harold + * revise errno + * + * Revision 1.10 1997/03/29 12:48:33 harold + * revise bug in read/write/listsec function + * + * Revision 1.9 2002/01/18 01:09:33 harold + * revise bugs in write/close/listsec function + * + * Revision 1.8 2002/01/09 11:37:11 harold + * no message + * + * + * Revision 1.2 2001/12/19 02:19:22 mhorse + * 第2次修改 + * + * Revision 1.1.1.1 2001/12/18 06:42:11 mhorse + * 马健莹第一次把配置文件读写库模块加入CVS(2001/12/18) + * + * + ******************************************************************************/ + +#include +#include +#include +#include +#ifdef OS_WINDOWS +#include +#include +#include +#else +//#include +#include +//#include +// #include +#include +#endif +#include "Profile_Hash.h" +#include "confrw_errno.h" +//#include "util.h" + + +//定义句柄记录数组 +static SProfileHanleInfo g_pHandleIndex[MAX_PROFILEHANDLE_NUM]; + +//句柄记录数组是否经过初始化 PGCTRUE-已经被初始化 +static PGCBOOL g_bHandleInit = PGCFALSE; + +//定义行注释符 +#define MARK_pgcchar_NUM 2 +static pgcchar gs_szMarkpgcchar[MARK_pgcchar_NUM] = {';', '#'}; + +//行结尾字符为\n,不包括\r +//#define LINE_EXCLUDE_0A + + +// 函数名 : UpperCase +// 函数说明 : 将小写转为大写 +// 返回值说明 : pgcchar -- 转换后的字符 +// 参数说明 : cCh -- 源字符 +pgcchar* UpperCase(pgcchar *szSource) +{ + pgcchar* pcTemp = szSource, *pcFirst = szSource; + + if (pcTemp == NULL) + return NULL; + + while (*pcTemp != '\0') + { + if ((*pcTemp >= 'a') && (*pcTemp <= 'z')) + *pcTemp = (pgcchar)(*pcTemp - ('a' - 'A')) ; + pcTemp++; + } + + return pcFirst; +} + + +/* +* 哈希函数 +*/ +// 给出关键字, 求同义词序号 +static u32 fnhash_index_of(const void * pKey, u32 hash_size); + +// 求关键字 +static void * fnhash_key_of(const SItemInCache * pindex); + +// 比较关键字 +static int fnhash_compare(const void * pKey1, const void * pKey2); + + + +/* +* 根据已知的历史数据库索引数组, 为其建立一个哈希表. +* +* 参数 +* pindex -- 索引数组的指针 +* count -- pindex索引数组中索引的个数, pindex[0] -- pindex[count - 1]为 +* 索引 +* pphash_of_index -- 将pindex所指向的数组哈希化, 这样, 在随后的索引搜索 +* 时, 使用该哈希索引. +* +* 返回值 +* SUCCESS -- 成功 +* 其它 -- 失败代码 +* +*/ +#define INDEX_HASH_TABLE_SIZE_FACTOR 20 +pgc32 profile_build_hash_index ( SItemInCache * pindex, + pgc32 count, + TChainHash ** pphash_of_index ) +{ + pgc32 i = 0; + TChainHash * phash_table = NULL; + + phash_table = new TChainHash(count * INDEX_HASH_TABLE_SIZE_FACTOR, + fnhash_index_of, + fnhash_key_of, + fnhash_compare, + NULL/*fnhash_create_item*/, + NULL/*fnhash_free_item*/, + NULL/*fnhash_copy_item*/, + NULL/*fnhash_alloc*/, + NULL/*fnhash_dealloc*/); + if (phash_table == NULL) + return ERROR_MEMORY_ALLOC; + + for(i = 0; i < count; i++) + phash_table->insertItem(pindex + i); + + *pphash_of_index = phash_table; + + return SUCCESS; +} + + + +/* +* 在索引区中搜索 +* +* 参数 +* pindex_base -- 被哈希化的索引数组的指针 +* phash_of_index -- 索引数组的哈希表 +* szSecName -- 被查询的段名 +* szItemName - 被查询的项目名 +* +* 返回值 +* 索引在索引数组中的序号 -- 成功的查找到指定的配置项目的索引 +* -1 -- 失败 +*/ +pgc32 profile_search_sequence ( SItemInCache **pindex_base, + TChainHash *phash_of_index, + const pgcchar *szSecName, + const pgcchar *szItemName) +{ + SItemInCache *p = NULL, index; + + memset(&index, 0, sizeof(SItemInCache)); + if (szSecName != NULL) + { + //以下执行大小写转换 +#ifdef OS_WINDOWS + lstrcpyn(index.szSecName, szSecName, MAX_CHAR_LINE); + // strupr(index.szSecName); +#else + strncpy(index.szSecName, szSecName, MAX_CHAR_LINE - 1); + // UpperCase(index.szSecName); +#endif + } + if (szItemName != NULL) + { +#ifdef OS_WINDOWS + lstrcpyn(index.szItemName, szItemName, MAX_CHAR_LINE); + // strupr(index.szItemName); +#else + strncpy(index.szItemName, szItemName, MAX_CHAR_LINE - 1); + // UpperCase(index.szItemName); +#endif + } + p = phash_of_index->searchItem((void *)&index); + if(NULL == p) + return -1; + *pindex_base = p; + return 0; +} + + + + +/* +* 哈希函数 +*/ +// 给出关键字, 求同义词序号 +static u32 fnhash_index_of(const void * pKey, u32 hash_size) +{ + long index = 0; + u_char *pbString = NULL; + int iX = 0, iY = 0, i = 0; + + SItemInCache * pindex = (SItemInCache *)pKey, sindex; + + memcpy(&sindex, pindex, sizeof(SItemInCache)); + //以下执行大小写转换 +#ifdef OS_WINDOWS + strupr(sindex.szSecName); + strupr(sindex.szItemName); +#else + UpperCase(sindex.szSecName); + UpperCase(sindex.szItemName); +#endif + + //哈希转换 + pbString = (u_char*)sindex.szSecName; + for (i = 0; i < MAX_CHAR_LINE; i++) + { + iX = iX + pbString[i]; + } + iX = iX % MAX_SEC_NUM; + + pbString = (u_char*)sindex.szItemName; + for ( i = 0; i < MAX_CHAR_LINE; i++) + { + iY = iY + pbString[i]; + } + iY = iY % MAX_ITEM_NUM; + + index = iX * MAX_ITEM_NUM + iY; + + return (u32)(index % hash_size); +} + + + +// 求关键字 +static void * fnhash_key_of(const SItemInCache * pindex) +{ + return (void *)(pindex); +} + + + +// 比较关键字 +static int fnhash_compare(const void * pKey1, const void * pKey2) +{ + SItemInCache * pindex1 = (SItemInCache *)pKey1; + SItemInCache * pindex2 = (SItemInCache *)pKey2; + + if (pKey1 == NULL) + return 1; +//#ifdef OS_WINDOWS + if (pKey2 == NULL) + { + if (_stricmp(pindex1->szSecName, pindex2->szSecName) == 0) + return 0; + else + return 1; + } + else + { + if ((_stricmp(pindex1->szSecName, pindex2->szSecName) == 0) + && (_stricmp(pindex1->szItemName, pindex2->szItemName) == 0)) + return 0; + else + return 1; + } +/*#else + if (pKey2 == NULL) + { + + if (strcasecmp(pindex1->szSecName, pindex2->szSecName) == 0) + return 0; + else + return 1; + } + else + { + if ((strcasecmp(pindex1->szSecName, pindex2->szSecName) == 0) + && (strcasecmp(pindex1->szItemName, pindex2->szItemName) == 0)) + return 0; + else + return 1; + } +#endif*/ +} + + + + +//判断某行是否被注释 +PGCBOOL LineIsMark(pgcchar *szLine) +{ + for (pgc32 i = 0; i < MARK_pgcchar_NUM; i++) + if (*szLine == gs_szMarkpgcchar[i]) + return PGCTRUE; + return PGCFALSE; +} + + +//寻找段尾 +pgcchar* FindSecTail(pgcchar *szString) +{ + pgcchar *szStart = NULL, *szTemp = NULL; + + if ((szStart = strchr(szString, '\n')) == NULL) + { + return NULL; + } + + while (szStart != NULL) + { + szStart = strchr(szStart, '['); + if ((szStart != NULL) && (*(szStart - 1) == '\n')) + break; + if (szStart != NULL) szStart++; + } + + if (szStart != NULL) + { + szTemp = szStart; + while ((*szTemp != '\n') && (*szTemp != '\0')) + { + if (*szTemp == ']') + return szStart; + szTemp ++; + } + } + + return NULL; +} + + +//提取段名 +PGCBOOL DigSecName(const pgcchar *szString, pgcchar *szRevBuffer, pgc32 iBufferLength) +{ + pgcchar *szStart = NULL, *szTemp = NULL; + PGCBOOL bSecNameExist = PGCFALSE; + pgc32 iLength = iBufferLength - 1; + + if ((szStart = (pgcchar *)strchr((const char*)szString, '[')) != NULL) + { + szTemp = szStart; + while ((*szTemp != '\n') && (*szTemp != '\0')) + { + if (*szTemp == ']') + { + bSecNameExist = PGCTRUE; + break; + } + szTemp ++; + } + + if (bSecNameExist) + { + iLength = (pgc32)(szTemp - szStart) - 1; + if (iLength >= iBufferLength) + iLength = iBufferLength - 1; + for (pgc32 i = 0; i < iLength; i++) + szRevBuffer[i] = *(szStart + 1 + i); + szRevBuffer[iLength] = '\0'; + /* + #ifndef __unix__ + strupr(szRevBuffer); + #else + UpperCase(szRevBuffer); + #endif + */ + return PGCTRUE; + } + } + return PGCFALSE; +} + + +//提取项目名及项目值 +PGCBOOL DigItemContent( pgcchar *szString, pgcchar *szItemName, pgcchar *szItemVal, pgc32 iBufferLength) +{ + pgcchar *pcBeval = NULL, *pcTemp = NULL, szTemp[MAX_CHAR_LINE]; + pgc32 iCount = 0, i = 0; + + + if ((pcBeval = strchr(szString, '=')) == NULL) + return PGCFALSE; + + //获取项目名 + pcTemp = szString; + while ((pcTemp < pcBeval) && (iCount < (MAX_CHAR_LINE - 1))) + { + szTemp[iCount] = *pcTemp; + pcTemp++; + iCount++; + } + szTemp[iCount] = '\0'; + + //删除前面多余空格 + for ( i = 0; i < MAX_CHAR_LINE; i++) + { + if (szTemp[i] != ' ') + { + for (pgc32 j = i; j < MAX_CHAR_LINE; j++) + { + szTemp[j - i] = szTemp[j]; + }// end for + break; + }// end if + }// end for + + //删除后面多余空格 + for (i = iCount - 1; i >= 0; i--) + { + if (szTemp[i] != ' ') + break; + szTemp[i] = '\0'; + }// end for +/*#ifndef __unix__ + strupr(szTemp); +#else + UpperCase(szTemp); +#endif*/ + strcpy(szItemName, szTemp); + + //获取项目值 + memset(szTemp, 0, MAX_CHAR_LINE); +#ifdef OS_WINDOWS + lstrcpyn(szTemp, pcBeval + 1, MAX_CHAR_LINE); +#else + strncpy(szTemp ,pcBeval + 1, MAX_CHAR_LINE - 1); +#endif + //删除前面多余空格 + for (i = 0; i < MAX_CHAR_LINE; i++) + { + if (szTemp[i] != ' ') + { + for (pgc32 j = i; j < MAX_CHAR_LINE; j++) + { + szTemp[j - i] = szTemp[j]; + }// end for + break; + }// end if + }// end for + + //删除后面多余空格 + for ( i = (pgc32)strlen(szTemp) - 1 ; i >= 0; i--) + { + if (szTemp[i] != ' ') + break; + szTemp[i] = '\0'; + }// end for + strcpy(szItemVal, szTemp); + + return PGCTRUE; +} + + +// 函数名 : InsertNode +// 函数说明 : 在指定的段添加新项目 +// 返回值说明 : PGCBOOL -- +// 参数说明 : psHead -- +// 参数说明 : iPos -- +// 参数说明 : psCacheEntry -- +// 参数说明 : iSecPos -- +PGCBOOL InsertNode(SItemSequence * &psHead, pgc32 iPos, SItemInCache *psCacheEntry, pgc32 iSecPos) +{ + SItemSequence *psTemp = NULL, *psNewNode = NULL, *psPrior = NULL; + + if ((psHead == NULL) || (psCacheEntry == NULL)) + return PGCFALSE; + psNewNode = new SItemSequence[1]; + psNewNode->iPos = iPos; + psNewNode->NextNode = NULL; + + psTemp = psHead; + while (psTemp != NULL) + { + if (psTemp->iPos == iSecPos) + break; + psTemp = psTemp->NextNode; + } + while (psTemp != NULL) + { + psPrior = psTemp; + psTemp = psTemp->NextNode; + if ((psTemp == NULL) || psCacheEntry[psTemp->iPos].bIsSecName) + { + psPrior->NextNode = psNewNode; + psNewNode->NextNode = psTemp; + return PGCTRUE; + } + } + delete []psNewNode; + return PGCFALSE; +} + + + +// 函数名 : DisableSec +// 函数说明 : 使指定的段及其下属的各个项目无效 +// 返回值说明 : PGCBOOL -- +// 参数说明 : psHead -- +// 参数说明 : iSecPos -- +// 参数说明 : psCacheEntry -- +PGCBOOL DisableSec(SItemSequence * &psHead, pgc32 iSecPos, SItemInCache *psCacheEntry) +{ + SItemSequence *psTemp = NULL; + + if (psHead == NULL) + return PGCFALSE; + + psTemp = psHead; + while (psTemp != NULL) + { + if (psTemp->iPos == iSecPos) + break; + psTemp = psTemp->NextNode; + } + while (psTemp != NULL) + { + psCacheEntry[psTemp->iPos].valid = PGCFALSE; + psTemp = psTemp->NextNode; + if ((psTemp == NULL) || (psCacheEntry[psTemp->iPos].bIsSecName)) + { + return PGCTRUE; + } + } + return PGCFALSE; +} + + + +//添加一个节点到顺序链表尾部 +PGCBOOL AddNode(SItemSequence * &psHead, SItemSequence * &pCurSeq, pgc32 iPos) +{ + SItemSequence *psNewNode = NULL; + + psNewNode = new SItemSequence[1]; + psNewNode->iPos = iPos; + psNewNode->NextNode = NULL; + + if (psHead == NULL) + { + psHead = psNewNode; + pCurSeq = psHead; + } + else + { + if (pCurSeq) + { + pCurSeq->NextNode = psNewNode; + pCurSeq = psNewNode; + } + } + + return PGCTRUE; +} + + +void ReleaseProfileCache(HPROFILE hProfile) +{ + FILE *fstream = NULL; + TChainHash *pHashTable = NULL; + SItemSequence *pSequence = NULL, *psPrior = NULL; + SItemInCache *psCacheEntry = NULL; + SMemoChain *psMemo = NULL, *psMemoPrior = NULL; + pgc32 iCurItemCount = 0; + + fstream = g_pHandleIndex[hProfile].fstream ; + if (fstream != NULL) + fclose(fstream); + + pHashTable = g_pHandleIndex[hProfile].pHashTable; + if (pHashTable != NULL) + delete pHashTable; + + pSequence = g_pHandleIndex[hProfile].pSequence; + //删除该链表的所有节点 + while (pSequence != NULL) + { + psPrior = pSequence; + pSequence = pSequence->NextNode; + delete []psPrior; + } + + + iCurItemCount = g_pHandleIndex[hProfile].CurUseItems; + psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry; + //首先释放注释节点 + if (psCacheEntry != NULL) + { + for (pgc32 i = 0; i < iCurItemCount; i++) + { + psMemo = psCacheEntry[i].memo; + while (psMemo != NULL) + { + psMemoPrior = psMemo; + psMemo = psMemo->NextNode; + delete []psMemoPrior->szMemo; + delete []psMemoPrior; + } + } + free(psCacheEntry); + } + + return; +} + + +//调整缓冲区大小 +pgcu32 AdjustCache(HPROFILE hCacher, pgc32 iNewItem) +{ + pgc32 iOldSize = g_pHandleIndex[hCacher].CurItemCount, iNewSize = 0; + pgc32 iOldUse = g_pHandleIndex[hCacher].CurUseItems; + SItemInCache *pCacheEntry = NULL; + + if ((g_pHandleIndex[hCacher].CurUseItems + iNewItem ) >= iOldSize) + { + + iNewSize = iOldSize + RESIZE_ITEM_NUM; + pCacheEntry = (SItemInCache*)malloc(iNewSize * sizeof(SItemInCache)); + if (pCacheEntry == NULL) + return ERROR_MEMORY_ALLOC; + memset(pCacheEntry, 0, iNewSize * sizeof(SItemInCache)); + memmove(pCacheEntry, g_pHandleIndex[hCacher].pCacheEntry, iOldSize * sizeof(SItemInCache)); + free(g_pHandleIndex[hCacher].pCacheEntry); + g_pHandleIndex[hCacher].CurItemCount = iNewSize; + g_pHandleIndex[hCacher].pCacheEntry = pCacheEntry; + + //分离哈希表的所有数据项 + g_pHandleIndex[hCacher].pHashTable->detachItems(); + for (pgc32 i = 0; i < iOldUse; i++) + g_pHandleIndex[hCacher].pHashTable->insertItem(pCacheEntry + i); + return SUCCESS; + } + return ERROR_FAIL; +} + + + +// 函数名 : get_file_lastMTime +// 函数说明 : 获取文件上一次被修改的时间 +// 返回值说明 : void -- +// 参数说明 : pszfname -- +// 参数说明 : pt -- +pgc32 get_file_lastMTime(char * pszfname, timeval *pt) +{ + int ret = 0; + + struct stat buf; + + memset((void *)&buf, 0, sizeof(buf)); + + ret = stat(pszfname, &buf); + if(-1 == ret) + return ERROR_FAIL; + + pt->tv_sec = buf.st_mtime; + pt->tv_usec = 0; + return SUCCESS; +} + + + +//将缓冲的数据重新写成文件 +pgc32 ReWriteProfile(HPROFILE hProfile) +{ + pgc32 iSize = 0; + pgcchar *pcFileBuffer = NULL, *pcTemp = NULL; + pgcchar *pcHead = NULL; + PGCBOOL bSecExist = PGCFALSE; + SItemSequence * psSeq = g_pHandleIndex[hProfile].pSequence ; + SItemInCache *psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry, *psTemp = NULL; + SMemoChain *psMemo = NULL; + FILE *stream = /*g_pHandleIndex[hProfile].fstream*/0; + iSize = (g_pHandleIndex[hProfile].CurLines + 2) * (MAX_CHAR_LINE + 2); + + if (( pcHead = (pgcchar*)malloc(iSize)) != NULL) + { + pcFileBuffer = pcHead; + memset(pcFileBuffer, 0, iSize); + while (psSeq != NULL) + { + psTemp = psCacheEntry + psSeq->iPos; + if (psTemp->valid) + { + //有注释吗? + psMemo = psTemp->memo; + while (psMemo != NULL) + { + //写一行注释 + pcTemp = psMemo->szMemo; + while (*pcTemp != '\0') + { + *pcFileBuffer = *pcTemp; + pcFileBuffer++; + pcTemp++; + } +#ifdef LINE_EXCLUDE_0A + *pcFileBuffer = '\n'; + pcFileBuffer += 1; +#else + *pcFileBuffer = '\r'; + *(pcFileBuffer + 1) = '\n'; + pcFileBuffer += 2; +#endif + psMemo = psMemo->NextNode; + } + + //是段吗? + if (psTemp->bIsSecName) + { + if (bSecExist) + { +#ifdef LINE_EXCLUDE_0A + *pcFileBuffer = '\n'; + pcFileBuffer += 1; +#else + *pcFileBuffer = '\r'; + *(pcFileBuffer + 1) = '\n'; + pcFileBuffer += 2; +#endif + } + else + bSecExist = PGCTRUE; + + *pcFileBuffer = '['; + pcFileBuffer++; + pcTemp = psTemp->szSecName; + while (*pcTemp != '\0') + { + *pcFileBuffer = *pcTemp; + pcFileBuffer++; + pcTemp++; + } + *pcFileBuffer = ']'; +#ifdef LINE_EXCLUDE_0A + *(pcFileBuffer + 1) = '\n'; + pcFileBuffer += 2; +#else + *(pcFileBuffer + 1) = '\r'; + *(pcFileBuffer + 2) = '\n'; + pcFileBuffer += 3; +#endif + + } + else + { + pcTemp = psTemp->szItemName; + while (*pcTemp != '\0') + { + *pcFileBuffer = *pcTemp; + pcFileBuffer++; + pcTemp++; + } + *pcFileBuffer = '='; + pcFileBuffer++; + pcTemp = psTemp->szItemVal; + while (*pcTemp != '\0') + { + *pcFileBuffer = *pcTemp; + pcFileBuffer++; + pcTemp++; + } +#ifdef LINE_EXCLUDE_0A + *pcFileBuffer = '\n'; + pcFileBuffer += 1; +#else + *pcFileBuffer = '\r'; + *(pcFileBuffer + 1) = '\n'; + pcFileBuffer += 2; +#endif + }// end else + }// end if "valid" + psSeq = psSeq->NextNode; + }// end while + + //2002/03/05 杨小波++++++++++++++++++++++++++++++++++++++++++++ +#if 0 + pgcu32 numwritten = (pgcu32)pcFileBuffer - (pgcu32)pcHead ; +#endif + pgcu32 numwritten = (pgcu32)(pcFileBuffer - pcHead) ; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +#ifdef OS_WINDOWS + //windows下打开文件 + /*if ((stream = fopen(g_pHandleIndex[hProfile].szPathName, "w+b")) == NULL) + { + free(pcHead); + return ERROR_FOPEN; + }*/ +#else + //unix下打开文件 + /*PGCBOOL bOpenOK = PGCFALSE; + do + { + errno = 0; + if ((stream = fopen(g_pHandleIndex[hProfile].szPathName, "w+b")) != NULL) + { + bOpenOK = PGCTRUE; + break; + } + } + while (errno == EINTR); + + if (!bOpenOK) + { + free(pcHead); + return ERROR_FOPEN; + }*/ + //ghConfig = DSOpenFile("g_pHandleIndex[hProfile].szPathName"); + +#endif + + fseek(stream, 0, SEEK_SET); + //函数fwrite在写数据到文件时,如遇字符NULL,会产生错误,从而使文件无法定位结尾 + pgc32 numwritted = (pgc32)fwrite(pcHead, sizeof( pgcchar ), numwritten , stream ); + free(pcHead); + fclose(stream); + //记录下修改文件的时间 + get_file_lastMTime(g_pHandleIndex[hProfile].szPathName, &g_pHandleIndex[hProfile].tLastModify); + if (numwritted != numwritten) + { + return ERROR_FWRITE; + } + return SUCCESS; + + }// end if + return ERROR_FAIL; +} + + +int timeval_compare(timeval * ptv1, timeval * ptv2) +{ + int del_sec = ptv1->tv_sec - ptv2->tv_sec; + int del_usec = ptv1->tv_usec - ptv2->tv_usec; + + return (del_sec != 0) ? del_sec : del_usec; +} + + +// 函数名 : ReCreateCache +// 函数说明 : 当有当前进程以外的进程修改配置文件后,需要调用此函数重建配置文件缓冲 +// 返回值说明 : void -- +// 参数说明 : hProfile -- +void ReCreateCache(HPROFILE hProfile) +{ + timeval tLastModify, *ptRecModify = NULL; + pgcchar *szProfileName = g_pHandleIndex[hProfile].szPathName; + ptRecModify = &g_pHandleIndex[hProfile].tLastModify; + if (szProfileName == 0) + return; + + if (get_file_lastMTime(szProfileName, &tLastModify) == SUCCESS) + { + if (timeval_compare(&tLastModify, ptRecModify) > 0) + { + ReleaseProfileCache(hProfile); + ProcessCreateCache(hProfile); + } + } + return; +} + + +pgc32 ProcessCreateCache(HPROFILE hProfile) +{ + pgcchar *pcFileBuffer = NULL, *pcTemp = NULL, *pcStart = NULL, *pcEnd = NULL; + pgcchar *pcNextLine = NULL, *pcTemp1 = NULL ; + pgcchar szSecName[MAX_CHAR_LINE], CurItemName[MAX_CHAR_LINE], CurItemVal[MAX_CHAR_LINE]; + SItemInCache *psTemp = NULL; + SMemoChain *psMemoTep = NULL, *psMemo = NULL; + TChainHash * phash_table = NULL; + PGCBOOL bSecNameExist = PGCFALSE; + FILE *fstream = NULL; + long lFileLength = 0; + SItemInCache *psCacheEntry = NULL, *psCacheTep = NULL; + pgc32 iCount = 0, iPos = 0, iCurSec = 0, iCurItem = 0, iCurItemCount = 0; + //iCurLineType:当前行类型 0-不能确定 ;1-注释行; 2-段名 ;3-项目内容,4-空行 + pgc32 iCurLineType = 0, iLines = 0, i = 0; + pgcchar szProfileName[MAX_PATH_NUM]; + + memset(szProfileName, 0, MAX_PATH_NUM); + //保存文件全路径名 +//#ifdef OS_WINDOWS + lstrcpyn((LPWSTR)szProfileName, (LPWSTR)g_pHandleIndex[hProfile].szPathName, MAX_PATH_NUM); +/*#else + strncpy(szProfileName, g_pHandleIndex[hProfile].szPathName, MAX_PATH_NUM - 1); +#endif*/ + + memset(&g_pHandleIndex[hProfile], 0, sizeof(SProfileHanleInfo)); +//#ifdef OS_WINDOWS + //windows下打开文件 + if ((fstream = fopen(szProfileName, "r+b")) == NULL) + { + return ERROR_FOPEN; + } +/*#else + //unix下打开文件 + PGCBOOL bOpenOK = PGCFALSE; + do + { + errno = 0; + if ((fstream = fopen(szProfileName, "r+b")) != NULL) + { + bOpenOK = PGCTRUE; + break; + } + } + while (errno == EINTR); + + if (!bOpenOK) + return ERROR_FOPEN; +#endif*/ + + if (fseek(fstream, 0, SEEK_END) != 0) + { + fclose(fstream); + return 0; + } + + //获取文件长度 + lFileLength = ftell(fstream); + pcTemp = new pgcchar[lFileLength + 1]; + if (pcTemp == NULL) + { + fclose(fstream); + return 0; + } + memset(pcTemp, 0, lFileLength + 1); + if (fseek(fstream, 0, SEEK_SET) != 0) + { + fclose(fstream); + return 0; + } + //将文件读入缓冲 + if ((iCount = (pgc32)fread(pcTemp, sizeof( pgcchar ), lFileLength, fstream)) != lFileLength) + { + fclose(fstream); + return ERROR_FREAD; + } + + + + //格式化流(去除每一行前面的多余空格) + pcStart = pcTemp; + pcEnd = pcTemp + iCount; + while ((pcStart != NULL) && (pcStart < pcEnd)) + { + if (*pcStart == ' ') + { + *pcStart = 0; + pcStart ++; + } + else + { + if (*pcStart == '\n') + pcStart ++; + else + { + if ((pcStart = strchr(pcStart, '\n')) == NULL) break; + pcStart ++; + } + } + }// end while + + + + //格式化流(去除每一行结束标志"\r\n"中的"\r"标志,仅保留"\n"标志) + pcStart = pcTemp; + while ((pcStart != NULL) && (pcStart < pcEnd)) + { + if ((*pcStart == '\r') && (*(pcStart + 1) == '\n')) + { + *pcStart = 0; + pcStart +=2; + } + else + pcStart++; + }// end while + + + + //统计行数 + pcStart = pcTemp; + while ((pcStart != NULL) && (pcStart < pcEnd)) + { + if (*pcStart == '\n') + { + iLines++; + } + pcStart++; + }// end while + iLines++; + g_pHandleIndex[hProfile].CurLines = iLines; + + //重建文件缓冲 + pcFileBuffer = new pgcchar[iCount + 1]; + memset(pcFileBuffer, 0, iCount + 1); + for ( i = 0; i < iCount; i++) + { + if (pcTemp[i] != 0) + { + pcFileBuffer[iPos] = pcTemp[i]; + iPos++; + } + } + delete []pcTemp; + + + + //分配配置项缓冲 + psCacheEntry = (SItemInCache *)malloc(INITCACHE_ITEM_NUM * sizeof(SItemInCache)); + if (psCacheEntry == NULL) + { + if (pcFileBuffer != NULL) + delete []pcFileBuffer; + fclose(fstream); + return ERROR_MEMORY_ALLOC; + } + memset(psCacheEntry, 0, INITCACHE_ITEM_NUM * sizeof(SItemInCache)); + iCurItemCount = INITCACHE_ITEM_NUM; + g_pHandleIndex[hProfile].fstream = fstream; + g_pHandleIndex[hProfile].pHashTable = NULL; + g_pHandleIndex[hProfile].pSequence = NULL; + g_pHandleIndex[hProfile].pCurSeq = NULL; + g_pHandleIndex[hProfile].CurItemCount = iCurItemCount; + g_pHandleIndex[hProfile].pCacheEntry = psCacheEntry; + + //提取各段 + pcStart = pcFileBuffer; + pcEnd = NULL; + while ((pcStart != NULL) && (pcStart < (pcFileBuffer + iPos))) + { + //寻找段尾 + pcEnd = FindSecTail(pcStart + 1); + + if (pcEnd != NULL) + *(pcEnd - 1) = '\0'; + + //检查行类型 + while (pcStart != NULL) + { + //确定下一行的位置 + if ((pcNextLine = strchr(pcStart, '\n')) != NULL) + { + //如果为空行 + if (pcStart == pcNextLine) + iCurLineType = 4; + *pcNextLine = '\0'; + pcNextLine++; + } + + if (iCurLineType != 4) + { + //检查当前行是否为注释行 + if (LineIsMark(pcStart)) + { + iCurLineType = 1; + } + else + { + pcTemp = strchr(pcStart, '['); + pcTemp1 = strchr(pcStart, ']'); + //如果当前行是段名,则提取段名 + if ( pcTemp && pcTemp1 && (pcTemp1 > pcTemp)) + { + DigSecName(pcStart, szSecName, MAX_CHAR_LINE); + iCurLineType = 2; + } + else + { + pcTemp = strchr(pcStart, '='); + //如果当前行是项目记录,则提取项目名及项目值 + if (pcTemp != NULL) + { + DigItemContent(pcStart, CurItemName, CurItemVal, MAX_CHAR_LINE); + iCurLineType = 3; + } + else + iCurLineType = 0; + } + }// end else + } + + switch (iCurLineType) + { + //如果是注释行,或空行 + case 1: + case 4: + //将注释行添加入节点 + psMemoTep = psMemo; + if (psMemoTep != NULL) + { + while (psMemoTep->NextNode != NULL) + { + psMemoTep = psMemoTep->NextNode; + }// end while + psMemoTep->NextNode = new SMemoChain[1]; + if (iCurLineType == 1) + { + psMemoTep->NextNode->szMemo = new pgcchar[strlen(pcStart) + 1]; + strcpy(psMemoTep->NextNode->szMemo, pcStart); + } + else if (iCurLineType == 4) + { +#ifdef LINE_EXCLUDE_0A + psMemoTep->NextNode->szMemo = new pgcchar[2]; + psMemoTep->NextNode->szMemo[0] = '\0'; + psMemoTep->NextNode->szMemo[1] = '\0'; +#else + psMemoTep->NextNode->szMemo = new pgcchar[3]; + psMemoTep->NextNode->szMemo[0] = '\0'; + psMemoTep->NextNode->szMemo[1] = '\n'; + psMemoTep->NextNode->szMemo[2] = '\0'; +#endif + } + psMemoTep->NextNode->NextNode = NULL; + }// end if + else + { + psMemo = new SMemoChain[1]; + if (iCurLineType == 1) + { + psMemo->szMemo = new pgcchar[strlen(pcStart) + 1]; + strcpy(psMemo->szMemo, pcStart); + } + else if (iCurLineType == 4) + { +#ifdef LINE_EXCLUDE_0A + psMemo->szMemo = new pgcchar[2]; + psMemo->szMemo[0] = '\0'; + psMemo->szMemo[1] = '\0'; +#else + psMemo->szMemo = new pgcchar[3]; + psMemo->szMemo[0] = '\0'; + psMemo->szMemo[1] = '\n'; + psMemo->szMemo[2] = '\0'; +#endif + } + psMemo->NextNode = NULL; + }// end else + + break; + + //如果是段名 + case 2: + psTemp = &psCacheEntry[iCurItem]; + strcpy(psTemp->szSecName, szSecName); + psTemp->valid = PGCTRUE; + psTemp->bIsSecName = PGCTRUE; + psTemp->memo = psMemo; + + AddNode(g_pHandleIndex[hProfile].pSequence, g_pHandleIndex[hProfile].pCurSeq, iCurItem); + bSecNameExist = PGCTRUE; + iCurItem ++; + psMemo = NULL; + break; + //如果是项目赋值 + case 3: + if (bSecNameExist) + { + psTemp = &psCacheEntry[iCurItem]; + strcpy(psTemp->szSecName, szSecName); + strcpy(psTemp->szItemName, CurItemName); + strcpy(psTemp->szItemVal, CurItemVal); + psTemp->valid = PGCTRUE; + psTemp->bIsSecName = PGCFALSE; + psTemp->memo = psMemo; + + AddNode(g_pHandleIndex[hProfile].pSequence, g_pHandleIndex[hProfile].pCurSeq, iCurItem); + iCurItem ++; + psMemo = NULL; + }//end if + break; + //default: + }// end switch + + iCurLineType = 0; + + //如果原先的缓冲区太小,则递增缓冲区 + if (iCurItem >= iCurItemCount) + { + psCacheTep = (SItemInCache*)malloc((iCurItemCount + RESIZE_ITEM_NUM) * sizeof(SItemInCache)); + if (psCacheTep == NULL) + { + ReleaseProfileCache(hProfile); + return ERROR_MEMORY_ALLOC; + } + memset(psCacheTep, 0, (iCurItemCount + RESIZE_ITEM_NUM) * sizeof(SItemInCache)); + memmove(psCacheTep, psCacheEntry, sizeof(SItemInCache) * iCurItemCount); + free(psCacheEntry); + psCacheEntry = psCacheTep; + iCurItemCount = iCurItemCount + RESIZE_ITEM_NUM; + g_pHandleIndex[hProfile].CurItemCount = iCurItemCount; + g_pHandleIndex[hProfile].pCacheEntry = psCacheEntry; + }// end if + + pcStart = pcNextLine; + }// end while + bSecNameExist = PGCFALSE; + pcStart = pcEnd; + }// end while + + if (pcFileBuffer != NULL) + delete []pcFileBuffer; + + pgc32 iRev = -1; + + //创建哈希表 + iRev = profile_build_hash_index(psCacheEntry, iCurItem , &phash_table); + if (iRev != SUCCESS) + { + ReleaseProfileCache(hProfile); + return ERROR_CONF_CREATEHASH ; + } + + g_pHandleIndex[hProfile].pHashTable = phash_table; + g_pHandleIndex[hProfile].CurUseItems = iCurItem ; + g_pHandleIndex[hProfile].CurSecNum = iCurSec; + + fstream = g_pHandleIndex[hProfile].fstream; + g_pHandleIndex[hProfile].fstream = 0; + fclose(fstream); + //保存文件全路径名 +#ifdef OS_WINDOWS + lstrcpyn(g_pHandleIndex[hProfile].szPathName, szProfileName, MAX_PATH_NUM); +#else + strncpy(g_pHandleIndex[hProfile].szPathName, szProfileName, MAX_PATH_NUM - 1); +#endif + //记录下修改文件的时间 + get_file_lastMTime(szProfileName, &g_pHandleIndex[hProfile].tLastModify); + + return SUCCESS; +} + + + + + +//以下为应用接口 +//----------------------------------------------------------------------------------------- + +// 函数名 : create_profile_cache +// 函数说明 : 建立配置文件缓冲 +// 返回值说明 : HPROFILE -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 + +// 返回值 说明 +// SUCCESS 成功建立配置文件缓冲 +// ERROR_CONF_NOHANDLE 建立配置文件缓冲失败,原因:没有空闲的配置文件缓冲句柄分配给当前配置文件缓冲 +// ERROR_FOPEN 打开文件失败 +// ERROR_FREAD 读文件失败 +// ERROR_CONF_CREATEHASH 建立哈希表失败 +// ERROR_MEMORY_ALLOC 申请分配指定大小的内存失败 +// ERROR_CONF_NULL_HANDEPTR 输入了一个空的句柄指针作参数 + +// 参数说明 : szProfileName --[in] 配置文件全路径名 +// 参数说明 : phfile --[out]如果函数执行成功,则返回一个句柄 +int create_profile_cache(pgcchar *szProfileName, int *phfile) +{ + HPROFILE hCurCacher = 0; + + if (szProfileName == NULL) + return ERROR_FOPEN ; + + if (phfile == NULL) + return ERROR_CONF_NULL_HANDEPTR; + + //检查句柄数组是否经过初始化 + if (!g_bHandleInit) + { + memset(g_pHandleIndex, 0, MAX_PROFILEHANDLE_NUM * sizeof(SProfileHanleInfo)); + g_bHandleInit = PGCTRUE; + } + + //为当前缓冲寻找一个空闲句柄 + for (int i = 1; i < MAX_PROFILEHANDLE_NUM; i++) + if (g_pHandleIndex[i].pCacheEntry == NULL) + { + hCurCacher = i; + break; + } + + if ( hCurCacher < 1) + { + return ERROR_CONF_NOHANDLE; + } + + //保存文件全路径名 +//#ifdef OS_WINDOWS + lstrcpyn((LPWSTR)g_pHandleIndex[hCurCacher].szPathName, (LPWSTR)szProfileName, MAX_PATH_NUM); +/*#else + strncpy(g_pHandleIndex[hCurCacher].szPathName, szProfileName, MAX_PATH_NUM - 1); +#endif*/ + pgc32 iExeRev = 0; + if ((iExeRev = ProcessCreateCache(hCurCacher)) != SUCCESS) + return iExeRev; + + *phfile = hCurCacher; + return SUCCESS; +} + + + +// 函数名 : CloseProfileHandle +// 函数说明 : 关闭配置文件缓冲 +// 函数逻辑 : 根据在该配置文件缓冲句柄中记录的信息,释放资源 +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 + +// 返回值 说明 +// SUCCESS 成功关闭配置文件缓冲 +// ERROR_CONF_INVALIDHANDLE 输入了非法的配置文件缓冲句柄 + +// 参数说明 : hProfile --[in]配置文件缓冲句柄 +int close_profile_handle(HPROFILE hProfile) +{ + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + ReleaseProfileCache(hProfile); + + memset(&g_pHandleIndex[hProfile], 0, sizeof(SProfileHanleInfo)); + + return SUCCESS; +} + + +// 函数名 : GetPgcProfileString +// 函数说明 : 根据段名,项目名获取项目值 +// 函数逻辑 : 调用者通过参数lpAppName, lpKeyName传入要取出的项目值所在的段名和项目名, +// 如果指定的段及项目名存在,函数将取出的项目值拷贝到以lpReturnedString为首地址的 +// 目标缓冲中(目标缓冲的长度通过指针pdwSize传入),随后函数会将取出的项目值 +// 的长度(包括'\0'字符)写入地址指针pdwSize中; 如果指定的段及项目名不存在,则执行缺省拷贝,即将 +// lpDefault 所指向的字符串拷贝到目标缓冲区lpReturnedString中; 如果目标缓冲区的首地址 +// lpReturnedString为空或传入的目标缓冲的长度小于1,那么函数不会将任何字符串拷贝到 +// 目标缓冲,但是仍会将取出的项目值的长度(包括'\0'字符)写入到指针pdwSize所指向的地址中。 +// +// +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 + +// 返回值 说明 +// SUCCESS 如果指定的段及项目名存在,函数将取出的项目值拷贝到以lpReturnedString为首地址的 +// 目标缓冲中,如果取出的项目值的长度小于或等于目标缓冲区的长度,那么整个项目值将 +// 被完全拷贝到目标缓冲中,此时函数返回SUCCESS + +// ERROR_CONF_REVBUFFER 如果指定的段及项目名存在,但是取出的项目值的长度大于目标缓冲 +// 区的长度, 那么取出的项目值将被截断为和目标缓冲区一样的大小,然后再拷贝到目标缓 +// 区,此时函数返回ERROR_CONF_REVBUFFER + +// +// SUCCESS_CONF_DEFCOPY 如果指定的段及项目名不存在,并且lpDefault指针不为空,则函数将lpDefault +// 所指向的字符串拷贝到目标缓冲区lpReturnedString,如果lpDefault指向的字符串 +// 的长度大于目标缓冲区的长度,那么只从lpDefault开始拷贝 [目标缓冲区的长度 - 1] +// 个字符到缓冲中。 + +// ERROR_CONF_INVALIDHANDLE 输入了非法的配置文件缓冲句柄 + +// ERROR_FAIL 函数执行失败,即未拷贝任何字符到目标缓冲区 + +// 参数说明 : lpAppName --[in]段名 +// 参数说明 : lpKeyName --[in]项目名 +// 参数说明 : lpDefault --[in] 当获取指定的项目值失败时,将该缓冲区的字符串写入lpReturnedString目标缓冲 +// 参数说明 : lpReturnedString --[out] 目标缓冲区,用来存放取出的项目值 +// 参数说明 : pdwSize -- [in][out]指向缓冲区的长度的指针,同时在调用结束后,将取出的项目字符串的长度(包括'\0'字符)写入该地址 +// 参数说明 : hProfile --[in] 配置文件缓冲句柄 +int get_pgcprofile_string( + const pgcchar * lpAppName, // points to section name + const pgcchar * lpKeyName, // point to key name + const pgcchar * lpDefault, // point to default string + pgcchar * lpReturnedString, // point to destination buffer + pgcu32 * pdwSize, // point to size of destination buffer + HPROFILE hProfile // point to initialization filename + ) +{ + SItemInCache *psTemp = NULL; + TChainHash *phash_table = NULL; + pgcu32 dwBuffer = 0, dwCount = 0, dwNeed = 0; + //bRevBuffer - PGCTRUE表示接收缓冲区足够大 + PGCBOOL bRevBuffer = PGCTRUE; + + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + if ((lpAppName == NULL) || ( lpKeyName == NULL)) + return ERROR_FAIL; + + ReCreateCache(hProfile); + + phash_table = g_pHandleIndex[hProfile].pHashTable; + if (phash_table == NULL) + return ERROR_CONF_INVALIDHANDLE; + + profile_search_sequence(&psTemp, phash_table, lpAppName, lpKeyName); + if ((psTemp != NULL) && (psTemp->valid) && (pdwSize != NULL)) + { + dwBuffer = (pgcu32)strlen(psTemp->szItemVal) + 1; + dwNeed = dwBuffer; + if (dwBuffer > *pdwSize) + { + dwBuffer = *pdwSize; + bRevBuffer = PGCFALSE; + } + if ((lpReturnedString != NULL) && (dwBuffer > 0)) + { + for (dwCount = 0; dwCount < dwBuffer - 1; dwCount++) + lpReturnedString[dwCount] = psTemp->szItemVal[dwCount]; + + lpReturnedString[dwCount] = '\0'; + } + } + else + { + //执行缺省拷贝 + if ((lpDefault != NULL) && (pdwSize != NULL)) + { + dwBuffer = (pgcu32)strlen(lpDefault) + 1; + dwNeed = dwBuffer; + if (dwBuffer > *pdwSize) + { + dwBuffer = *pdwSize; + bRevBuffer = PGCFALSE; + } + if ((dwBuffer > 0) && (lpReturnedString != NULL)) + { + //2002/03/05 杨小波++++++++++++++++++++++++++++++++++++++++++++ +#if 0 + for (pgcu32 dwCount = 0; dwCount < dwBuffer - 1; dwCount++) +#endif + for (dwCount = 0; dwCount < dwBuffer - 1; dwCount++) + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + lpReturnedString[dwCount] = lpDefault[dwCount]; + + lpReturnedString[dwCount] = '\0'; + } + } + else + dwBuffer = 0; + } + *pdwSize = dwNeed; + + if (dwBuffer == 0) + return ERROR_FAIL; + + if (!bRevBuffer) + return ERROR_CONF_REVBUFFER; + + return SUCCESS; +} + + + +// 函数名 : WritePgcProfileString +// 函数说明 : 根据段名,项目名写项目值 +// 函数逻辑 : 调用者通过参数lpAppName, lpKeyName传入要写入的项目值所在的段名和项目名, +// 如果指定的段及项目名存在,函数将把lpString所指向的以空字符结尾的字符串拷贝到 +// 以该段名,项目名对应的项目值缓冲中,然后再把整个配置文件缓冲的内容写入到文件中, +// 并返回SUCCESS;如果指定的段及项目名不存在,函数会根据参数bInsertItem的值决定是否将输入的段名以及 +// 项目名添加到配置文件中,如果bInsertItem为真,则添加该段名和项目名,然后写入项目值, +// 并返回SUCCESS; 如果bInsertItem为假,函数返回ERROR_FAIL。 + +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 + +// 返回值 说明 +// SUCCESS 如果指定的段及项目名存在,函数将把lpString所指向的以空字符结尾的字符串拷贝到 +// 以该段名,项目名对应的项目值缓冲中,然后再把整个配置文件缓冲的内容写入到文件中, +// 并返回SUCCESS +// ERROR_FWRITE 写文件错误 +// ERROR_CONF_INVALIDHANDLE 输入了非法的配置文件缓冲句柄 +// ERROR_CONF_INPUTSTRING_TOOLARGE 输入的段名,项目名,项目值的字符串长度超长 +// ERROR_FAIL 函数执行失败,即未将任何字符写到配置文件缓冲区以及文件 + +// 参数说明 : lpAppName[in] -- 段名 +// 参数说明 : lpKeyName[in] -- 项目名 +// 参数说明 : lpString[in] -- 要写入的字符串 +// 参数说明 : hProfile[in] -- 配置文件缓冲句柄 +// 参数说明 : bInsertItem[in] -- 当指定的段名或项目名不存在时,是否添加该段或项目;PGCTRUE-添加;PGCFALSE-不添加(缺省) +int write_pgcprofile_string( + const pgcchar * lpAppName, // point to section name + const pgcchar * lpKeyName, // point to key name + const pgcchar * lpString, // point to string to add + HPROFILE hProfile, // handle to Profile Cache + PGCBOOL bInsertItem + ) +{ + SItemInCache *psTemp = NULL, *psCacheEntry = NULL, *psSec = NULL; + TChainHash *phash_table = NULL; + pgc32 iBuffer = 0, iCurItem = 0, iSecPos = 0, i = 0, iWriteSuccess = 0; + PGCBOOL bSecExist = PGCFALSE; + PGCBOOL bTrunc = PGCFALSE ;/*写入的字符串是否被截断*/ + + //输入句柄合法性检查 + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + //输入段名及项目名合法性检查 + if ((lpAppName == NULL) || ( lpKeyName == NULL)) + return ERROR_FAIL; + + //判断输入字符串是否超长 + if (strlen(lpAppName) >= MAX_CHAR_LINE) + bTrunc = PGCTRUE; + if (strlen(lpKeyName) >= MAX_CHAR_LINE) + bTrunc = PGCTRUE; + if ( (lpString != NULL) && (strlen(lpString) >= MAX_CHAR_LINE)) + bTrunc = PGCTRUE; + if (bTrunc) + return ERROR_CONF_INPUTSTRING_TOOLARGE; + + //如果配置文件被其它进程修改,则重构缓冲 + ReCreateCache(hProfile); + + //哈希表合法性检查 + phash_table = g_pHandleIndex[hProfile].pHashTable; + if (phash_table == NULL) + return ERROR_CONF_INVALIDHANDLE; + + psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry; + + psTemp = NULL; + profile_search_sequence(&psTemp, phash_table, lpAppName, lpKeyName); + if ((psTemp == NULL) && (bInsertItem)) + { + //检查该段名是否已经存在 + profile_search_sequence(&psSec, phash_table, lpAppName, NULL); + if (psSec != NULL) + { + pgcu32 a1, a2; + + //2002/03/05 杨小波++++++++++++++++++++++++++++++++++++++++++++ +#if 0 + a1 = (pgcu32)psSec - (pgcu32)psCacheEntry; +#endif + a1 = (pgcu32)(psSec - psCacheEntry); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + a2 = (pgcu32)sizeof(SItemInCache); + iSecPos = a1 / a2; + bSecExist = PGCTRUE; + psSec->valid = PGCTRUE; + } + + //重构缓冲区大小 + AdjustCache(hProfile, 2); + psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry; + iCurItem = g_pHandleIndex[hProfile].CurUseItems; + + //应该插入新段名吗? + if (!bSecExist) + { + psTemp = &psCacheEntry[iCurItem]; +#ifdef OS_WINDOWS + lstrcpyn(psTemp->szSecName, lpAppName, MAX_CHAR_LINE); +#else + memset(psTemp->szSecName, 0, MAX_CHAR_LINE); + strncpy(psTemp->szSecName, lpAppName, MAX_CHAR_LINE - 1); + +#endif + psTemp->valid = PGCTRUE; + psTemp->bIsSecName = PGCTRUE; + psTemp->memo = NULL; + + phash_table->insertItem(psTemp); + AddNode(g_pHandleIndex[hProfile].pSequence, g_pHandleIndex[hProfile].pCurSeq, iCurItem); + iSecPos = iCurItem; + iCurItem++; + g_pHandleIndex[hProfile].CurLines++; + } + //插入新项目名及项目值 + psTemp = &psCacheEntry[iCurItem]; + +#ifdef OS_WINDOWS + lstrcpyn(psTemp->szSecName, lpAppName, MAX_CHAR_LINE); + lstrcpyn(psTemp->szItemName, lpKeyName, MAX_CHAR_LINE); + lstrcpyn(psTemp->szItemVal, lpString, MAX_CHAR_LINE); +#else + memset(psTemp, 0, sizeof(SItemInCache)); + strncpy(psTemp->szSecName, lpAppName, MAX_CHAR_LINE - 1); + strncpy(psTemp->szItemName, lpKeyName, MAX_CHAR_LINE - 1); + strncpy(psTemp->szItemVal, lpString, MAX_CHAR_LINE - 1); +#endif + + psTemp->valid = PGCTRUE; + psTemp->bIsSecName = PGCFALSE; + psTemp->memo = NULL; + + + phash_table->insertItem(psTemp); + InsertNode(g_pHandleIndex[hProfile].pSequence, iCurItem, psCacheEntry, iSecPos); + iCurItem++; + + g_pHandleIndex[hProfile].CurUseItems = iCurItem; + g_pHandleIndex[hProfile].CurLines++; + + iBuffer = (pgc32)strlen(psTemp->szItemVal); + psTemp = NULL; + if ((iWriteSuccess = ReWriteProfile(hProfile)) != SUCCESS) + return iWriteSuccess; + } + + if ((psTemp == NULL) && (!bInsertItem)) + return ERROR_CONF_NOTEXIST; + + //如果指定段的项目存在则 + if ((psTemp != NULL) && (lpString != NULL)) + { + if ((psTemp->valid) || (bInsertItem)) + { + iBuffer = (pgc32)strlen(lpString); + if (iBuffer >= MAX_CHAR_LINE) + iBuffer = MAX_CHAR_LINE - 1; + for (i = 0; i < iBuffer; i++) + psTemp->szItemVal[i] = lpString[i]; + psTemp->szItemVal[i] = '\0'; + + psTemp->valid = PGCTRUE; + if ((iWriteSuccess = ReWriteProfile(hProfile)) != SUCCESS) + return iWriteSuccess; + } + } + return SUCCESS; +} + + + +// 函数名 : GetPgcProfileSectionNames +// 函数说明 : 获取配置文件的所有段名 +// 函数逻辑 :将从配置文件中获取的段名按在文件中出现的先后次序写到pdwSize所指向的地址空间, +// 每个段名以一个空字符作为结束标志,在最后一个段名的结尾处再多加一个空字符 +// 作为所有段名的结束标志,即内存格式为 :段名1\0段名2\0......最后一个段名\0\0 + +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 +// 参数说明 : LPTSTR lpszReturnBuffer --[out] 写入缓冲区 +// 参数说明 : pgcu32 *pdwSize -- [in][out]写入缓冲区的按字节长度 +// 参数说明 : pgcu32 *nSecNum --[out]将获取的段总数写入该地址 +// 参数说明 : hProfile-- [in] handle to Profile Cache +int get_pgcprofile_secnames( pgcchar * lpszReturnBuffer, // address of return buffer + pgcu32 * pdwSize, // size of return buffer + pgcu32 *nSecNum, + HPROFILE hProfile // handle to Profile Cache + ) +{ + pgc32 iCount = g_pHandleIndex[hProfile].CurUseItems , iSecNum = 0, i = -1; + pgcu32 dwWrite = 0, dwSize = 0, dwNeed = 0; + SItemInCache *psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry; + pgcchar *szSec = NULL; + + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + ReCreateCache(hProfile); + + if ((pdwSize != NULL) && (*pdwSize > 2)) + dwSize = *pdwSize - 2; + + if ((dwSize > 2) && (lpszReturnBuffer != NULL)) + { + for (i = 0; i < iCount; i++) + { + if ((psCacheEntry[i].bIsSecName) && (psCacheEntry[i].valid)) + { + szSec = psCacheEntry[i].szSecName; + dwNeed = dwNeed + (pgcu32)strlen(szSec) + 1; + iSecNum++; + while ((dwWrite < dwSize ) && (*szSec != '\0')) + { + *lpszReturnBuffer = *szSec; + dwWrite++; + lpszReturnBuffer++; + szSec++; + } + *lpszReturnBuffer = '\0'; + lpszReturnBuffer++; + dwWrite++; + if (dwWrite >= dwSize) + break; + }// endif + }// end for + *lpszReturnBuffer = '\0'; + } + //求所有段名的字符个数总和以及段个数 + for (pgc32 iStart = i + 1; iStart < iCount; iStart++) + { + if ((psCacheEntry[iStart].bIsSecName) && (psCacheEntry[iStart].valid)) + { + iSecNum++; + szSec = psCacheEntry[iStart].szSecName; + if (szSec != NULL) + { + dwNeed = dwNeed + (pgcu32)strlen(szSec) + 1; + } + } + } + if (pdwSize) + *pdwSize = dwNeed; + if (nSecNum) + *nSecNum = iSecNum; + + return SUCCESS; +} + + + +// 函数名 : del_pgcprofile_key +// 函数说明 : 删除指定的项目 +// 函数逻辑 :在缓冲中删除指定的项目,以及该项目上方的注释,然后以覆盖方式重写文件。 + +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 +// 参数说明 : lpAppName --[in] 段名 +// 参数说明 : lpKeyName -- [in]项目名 +// 参数说明 : HPROFILE hProfile --[in]配置文件的缓冲句柄 +int del_pgcprofile_key( const pgcchar * lpAppName, // point to section name + const pgcchar * lpKeyName, // point to key name + HPROFILE hProfile // point to initialization filename + ) +{ + SItemInCache *psTemp = NULL; + TChainHash *phash_table = NULL; + pgc32 iWriteSuccess = 0; + + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + if ((lpAppName == NULL) || ( lpKeyName == NULL)) + return ERROR_FAIL; + + ReCreateCache(hProfile); + + phash_table = g_pHandleIndex[hProfile].pHashTable; + if (phash_table == NULL) + return ERROR_CONF_INVALIDHANDLE; + + profile_search_sequence(&psTemp, phash_table, lpAppName, lpKeyName); + if (psTemp != NULL) + { + psTemp->valid = PGCFALSE; + if ((iWriteSuccess = ReWriteProfile(hProfile)) != SUCCESS) + return iWriteSuccess; + return SUCCESS; + } + return ERROR_CONF_NOTEXIST; +} + + + + +// 函数名 : del_pgcprofile_sec +// 函数说明 : 删除指定的段 +// 函数逻辑 :在缓冲中删除指定的段,以及该段上方的注释,然后以覆盖方式重写文件; +// 在删除一个段的同时,该段下属的所有项目(包括项目上方的注释)将被删除 + +// 返回值说明 : int -- 成功则返回SUCCESS,失败则返回具体的执行失败的代码 +// 参数说明 : lpAppName --[in] 段名 +// 参数说明 : HPROFILE hProfile --[in]配置文件的缓冲句柄 +int del_pgcprofile_sec( const pgcchar * lpAppName, + HPROFILE hProfile + ) +{ + SItemInCache *psSec = NULL, *psCacheEntry = NULL; + TChainHash *phash_table = NULL; + pgc32 iSecPos = 0; + + if ((hProfile < 1) || (hProfile >= MAX_PROFILEHANDLE_NUM)) + return ERROR_CONF_INVALIDHANDLE; + + if (lpAppName == NULL) + return ERROR_FAIL; + + psCacheEntry = g_pHandleIndex[hProfile].pCacheEntry; + if (psCacheEntry == NULL) + return ERROR_CONF_INVALIDHANDLE; + + ReCreateCache(hProfile); + + phash_table = g_pHandleIndex[hProfile].pHashTable; + if (phash_table == NULL) + return ERROR_CONF_INVALIDHANDLE; + + profile_search_sequence(&psSec, phash_table, lpAppName, NULL); + if (psSec != NULL) + { + pgcu32 a1, a2; + + //2002/03/05 杨小波++++++++++++++++++++++++++++++++++++++++++++ +#if 0 + a1 = (pgcu32)psSec - (pgcu32)psCacheEntry; +#endif + a1 = (pgcu32)(psSec - psCacheEntry); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + a2 = (pgcu32)sizeof(SItemInCache); + iSecPos = a1 / a2; + if (DisableSec(g_pHandleIndex[hProfile].pSequence, iSecPos, psCacheEntry)) + { + return ReWriteProfile(hProfile); + } + } + return ERROR_CONF_NOTEXIST; +} + diff --git a/Profile_Hash.h b/Profile_Hash.h new file mode 100644 index 0000000..3d5bc60 --- /dev/null +++ b/Profile_Hash.h @@ -0,0 +1,514 @@ +/****************************************************************************************** + * + * 作者: m.j.y + * + * Pgc配置文件读写等操作--内部函数定义 + * + * $Log: Profile_Hash.h,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.1.2.1 2006/07/28 07:54:02 zhuzhenhua + * no message + * + * Revision 1.4 2003/07/14 01:56:23 scada + * 使用def文件导出函数 + * + * Revision 1.3 2003/06/05 03:56:16 jehu + * 将注释修改为符合doxgen工具提取开发文档 + * + * Revision 1.2 2002/12/04 07:47:36 scada + * for NT + * + * Revision 1.1.1.1 2002/08/21 07:16:37 harold + * temporarily import + * + * Revision 1.14 2002/06/03 10:07:04 mhorse + * 更改了宏的值 + * + * Revision 1.13 2002/03/20 03:40:02 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 13:43:18 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 08:17:08 harold + * no message + * + * Revision 1.12 2002/01/23 05:27:39 harold + * no message + * + * Revision 1.11 2002/01/23 02:39:57 harold + * test_function + * + * Revision 1.10 2002/01/22 08:54:26 harold + * modify2002-01-22-16:46 + * + * Revision 1.9 2002/01/21 12:58:49 harold + * no message + * + * Revision 1.8 2002/01/21 04:52:41 harold + * no message + * + * Revision 1.7 2002/01/18 12:56:14 harold + * revise errno + * + * Revision 1.6 1997/03/29 12:49:05 harold + * revise bug in read/write/listsec function + * + * Revision 1.5 2002/01/18 01:08:03 harold + * revise bugs in write/close/listsec function + * + * Revision 1.4 2002/01/16 09:49:41 harold + * no message + * + * Revision 1.3 2002/01/16 08:13:41 harold + * no message + * + * Revision 1.2 2002/01/09 09:42:40 harold + * no message + * + * + ******************************************************************************************/ + + +#ifndef profile_hashisdjfidsxxxxxxxxxxxxxijpsijfspo +#define profile_hashisdjfidsxxxxxxxxxxxxxijpsijfspo +/*! + * \if developer_doc + * \file + * + * \brief Pgc配置文件读写等操作--内部函数定义头文件。 + * + * id: $Id: Profile_Hash.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif +*/ + + +//#include +#include +#include +//#ifdef OS_LINUX +// #include +//#else + #include + #include +//#endif //OS_LINUX + +#include "global_errno.h" +#include "typedef.h" +//#include "basetype.h" +#include "harximoban.h" +/*! +* \if by_group +* \addtogroup grp_config_rw +* @{ +* \endif +*/ + +/*! + * 配置文件中, 每一行的最大长度 + */ +#define MAX_CONF_LINE_L (1024) +//!< 定义每行(注释行的字符个数无限制)允许的最大字符个数, 包括换行符号'\r\n'及null字符 +#define MAX_CHAR_LINE (MAX_CONF_LINE_L) + +#ifndef PATH_MAX +#define PATH_MAX 260 +#endif +#define MAX_PATH 260 + +//!< 定义存储文件路径的字符串数组的大小 +#define MAX_PATH_NUM (MAX_PATH) + +//在重新生成配置文件时,是否将'\r\n'作为行结束标志 +//#define REWRITEFILE_ADDCHAR_13 + +//!< 设置缓冲区的最大段数 +#define MAX_SEC_NUM 2500 + +//!< 设置缓冲区的每一段的最大项目个数 +#define MAX_ITEM_NUM 30 + +//!< 定义初始化缓冲区容纳项目的个数 +#define INITCACHE_ITEM_NUM 5000 + +//!< 缓冲区增大时的递增项目的个数 +#define RESIZE_ITEM_NUM 5000 + +//!< 定义在一个进程中允许同时打开的配置文件缓冲句柄的个数 +#define MAX_PROFILEHANDLE_NUM 50 + +//!< 定义配置文件缓冲句柄 +typedef pgc32 HPROFILE; + +//!< 保存注释的链表 +typedef struct tagMemoChain +{ + pgcchar *szMemo; + tagMemoChain * NextNode; +} SMemoChain; + +//!< 缓冲项的结构 +typedef struct tagItemInCache +{ + pgcchar szItemName[MAX_CHAR_LINE]; + pgcchar szItemVal[MAX_CHAR_LINE]; + pgcchar szSecName[MAX_CHAR_LINE]; + PGCBOOL valid; + PGCBOOL bIsSecName; + SMemoChain *memo; + tagItemInCache() + { + memset(this, 0, sizeof(*this)); + } +} SItemInCache; + +//!< 项目位置链表结构 +typedef struct tagItemSequence +{ + pgc32 iPos; + tagItemSequence *NextNode; + tagItemSequence() + { + memset(this, 0, sizeof(*this)); + } +} SItemSequence; + +//!< 定义存储句柄对应的信息的结构 +typedef struct tagProfileHanleInfo +{ + FILE *fstream; + //!< 保存配置文件全路径名 + pgcchar szPathName[MAX_PATH_NUM]; + //!< 配置文件上一次被修改的时间 + timeval tLastModify; + //!< 哈希表指针 + TChainHash *pHashTable; + //!< 行位置链表头指针 + SItemSequence *pSequence; + //!< 行位置链表当前指针 + SItemSequence *pCurSeq; + //!< 缓冲区数组入口 + SItemInCache* pCacheEntry; + //!< 段总数 + pgc32 CurSecNum; + //!< 当前缓冲区能容纳的项目个数 + pgc32 CurItemCount; + //!< 已经使用的项目个数 + pgc32 CurUseItems; + //!< 当前文件中的行数 + pgc32 CurLines; + tagProfileHanleInfo() + { + memset(this, 0, sizeof(*this)); + } +} SProfileHanleInfo; + +/*! +* \brief 根据已知的历史数据库索引数组, 为其建立一个哈希表. +* +* \param pindex --[in] 索引数组的指针 +* \param count --[in] pindex索引数组中索引的个数, pindex[0] -- pindex[count - 1]为索引 +* \param pphash_of_index --[in] 将pindex所指向的数组哈希化, 这样, 在随后的索引搜索时, 使用该哈希索引. +* +* \retval SUCCESS -- 成功 +* \retval 其它 -- 失败代码 +* +*/ +pgc32 profile_build_hash_index ( SItemInCache * pindex, + pgc32 count, + TChainHash ** pphash_of_index ); + + +/*! +* \brief 在索引区中搜索 +* +* \param pindex_base --[in] 被哈希化的索引数组的指针 +* \param phash_of_index --[in] 索引数组的哈希表 +* \param szSecName --[in] 被查询的段名 +* \param szItemName --[in] 被查询的项目名 +* +* \retval 索引在索引数组中的序号 -- 成功的查找到指定的配置项目的索引 +* \retval -1 -- 失败 +*/ +pgc32 profile_search_sequence ( SItemInCache **pindex_base, + TChainHash *phash_of_index, + pgcchar *szSecName, + pgcchar *szItemName); + + +/*! +* \brief 判断某行是否被注释。 +* +* \param szLine --[in] 行字串 +* +* \retval PGCTRUE 是注释行 +* \retval PGCFALSE 不是注释行 +*/ +PGCBOOL LineIsMark(pgcchar *szLine); + +/*! +* \brief 寻找段尾。 +* +* \param szString --[in] 字串 +* +* \retval 字船指针 段尾的位置指针 +* \retval NULL 没找到段尾 +*/ +pgcchar* FindSecTail(pgcchar *szString); + +/*! +* \brief 提取段名。 +* +* \param szString --[in] 需要提取段名的字串。 +* \param szRevBuffer --[out] 段名字串缓冲,返回的段名保存在此。 +* \param iBufferLength --[in] 段名字串缓冲空间的长度。 +* +* \retval PGCTRUE 提取段名成功 +* \retval PGCFALSE 提取段名失败 +*/ +PGCBOOL DigSecName(const pgcchar *szString, pgcchar *szRevBuffer, pgc32 iBufferLength); + +/*! +* \brief 提取项目名及项目值。 +* +* \param szString --[in] 需要提取项目名及项目值的字串。 +* \param szItemName --[in] 行字符串头指针。 +* \param szItemVal --[out] 项目值字串缓冲,返回的项目值保存在此。 +* \param iBufferLength --[in] 项目值字串空间的长度。 +* +* \retval PGCTRUE 成功 +* \retval PGCFALSE 失败 +*/ +PGCBOOL DigItemContent( pgcchar *szString, pgcchar *szItemName, pgcchar *szItemVal, pgc32 iBufferLength); + +/*! +* \brief 添加一个节点到顺序链表中。 +* +* \param psHead --[in] 顺序链表头节点的指针。 +* \param iPos --[in] 该节点要保存的缓冲数组的偏移位置。 +* +* \retval PGCTRUE 成功 +* \retval PGCFALSE 失败 +*/ +PGCBOOL AddNode(SItemSequence * &psHead, pgc32 iPos); + +/*! +* \brief 释放配置文件缓冲句柄。 +* +* \param hProfile --[in] 配置文件缓冲句柄。 +*/ +void ReleaseProfileCache(HPROFILE hProfile); + + +/*! +* \brief 重写配置文件。 +* +* \param hProfile --[in] 配置文件缓冲句柄。 +* +* \retval SUCCESS 成功。 +* \retval 其它 失败,错误代码。 +*/ +pgc32 ReWriteProfile(HPROFILE hProfile); + + +/*! +* \brief 创建文件句柄缓冲。 +* +* \param hProfile --[in] 配置文件缓冲句柄。 +* +* \retval SUCCESS 成功。 +* \retval 其它 失败,错误代码。 +*/ +pgc32 ProcessCreateCache(HPROFILE hProfile); + +//----------------------------------------------------------------------------------------- +/*! +*\verbatim +//以下为应用接口 +****************************************************************************************** +* +* 作者: m.j.y +* +* Pgc读配置文件--外部函数定义(供外部调用人员使用) +* +****************************************************************************************** +*\endverbaim +*/ + +/*! +* \brief 建立配置文件缓冲。 +* +* \param szProfileName --[in] 配置文件全路径名。 +* \param phfile --[out] 如果函数执行成功,则返回一个句柄。 +* +* \retval SUCCESS -- 成功建立配置文件缓冲。 +* \retval 失败则返回具体的执行失败的代码。 +* \retval ERROR_CONF_NOHANDLE -- 建立配置文件缓冲失败,原因:没有空闲的配置文件缓冲句柄分配给当前配置文件缓冲。 +* \retval ERROR_FOPEN -- 打开文件失败。 +* \retval ERROR_FREAD -- 读文件失败。 +* \retval ERROR_CONF_CREATEHASH -- 建立哈希表失败。 +* \retval ERROR_MEMORY_ALLOC -- 不能不能分配指定大小的内存。 +*/ +int create_profile_cache(pgcchar *szProfileName, int *phfile); + +/*! +* \brief 关闭配置文件缓冲。 +* +* 函数逻辑:根据在该配置文件缓冲句柄中记录的信息,释放资源. +* +* \param hProfile --[in] 配置文件缓冲句柄。 +* +* \retval SUCCESS -- 成功。 +* \retval 失败则返回具体的执行失败的代码。 +* \retval ERROR_CONF_INVALIDHANDLE -- 输入了非法的配置文件缓冲句柄。 +*/ +int close_profile_handle(HPROFILE hProfile); + + +/*! +* \brief 根据段名,项目名获取项目值。 +* +* 函数逻辑:调用者通过参数lpAppName, lpKeyName传入要取出的项目值所在的段名和项目名, +* 如果指定的段及项目名存在,函数将取出的项目值拷贝到以lpReturnedString为首地址的 +* 目标缓冲中(目标缓冲的长度通过指针pdwSize传入),随后函数会将取出的项目值 +* 的长度(包括'\0'字符)写入地址指针pdwSize中; 如果指定的段及项目名不存在,则执行缺省拷贝,即将 +* lpDefault 所指向的字符串拷贝到目标缓冲区lpReturnedString中; 如果目标缓冲区的首地址 +* lpReturnedString为空或传入的目标缓冲的长度小于1,那么函数不会将任何字符串拷贝到 +* 目标缓冲,但是仍会将取出的项目值的长度(包括'\0'字符)写入地址指针pdwSize中。 +* +* \param lpAppName --[in] 段名。 +* \param lpDefault --[in] 当获取指定的项目值失败时,将该缓冲区的字符串写入lpReturnedString目标缓冲。 +* \param lpReturnedString --[out] 目标缓冲区,用来存放取出的项目值。 +* \param pdwSize --[in][out] 指向缓冲区的长度的指针,同时在调用结束后,将取出的项目字符串的长度(包括'\0'字符)写入该地址。 +* \param hProfile --[in] 配置文件缓冲句柄。 +* +* \retval SUCCESS -- 成功,如果指定的段及项目名存在,函数将取出的项目值拷贝到以lpReturnedString为首地址的 +* 目标缓冲中,如果取出的项目值的长度小于或等于目标缓冲区的长度,那么整个项目值将被完全拷贝到目标缓冲中,此时函数返回SUCCESS。 +* \retval ERROR_CONF_REVBUFFER -- 如果指定的段及项目名存在,但是取出的项目值的长度大于目标缓冲区的长度, +* 那么取出的项目值将被截断为和目标缓冲区一样的大小,然后再拷贝到目标缓区,此时函数返回ERROR_CONF_REVBUFFER。 +* \retval SUCCESS_CONF_DEFCOPY -- 如果指定的段及项目名不存在,并且lpDefault指针不为空,则函数将lpDefault所指向的字符串拷贝到目标缓冲区lpReturnedString, +* 如果lpDefault指向的字符串的长度大于目标缓冲区的长度,那么只从lpDefault开始拷贝 [目标缓冲区的长度 - 1]个字符到缓冲中。 +* \retval ERROR_CONF_INVALIDHANDLE -- 输入了非法的配置文件缓冲句柄。 +* \retval ERROR_FAIL -- 函数执行失败,即未拷贝任何字符到目标缓冲区。 +*/ +int get_pgcprofile_string( + const pgcchar * lpAppName, // points to section name + const pgcchar * lpKeyName, // point to key name + const pgcchar * lpDefault, // point to default string + pgcchar * lpReturnedString, // point to destination buffer + pgcu32 * pdwSize, // point to size of destination buffer + HPROFILE hProfile // point to initialization filename + ); + +/*! +* \brief 根据段名,项目名写项目值。 +* +* 函数逻辑: 调用者通过参数lpAppName, lpKeyName传入要写入的项目值所在的段名和项目名, +* 如果指定的段及项目名存在,函数将把lpString所指向的以空字符结尾的字符串拷贝到 +* 以该段名,项目名对应的项目值缓冲中,然后再把整个配置文件缓冲的内容写入到文件中, +* 并返回SUCCESS;如果指定的段及项目名不存在,函数会根据参数bInsertItem的值决定是否将输入的段名以及 +* 项目名添加到配置文件中,如果bInsertItem为真,则添加该段名和项目名,然后写入项目值, +* 并返回SUCCESS; 如果bInsertItem为假,函数返回ERROR_FAIL。 +* +* \param lpAppName --[in] 段名 +* \param lpKeyName --[in] 项目名 +* \param lpString --[in] 要写入的字符串 +* \param hProfile --[in] 配置文件缓冲句柄 +* \param bInsertItem --[in] 当指定的段名或项目名不存在时,是否添加该段或项目;PGCTRUE-添加;PGCFALSE-不添加(缺省) +* +* \retval SUCCESS(0) -- 如果指定的段及项目名存在,函数将把lpString所指向的以空字符结尾的字符串拷贝到 +* 以该段名,项目名对应的项目值缓冲中,然后再把整个配置文件缓冲的内容写入到文件中,并返回SUCCESS +* \retval ERROR_FWRITE -- 写文件错误 +* \retval ERROR_CONF_INVALIDHANDLE -- 输入了非法的配置文件缓冲句柄 +* \retval ERROR_FAIL -- 函数执行失败,即未将任何字符写到配置文件缓冲区以及文件 +*/ +int write_pgcprofile_string( + const pgcchar * lpAppName, // point to section name + const pgcchar * lpKeyName, // point to key name + const pgcchar * lpString, // point to string to add + HPROFILE hProfile, // handle to Profile Cache + PGCBOOL bInsertItem + ); + +/*! +* \brief 获取配置文件的所有段名。 +* +* 函数逻辑:将从配置文件中获取的段名按在文件中出现的先后次序写到pdwSize所指向的地址空间, +* 每个段名以一个空字符作为结束标志,在最后一个段名的结尾处再多加一个空字符 +* 作为所有全部段名的结束标志,即内存格式为 :段名1\0段名2\0......最后一个段名\0\0 +* +* \param lpszReturnBuffer --[out] 写入缓冲区。 +* \param pdwSize --[in][out] 写入缓冲区的按字节长度。 +* \param nSecNum --[out] 将获取的段总数写入该地址。 +* \param hProfile --[in] handle to Profile Cache +* +* \retval SUCCESS -- 成功 +* \retval 其它 -- 失败则返回具体的执行失败的代码 +*/ +int get_pgcprofile_secnames( + pgcchar * lpszReturnBuffer, // address of return buffer + pgcu32 * pdwSize, // size of return buffer + pgcu32 *nSecNum, + HPROFILE hProfile // handle to Profile Cache + ); + +/*! +* \brief 删除指定的项目。 +* +* 函数逻辑:在缓冲中删除指定的项目,以及该项目上方的注释,然后以覆盖方式重写文件。 +* +* \param lpAppName --[in] 段名 +* \param lpKeyName --[in] 项目名 +* \param hProfile --[in] 配置文件的缓冲句柄 +* +* \retval SUCCESS -- 成功 +* \retval 其它 -- 失败则返回具体的执行失败的代码 +*/ +int del_pgcprofile_key( const pgcchar * lpAppName, // point to section name + const pgcchar * lpKeyName, // point to key name + HPROFILE hProfile // point to initialization filename + ); + +/*! +* \brief 删除指定的段。 +* +* 函数逻辑:在缓冲中删除指定的段,以及该段上方的注释,然后以覆盖方式重写文件; +* 在删除一个段的同时,该段下属的所有项目(包括项目上方的注释)将被删除。 +* +* \param lpAppName --[in] 段名 +* \param hProfile --[in] 配置文件的缓冲句柄 +* +* \retval SUCCESS -- 成功 +* \retval 其它 -- 失败则返回具体的执行失败的代码 +*/ +int del_pgcprofile_sec( const pgcchar * lpAppName, + HPROFILE hProfile + ); + + /*! + * \brief 时间比较, 并返回其差值的绝对值 + * + * \param ptv1 --[in] 时间1 + * \param ptv2 --[in] 时间2 + * \param ptv_abs_delta --[out] 返回差值的绝对值, 如果该参数不为0. + * + * \retval 小于0 -- ptv1 小于(早于) ptv2 + * \retval 等于0 -- ptv1 等于(等于) ptv2 + * \retval 大于0 -- ptv1 大于(晚于) ptv2 + */ + int timeval_compare ( + const timeval * ptv1, + const timeval * ptv2, + timeval * ptv_abs_delta = 0 ); + +/*! +* \if by_group +* @} +* \endif +*/ +#endif + diff --git a/_confrw.h b/_confrw.h new file mode 100644 index 0000000..f303ccc --- /dev/null +++ b/_confrw.h @@ -0,0 +1,13 @@ + +#if !defined(___CONFRW_H__DASJFHNZVCKZLCVHASPFDUIWQERJADHBNCBJADJFJDJAHFLWEJAHDSLFHLA) +#define ___CONFRW_H__DASJFHNZVCKZLCVHASPFDUIWQERJADHBNCBJADJFJDJAHFLWEJAHDSLFHLA + + +//#include +#include "confrw_errno.h" +#include "confrw.h" + +//#include "Profile_Hash.h" + + +#endif //!defined(___CONFRW_H__DASJFHNZVCKZLCVHASPFDUIWQERJADHBNCBJADJFJDJAHFLWEJAHDSLFHLA) diff --git a/baohua.h b/baohua.h new file mode 100644 index 0000000..b42ef03 --- /dev/null +++ b/baohua.h @@ -0,0 +1,77 @@ +#ifndef __BAOHU_A_H_H_ICL__ +#define __BAOHU_A_H_H_ICL__ + +#include "common.h" + +// 设备信息定义 +#define DEVIVE_NAME "CAC-SERVER" +#define VERSION "V1.00" +#define VERSION_DATE "2023-11-10" +#define MANUFACTURER "Global CAC" + +extern SIO_PARAM_DEF SioParam[]; + +extern FUNCTION_CALL *FunCallPtr; + +extern u_short MaxSerialPortNum; +extern u_short MaxNetPortNum; +extern u_short MaxPortNum; + +extern void *pvconf_handle; +extern void *pvportconf_handle; +extern void *pvdataconf_handle; +extern char pvDataFileName[256]; + +extern char DeviceName[]; +extern char Version[]; +extern char VersionDate[]; +extern char Manufacturer[]; +extern char IniFilePath[256]; + +extern DAY_TIME DayTime; + +void ByPassRecvData( int commid, u_char *buf, int len ); +void WatchPortRecvData( void ); + +// 从 config.ini 或 portconfig.ini 读信息 +u_long GetPrivateProString( char * section, char * entry, char * deflautstr, char * reslut,int len, char *inifile ); + +u_long atoul( u_char *buf ); + +int SetPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int GetPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int SetPorvPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int GetPorvPntMsg( int port, int point, void *pntmsg, BYTE type ); + +int CheckPollCmdBufEmpty( int port ); +int PutPollCmdToBuf( int port, int type, WORD wait, char *buf, int len ); + +void PortMemeryMalloc( int port, int type ); + +void YkYtCommandProcess( int port, u_char *buf, int len ); + + +// 读设备信息,检查芯片状态和读芯片类型和频率 +void ReadPortConfigInfo( u_short netport ); + +void DataDisp( HWND ); + +void CloseUdpSetSock( void ); +void PageUp( void ); +void PageDown( void ); +void PageHome( void ); +void PageEnd( void ); +void LineUp( void ); +void LineDown( void ); + +void OpenAllPort( void ); +void CloseOnePort( int commid ); +void CloseAllPort( void ); +void PollAllSerialPort( void ); +void PollAllNetPort( void ); + +void TimerProc( void ); +void SystemRtuTime( void ); + +#endif + diff --git a/basefunc.cpp b/basefunc.cpp new file mode 100644 index 0000000..fe07ccd --- /dev/null +++ b/basefunc.cpp @@ -0,0 +1,922 @@ +//#ifdef OS_WINDOWS +#include +#include +#include +/*#else +#include +#endif*/ +#include +#include +#include +#include "basefunc.h" + +extern char IniFilePath[256]; + +void DebugPrint(char *szDebug) +{ +//#ifdef OS_WINDOWS + OutputDebugString((WCHAR*)szDebug); + OutputDebugString((WCHAR*)"\n"); +//#else +// printf("%s\n", szDebug); +//#endif +} + +int CmpString(const u_char *str1, const u_char *str2) +{ + size_t i, len; + + + len = strlen((char*)str1); + if(len != strlen((char*)str2)) + { + return 0; + } + + for (i = 0; i < len; i++) + { + if(toupper(str1[i]) != toupper(str2[i])) + { + return 0; + } + } + + return 1; +} + +int CmpString2(const char *str1, const char *str2) +{ + size_t i, len; + + len = strlen(str1); + if(len != strlen(str2)) + { + return 0; + } + + for (i = 0; i < len; i++) + { + if(toupper(str1[i]) != toupper(str2[i])) + { + return 0; + } + } + + return 1; +} + +BOOL IsRemarkLine(const char *str) +{ + int i, iLen; + BOOL bRetVal; + + bRetVal = FALSE; + iLen = strlen(str); + for(i=0; i sizeof(buf)) + return FALSE; + + if( IsNetSequence() ) + { + for( i=0; i sizeof(buf)) + { + return FALSE; + } + + if(IsNetSequence() == FALSE) + { + for( i=0; iYear = tmptr->tm_year + 1900; + ptrDateTime->Month = tmptr->tm_mon + 1; + ptrDateTime->Day = tmptr->tm_mday; + ptrDateTime->Hour = tmptr->tm_hour; + ptrDateTime->Min = tmptr->tm_min; + ptrDateTime->Sec = tmptr->tm_sec; + ptrDateTime->mSec = msec; + ptrDateTime->WeekDay = tmptr->tm_wday; + ptrDateTime->MonthDay = tmptr->tm_mday; + + return TRUE; +} + +//******************************************************************** +//* 设置系统时间函数 * +//*参数: DAY_TIME : 时间缓冲区 * +//*返回值:BOOL retval : 是否成功 * +//******************************************************************** +//BOOL SetLocalTimeEx(DAY_TIME *ptrDateTime) +void SetLocalTimeEx(DAY_TIME *ptrDateTime) +{ +#/*if OS_LINUX + //int ret; + //pid_t pid; + //char szCmdLine[256]; + + //sprintf(szCmdLine, "date %02d%02d%02d%02d%04d.%02d", + // ptrDateTime->Month, + // ptrDateTime->Day, + // ptrDateTime->Hour, + // ptrDateTime->Min, + // ptrDateTime->Year, + // ptrDateTime->Sec); + + + //pid = vfork(); + //if(pid == 0) + //{ + // ret = system (szCmdLine); //执行date命令设置时间 + + // exit(0); + // //return exit(0); + // //if(ret == 0) + // //return TRUE; + // //else + // // return FALSE; + //} + ////else return TRUE; + + struct tm tm_st; + time_t tm_t; + + tm_st.tm_year = ptrDateTime->Year - 1900; + tm_st.tm_mon = ptrDateTime->Month - 1; + tm_st.tm_mday = ptrDateTime->Day; + tm_st.tm_hour = ptrDateTime->Hour; + tm_st.tm_min = ptrDateTime->Min; + tm_st.tm_sec = ptrDateTime->Sec; + + //printf("TIP_(%04d): %02d/%02d/%04d_%02d:%02d:%02d.\n", + // getpid(), tm_st.tm_mon+1, tm_st.tm_mday, tm_st.tm_year+1900, + // tm_st.tm_hour, tm_st.tm_min, tm_st.tm_sec); + + tm_t = mktime(&tm_st); + if(tm_t > 0) + { + stime(&tm_t); + + //printf("TIP_(%04d): set time is ok.\n", getpid()); + } +#else */ //windows + + SYSTEMTIME systime; + BOOL bRetVal; + + systime.wYear = ptrDateTime->Year; + systime.wMonth = ptrDateTime->Month; + //systime.wDayOfWeek = ptrDateTime->wDayOfWeek; + systime.wDay = ptrDateTime->Day; + systime.wHour = ptrDateTime->Hour; + systime.wMinute = ptrDateTime->Min; + systime.wSecond = ptrDateTime->Sec; + systime.wMilliseconds = ptrDateTime->mSec; + + bRetVal = SetLocalTime(&systime); + + //if(!bRetVal) return FALSE; + //else return TRUE; + +//#endif +} + +_int64 SystemTimeToMillseconds(DAY_TIME *lpTime, int i8HourOffset) +{ + _int64 iMilliseconds; + time_t iTime; + struct tm changetm; + //struct tm *testtm; + + iMilliseconds=0; + changetm.tm_hour = lpTime->Hour; + changetm.tm_mday = lpTime->Day; + changetm.tm_min = lpTime->Min; + changetm.tm_mon = lpTime->Month - 1; + changetm.tm_sec = lpTime->Sec; + changetm.tm_year = lpTime->Year - 1900; + changetm.tm_isdst = -1; + iTime = mktime(&changetm); + //testtm = localtime( &iTime ); + + if(iTime == (time_t)-1) + return 0; + + iMilliseconds = iTime - i8HourOffset * 3600 * 8; + iMilliseconds = iMilliseconds*1000 + lpTime->mSec; + + return iMilliseconds; +} + +void LogRunRecord(char *pstrLogMsg, char *pstrfilename) +{ + int ilen; + DAY_TIME sCurtime; + char szFileName[256]; + +//#if OS_WINDOWS + FILE *fp; + + GetLocalTimeEx(&sCurtime); + //getcwd(szFileName, sizeof(szFileName)-16); + if(pstrfilename == NULL) + { + sprintf(szFileName, "%s/%04d%02d%02d.log", IniFilePath, sCurtime.Year, sCurtime.Month, sCurtime.Day); + } + else + { + ilen = strlen(pstrfilename); + if((ilen < 3) || (ilen >= (sizeof(szFileName)-1))) + { + sprintf(szFileName, "%s/%04d%02d%02d.log", IniFilePath, + sCurtime.Year, sCurtime.Month, sCurtime.Day); + } + else + { + strcpy(szFileName, pstrfilename); + } + } + + fp = fopen(szFileName, "ab"); + if(fp != NULL) + { + fwrite(pstrLogMsg, sizeof(char), strlen(pstrLogMsg)+1, fp); + fclose(fp); + } +/*#else + int fp; + + GetLocalTimeEx(&sCurtime); + if(pstrfilename == NULL) + { + sprintf(szFileName, "/log/%04d%02d%02d.log", IniFilePath, + sCurtime.Year, sCurtime.Month, sCurtime.Day); + } + else + { + ilen = strlen(pstrfilename); + if((ilen < 3) || (ilen >= (sizeof(szFileName)-1))) + { + sprintf(szFileName, "/log/%04d%02d%02d.log", IniFilePath, + sCurtime.Year, sCurtime.Month, sCurtime.Day); + } + else + { + strcpy(szFileName, pstrfilename); + } + } + + fp = open(szFileName, O_CREAT|O_RDWR|O_APPEND); + if(fp < 0) + { + printf("TIP_(%04d): open %s is Failed.\n", getpid(), szFileName); + } + else + { + ilen = strlen(pstrLogMsg); + write(fp, pstrLogMsg, ilen); + close(fp); + } +#endif*/ +} + +BOOL CheckTcpIpAddr(char *addr) +{ + int d; + + char *ptr; + + if(strlen(addr) < 7) + return FALSE; + + if(strlen(addr) > 20) + return FALSE; + + d = atoi(addr); + if((d < 0) || (d > 255)) + { + return FALSE; + } + + ptr = strstr(addr, "."); + if(ptr == NULL) + { + return FALSE; + } + ptr++; + d = atoi(ptr); + if((d < 0) || (d > 255)) + { + return FALSE; + } + + ptr = strstr(ptr, "."); + if(ptr == NULL) + { + return FALSE; + } + ptr++; + d = atoi(ptr); + if((d < 0) || (d > 255)) + { + return FALSE; + } + + ptr = strstr(ptr, "."); + if(ptr == NULL) + { + return FALSE; + } + ptr++; + d = atoi(ptr); + if((d < 0) || (d > 255)) + { + return FALSE; + } + + return TRUE; +} + +WORD CalCheckout(u_char *buf, int len) +{ + int i; + WORD sum; + + sum = 0; + for(i = 0; i < len; i++) + { + sum += buf[i]; + } + + return sum; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// wen 2005.10.19 增加基本函数 +int IsHexChar(u_char c) +{ + if((c >= '0') && (c <= '9')) + return 1; + + if((c >= 'A') && (c <= 'F')) + return 1; + + if((c >= 'a') && (c <= 'f')) + return 1; + + return 0; +} + +int HexToDec(u_char c) +{ + if((c >= '0') && (c <= '9')) + return (c - '0'); + + if((c >= 'A') && (c <= 'F')) + return (c - 'A' + 10); + + if((c >= 'a') && (c <= 'f')) + return (c - 'a' + 10); + + return 0; +} + +u_long atoul(char *buf) +{ + int j, len; + u_long val; + char szbuf[256]; + + if(!buf) + return 0; + + if(strlen(buf) == 0) + return 0; + + if(buf[0] != '-') + strcpy(szbuf, buf); + else + strcpy(szbuf, &buf[1]); + + val = 0; + len = strlen(szbuf); + if((szbuf[0] == '0') && ((szbuf[1] == 'x')||(szbuf[1]=='X'))) + { + for(j = 2; j < len; j++) + { + if(IsHexChar(szbuf[j]) == 0) + break; + + val = val * 16 + HexToDec(szbuf[j]); + } + } + else + { + for(j = 0; j < len; j++) + { + if((szbuf[j] < '0') || (szbuf[j] > '9')) + break; + + val = val*10 + (szbuf[j] - '0'); + } + } + + return val; +} + +/* ! + \brief 删除字符串中的空格、制表符以及注释符 + \param str[in/out] -- 要删除的字符串指针 + \返回值 retval-- 处理后的字符串长度 +*/ +int StringCutSpace(char *str) +{ + int i, j, flag, len; + char *ptr; + + if(!str) + return 0; + + len = (int)strlen(str); + if(len == 0) + return 0; + + j = 0; + flag = 0; + for(i = 0; i < len; i++) + { + // 在双引号" "中的字符串不进行去空格和制表符的处理 + if(str[i] == '\"') + { + flag = flag ? 0 : 1; + continue; + } + + if(flag == 0) + { + if((str[i] == ' ') || (str[i] == '\t')) + continue; + } + + str[j++] = str[i]; + } + str[j] = 0; + + ptr = strstr(str, "//"); + if(ptr != NULL) + *ptr = 0x00; + ptr = strstr(str, "/*"); + if(ptr != NULL) + *ptr = 0x00; + ptr = strstr(str, "\n"); + if(ptr != NULL) + *ptr = 0x00; + ptr = strstr(str, "\r"); + if(ptr != NULL) + *ptr = 0x00; + ptr = strstr(str, "#"); + if(ptr != NULL) + *ptr = 0x00; + + return strlen(str); +} + +void StringToUpper(char *buf) +{ + int i, len; + + if(!buf) + return; + + len = strlen(buf); + for(i = 0; i < len; i++) + { + //buf[i] = toupper(buf[i]); + if((buf[i] >= 'a') && (buf[i] <= 'z')) + { + buf[i] -= 32; + } + } + + //printf("wen: Upperchar=%s\n", buf); +} + +void StringToLower(char *buf) +{ + int i, len; + + if(!buf) + return; + + len = strlen(buf); + for(i = 0; i < len; i++) + { + //buf[i] = tolower(buf[i]); + if((buf[i] >= 'A') && (buf[i] <= 'Z')) + { + buf[i] += 32; + } + } + + //printf("wen: Lowerchar=%s\n", buf); +} + +void PrintFormatMessage(int iMsgClass, char *ptrMsg) +{ + /* + int ilen; + char szMsg[256]; + + if(ptrMsg == NULL) + { + return; + } + + ilen = strlen(ptrMsg); + if(ilen > 200) + { + ptrMsg[200] = 0; + } + switch(iMsgClass) + { + // !输出信息级别为警告信息 + + case MSG_CLASS_WARN: + sprintf(szMsg, "WARN(%04d): %s\n", getpid(), ptrMsg); + break; + + /* !输出信息级别为错误信息 + + case MSG_CLASS_ERROR: + sprintf(szMsg, "ERR_(%04d): %s\n", getpid(), ptrMsg); + break; + + /* !输出信息级别为提示信息 + + case MSG_CLASS_TIP: + default: + sprintf(szMsg, "TIP_(%04d): %s\n", getpid(), ptrMsg); + break; + } + +#ifdef OS_WINDOWS + OutputDebugString(szMsg); +#else + printf("%s", szMsg); +#endif*/ +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// 超时判断 +BOOL JudgeTimeOut(DAY_TIME *pStartTime, int iTimeOutSeconds) +{ + int iDays, iVal1, iVal2; + int iAllSeconds; + DAY_TIME sCurTime; + + GetLocalTimeEx(&sCurTime); + + iDays = sCurTime.Day - pStartTime->Day; + if((iDays < 0) || abs(iDays) > 1) + { + return TRUE; + } + + iVal1 = sCurTime.Hour*3600 + sCurTime.Min*60 + sCurTime.Sec; + iVal2 = pStartTime->Hour*3600 + pStartTime->Min*60 + pStartTime->Sec; + iAllSeconds = iVal1 - iVal2; + if(iAllSeconds < 0) + { + iAllSeconds += 24*3600; + } + + if(iAllSeconds < iTimeOutSeconds) + { + return FALSE; + } + + return TRUE; +} + +// CRC校验表计算函数 +void CalcCRCTableEx(WORD *pwCrcTable, WORD wDivisor) +{ + int i, j, k; + WORD ench; + + for ( i = 0; i < 256; i++ ) + { + ench = 0; + for(k=0; k<8; k++) + { + if(i & (0x01<>k); + } + for ( j = 0; j < 8; j++ ) + { + if ( (ench & 0x8000) != 0 ) + { + ench = ench << 1; + ench = ench ^ wDivisor; + } + else + { + ench = ench << 1; + } + } + pwCrcTable[i]=0; + for(k=0; k<16; k++) + { + if(ench & (0x0001<>k); + } + } +} + +// 计算校验和 +BYTE CalcAllDataLpc(BYTE *pData, int iLen) +{ + int i; + BYTE retval; + + retval = pData[0]; + for(i=1; i +//#else +#include +#else*/ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +//#endif// OS_WINDOWS + +typedef u_char BYTE; +typedef u_short WORD; +typedef u_long DWORD; +typedef long i_32; +typedef u_long u_32; +typedef int BOOL; +#define TRUE 1 +#define FALSE 0 + +typedef struct tagCMDDEF +{ + u_32 CmdTimerCnt; //命令时间计数 + u_32 CmdTimerConst; //命令时间间隔 +} CMDDEF, *pCMDDEF; + +/*#ifndef OS_WINDOWS +typedef int bool; +typedef int64_t _int64; +typedef uint64_t _uint64; +typedef u_long UINT; +#define true TRUE +#define false FALSE + +typedef struct +{ + WORD Year __attribute__ ((packed)); + u_char Month __attribute__ ((packed)); + u_char Day __attribute__ ((packed)); + u_char WeekDay __attribute__ ((packed)); + u_char MonthDay __attribute__ ((packed)); + u_char Hour __attribute__ ((packed)); + u_char Min __attribute__ ((packed)); + u_char Sec __attribute__ ((packed)); + u_char reserved __attribute__ ((packed)); + WORD mSec __attribute__ ((packed)); +}DAY_TIME; + +#define DSLIB_API +#else*/ +#ifdef DSLIB_EXPORTS + #define DSLIB_API __declspec(dllexport) +#else + #define DSLIB_API __declspec(dllimport) +#endif// DSLIB_EXPORTS + +#pragma pack (push,1) +typedef struct +{ + WORD Year; + u_char Month; + u_char Day; + u_char WeekDay; + u_char MonthDay; + u_char Hour; + u_char Min; + u_char Sec; + u_char reserved; + WORD mSec; +} DAY_TIME; +#pragma pack (pop) +//#endif// OS_WINDOWS +#endif// __BASETYPE_H_ICL__ + diff --git a/buban103.cpp b/buban103.cpp new file mode 100644 index 0000000..eaa9bfa --- /dev/null +++ b/buban103.cpp @@ -0,0 +1,13336 @@ +//*************************************************************** +//* buban103.cpp * +//* aaawen 2004.10.19 * +//*************************************************************** +//_DEBUG_MSG_,_OS_WINDOWS_DEBUG_ +/*#ifdef OS_LINUX +#include "baohulib/commport.h" +#include "baohulib/serialport.h" +#else*/ +#include "commport.h" +#include "udpcomm.h" +#include "display.h" +//#endif +#include +#include +#include "buban103.h" +#include "scadaprotect.h" + +//typedef int i_32; +//typedef unsigned long u_32; + +extern SIO_PARAM_DEF SioParam[]; +extern FUNCTION_CALL *FunCallPtr; +extern void *pvconf_handle; +extern void *pvportconf_handle; +extern void *pvdataconf_handle; +extern char pvDataFileName[256]; +extern char IniFilePath[256]; +/*! + \brief 最大链路数量 + */ +const int MAX_LINK_NUM=30; +/*! + \brief 每条链路最大装置数量 + */ +const int MAX_DEV_NUM_EACH_LINK=12; + +/* +enum Param_Type +{ + PARAM_NO=0, + PARAM_LINK, + PARAM_DEV, + PARAM_YC, + PARAM_YX, + PARAM_YM, + PARAM_YK, + PARAM_SYNCTIME, + PARAM_ASDU10 +}; +*/ + +const char *gpStrBuban103Cmd[BUBAN103_TIMER_CMD_NUM] = +{ + "时间同步过程", + "总查询过程", + "电度量查询", + "通用分类数据模拟量查询", + "通用分类数据状态量查询" +}; + +/*! + 组织结构:链路(间隔)+装置 +*/ +const char *gpStrBuban103ConfigInfo[] = +{ + "*******部颁103规约开始*******", + " ", + " ; 轮询指令配置,所有命令召唤周期均以秒为单位。", + " 时间同步过程 = 0", + " 总查询过程 = 0", + " 电度量查询 = 0", + " 通用分类数据模拟量查询 = 0", + " 通用分类数据状态量查询 = 0", + " ", + " 链路数量=1", + " ; 缺省值=1,只支持一条链路,否则为实际的链路数量", + " ", + " 链路1模板文件名称 = 103template.csv", + " ... ...", + " 链路n模板文件名称 = 103template.csv", + " ; 其中,n=配置信息中的(链路数量)对应的值", + " ", + " 上送遥信变位=0", + " ;仅针对于转发,缺省情况下不上送", + " ", + "*******部颁103规约结束*******", + "", // 结束标志(中间不能含有该空字符串) +}; + +//******************************************************************** +//* 读取配置函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban103ReadConfig(int commid) +{ + int i, j, iDevId; + char szSection[128], entry[256], szbuf[128]; + char szPortConfig[256], szDir[256], szTemplate[256]; + pBUBAN103PORTPARAM pPortParam; + +#ifdef OS_LINUX + strcpy(szPortConfig, "portconfig.ini"); +#else + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); +#endif + + SioParam[commid].ExtInfo = HEAP_MALLOC(sizeof(BUBAN103PORTPARAM)); + Buban103DispMalloc(commid, sizeof(BUBAN103PORTPARAM)); + + if(!SioParam[commid].ExtInfo) + { + sprintf(szbuf, "WARN(%04d): commid_%02d ExtInfo=malloc(%d) failed.\n", + _getpid(), commid, sizeof(BUBAN103PORTPARAM)); + DebugPrint(szbuf); + return; + } + + memset(SioParam[commid].ExtInfo, 0, sizeof(BUBAN103PORTPARAM)); + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + // 只有在SioParam[commid].m_psBaoHu非空时,才会运行到这里 + pPortParam->m_psBaoHu = SioParam[commid].m_psBaoHu; + + sprintf(szSection, "Port%d", commid+1); + + if(GetPrivateProString(szSection, "上送遥信变位", "0", szbuf, 120, szPortConfig) > 0) + { + if(atoi(szbuf) == 0) + { + pPortParam->m_bSendChangeDi = FALSE; + } + else + { + pPortParam->m_bSendChangeDi = TRUE; + } + } + + // wen 2004.07.26 增加保护装置的状态处理 + if(GetPrivateProString(szSection, "链路数量", "1", szbuf, 120, szPortConfig) > 0) + { + pPortParam->m_iLinkNum = atoi(szbuf); + } + + if(pPortParam->m_iLinkNum <= 1) + { + pPortParam->m_iLinkNum = 1; + } + + if(pPortParam->m_iLinkNum > MAX_LINK_NUM) + { + pPortParam->m_iLinkNum = MAX_LINK_NUM; + } + + pPortParam->m_psLink + = (BUBAN103LINKDEF *)HEAP_MALLOC(sizeof(BUBAN103LINKDEF)*pPortParam->m_iLinkNum); + Buban103DispMalloc(commid, sizeof(BUBAN103LINKDEF)*pPortParam->m_iLinkNum); + + memset((void *)pPortParam->m_psLink, 0, sizeof(BUBAN103LINKDEF)*pPortParam->m_iLinkNum); + + // 假定所有链路的配置相同 + //for(i=0; im_iLinkNum; i++) + i=0; + { + // 轮询指令配置 + for(j=0; jm_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerConst + = (int)(atof(szbuf)*1000/TIMER_CNT); + if(pPortParam->m_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerConst > 5) + { + pPortParam->m_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerCnt + = pPortParam->m_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerConst - 5; + } + } + //GetPrivateProString(szSection, "超时时间", "20", szbuf, 120, szPortConfig); + //pPortParam->m_psLink[i].m_u32TimeOutConst = (int)(atof(szbuf)*1000/TIMER_CNT); + pPortParam->m_psLink[i].m_u32TimeOutConst = pPortParam->m_psBaoHu->RetryTime; + } + for(i=1; im_iLinkNum; i++) + { + for(j=0; jm_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerConst + = pPortParam->m_psLink[0].m_sArrayCmdTime[j].m_iCmdTimerConst; + pPortParam->m_psLink[i].m_sArrayCmdTime[j].m_iCmdTimerCnt + = pPortParam->m_psLink[0].m_sArrayCmdTime[j].m_iCmdTimerCnt; + } + + pPortParam->m_psLink[i].m_u32TimeOutConst = pPortParam->m_psLink[0].m_u32TimeOutConst; + } + for(i=0; im_iLinkNum; i++) + { + sprintf(entry, "链路%d模板文件名称", i+1); + GetPrivateProString(szSection, entry, "103template.csv", pPortParam->m_psLink[i].m_chArrayTempletFileName, + sizeof(pPortParam->m_psLink[i].m_chArrayTempletFileName)-1, szPortConfig); +#ifdef OS_LINUX + sprintf(szTemplate, "inf/%s", pPortParam->m_psLink[i].m_chArrayTempletFileName); +#else + sprintf(szTemplate, "%s/inf/%s", IniFilePath, pPortParam->m_psLink[i].m_chArrayTempletFileName); +#endif + // 判断是主站还是子站 + //InitBuban103InfoFromTempletFile(commid, szTemplate, &pPortParam->m_psLink[i]); + //InitBuban103InfoFromDat(commid, &pPortParam->m_psLink[i]); + if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType) + { + // wen 2005.06.22 初始化错误退出,以前配置争取的仍然可以正确运行 + //InitBuban103InfoFromTempletFileEx(commid, szTemplate, &pPortParam->m_psLink[i], FALSE); + if(FALSE == InitBuban103InfoFromTempletFileEx(commid, szTemplate, &pPortParam->m_psLink[i], FALSE)) + { + pPortParam->m_iLinkNum = i; + break; + } + } + else + { + // wen 2005.06.22 初始化错误退出,以前配置争取的仍然可以正确运行 + //InitBuban103InfoFromTempletFileEx(commid, szTemplate, &pPortParam->m_psLink[i], TRUE); + //InitBuban103InfoFromDat(commid, &pPortParam->m_psLink[i]); + if(FALSE == InitBuban103InfoFromTempletFileEx(commid, szTemplate, &pPortParam->m_psLink[i], TRUE)) + { + pPortParam->m_iLinkNum = i; + break; + } + else + { + InitBuban103InfoFromDat(commid, &pPortParam->m_psLink[i]); + } + } + } + + // wen 2005.05.17 重新计算数据库点的位置 + ReCalcDevPntStart(commid, pPortParam); + + InitBuban103CmdBuf(commid, pPortParam); + + // 初始化单向链表,链表最大数量为10个 + for(i=0; im_iLinkNum; i++) + { + if(pPortParam->m_psLink[i].m_psProvDev == NULL) + { + break; + } + + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + iDevId = (commid<<16) + (i<<8) + j; + SingleListInitEx(&pPortParam->m_psLink[i].m_psProvDev[j].m_sBaoHuData, 10, iDevId); + } + } + + //Buban103DispConfig(commid, pPortParam); +} + +//******************************************************************** +//* 读取端口数据函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void Buban103RecvData(int commid, u_char *buf, int len)// 规约读数据处理 +{ + int i; + pBUBAN103PORTPARAM pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + if(!IsExtInfoPtr(commid)) + return; + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + for(i=0; im_psBaoHu->m_iRevStatus) + { + case 0:// 0x10 / 0x68 + pPortParam->m_iRecvLen = 0; + if(buf[i] == 0x10) + { + pPortParam->m_psBaoHu->m_iRevStatus = 4; + pPortParam->m_psBaoHu->m_iNeedRevLength = 4; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + } + else if(buf[i] == 0x68) + { + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + } + else + { + // 错误数据增加 + SioParam[commid].ErrMsgNum++; + } + break; + case 1: + case 2: + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + break; + case 3:// 长度计算 + if(buf[i] == 0x68) + { + if(pPortParam->m_achRecvBuf[1] != pPortParam->m_achRecvBuf[2]) + { + pPortParam->m_psBaoHu->m_iRevStatus=1; + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + Buban103ProcessData(commid, pPortParam, FALSE); + pPortParam->m_iRecvLen = 0; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + } + else + { + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + pPortParam->m_psBaoHu->m_iNeedRevLength = (BYTE)(pPortParam->m_achRecvBuf[1])+2; + } + } + else + { + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + pPortParam->m_psBaoHu->m_iRevStatus=5; + } + break; + case 4:// 正确接收数据 + pPortParam->m_psBaoHu->m_iNeedRevLength--; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(pPortParam->m_psBaoHu->m_iNeedRevLength > 0) + break; + + if(buf[i] != 0x16) + { + pPortParam->m_psBaoHu->m_iRevStatus=5; + break; + } + + if(Buban103Check(pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen) == TRUE) + { + Buban103ProcessData(commid, pPortParam, TRUE); + pPortParam->m_psBaoHu->m_iRevStatus = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 1; + } + else + { + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + SioParam[commid].LostSyncCnt++; + pPortParam->m_psBaoHu->m_iRevStatus = 5; + } +#ifndef OS_LINUX + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + break; + case 5:// 错误接收数据 + default: + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(buf[i] == 0x16) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + Buban103ProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + pPortParam->m_psBaoHu->m_iRevStatus = 0; + pPortParam->m_iRecvLen = 0; + } + else + { + if(pPortParam->m_iRecvLen > 200) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + Buban103ProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + pPortParam->m_iRecvLen = 0; + } + } + break; + } + } + +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "wen: commid = %d, send=%d, recv=%d, error=%d, lost=%d\n", commid, + SioParam[commid].SendCharNum, SioParam[commid].RecvCharNum, + SioParam[commid].ErrMsgNum, SioParam[commid].LostSyncCnt); + DebugPrint(szbuf); +#endif +} + +//******************************************************************** +//* 定时器处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban103Timer(int commid) +{ + BUBAN103PORTPARAM *pPortParam; + BUBAN103LINKDEF *pLinkParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + // wen 2005.06.22 链路数据为0直接退出 + if(pPortParam->m_iLinkNum <= 0) + { + return; + } + + // 如果为转发端口,则不进行轮询指令的生成。 + if(PROTOCOL_SLAVE != pPortParam->m_psBaoHu->PortType) + { + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + if(IsDevLinkOk(pLinkParam, pPortParam->m_iLinkIdx) == TRUE) + { + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + if(IsLinkTimeOut(pLinkParam, 0) == TRUE) + { + InitBuban103CmdBuf(commid, pPortParam); + } + } + else + { + if(IsLinkTimeOut(pLinkParam, pPortParam->m_iLinkIdx) == TRUE) + { + InitBuban103DevCmdBuf(pLinkParam, pLinkParam->m_iDevIdx); + } + } + } + //Buban103FindNextCmd(commid); + if(TRUE == Buban103FindNextCmdEx(commid)) + { + Buban103CalcNextDev(commid, FALSE); + } + } + + Buban103SendCmdFormPollCmdBuf(commid); +} + +//******************************************************************** +//* 遥控遥调数据处理函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void Buban103YkYtProcess(int commid, u_char *buf, int len) // 遥控遥调处理 +{ + int iDirect,portno, ykytpnt; + u_char asdu, dco; + CASDU20 bCAsdu20; + YKYT_PARAM YkYtParam; + DEVDEF *pDevParam; + DEVADDRPARAM sAddrParam; + BUBAN103PORTPARAM *pPortParam; + char szbuf[128]; + + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + iDirect = buf[9] & 0x80; + portno = buf[0]+buf[1]*256+buf[2]*65536+buf[3]*16777216; + ykytpnt = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; + //ykytpnt--; + // 返校信息(反馈信号) + if(iDirect) + { + if((buf[8] == STEP_YKYT_SELECT) || (buf[8] == STEP_YKYT_SELECT+3)) + { + YkYtParam.m_iYkYtPnt = ykytpnt; + YkYtParam.m_iYkYtStep = buf[8]; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + YkYtParam.m_iYkYtOperate = buf[9]; + SendYkYtCommand2(commid, &YkYtParam); + sprintf(szbuf, "WARN(%04d): 转发遥控预令反校成功.\n", _getpid()); + DebugPrint(szbuf); + return; + } + Buban103ProvMakeYkYtCommand(commid, buf, len); + return; + } + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + // 返校失败 + // 条件: 端口链路状态为假或者未找到合适的控点 + if(FALSE == FindProtectDevFromYkYtPnt(pPortParam, &sAddrParam, ykytpnt)) + { + YkYtParam.m_iYkYtPnt = ykytpnt; + YkYtParam.m_iYkYtStep = buf[8]; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + YkYtParam.m_iYkYtOperate = 3; + SendYkYtCommand2(commid, &YkYtParam); + return; + } + else if(FALSE == IsDevLinkOk(&pPortParam->m_psLink[sAddrParam.m_iLinkIdx], sAddrParam.m_iDevIdx)) + { + YkYtParam.m_iYkYtPnt = ykytpnt; + YkYtParam.m_iYkYtStep = buf[8]; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + YkYtParam.m_iYkYtOperate = 3; + SendYkYtCommand2(commid, &YkYtParam); + return; + } + + pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + asdu = pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Asdu; + // 操作类型 + switch(buf[8]) + { + case STEP_YKYT_SELECT: + case STEP_YKYT_SELECT+3://选择 + if((C_DC_NA_3 != asdu) && (C_RC_NA_3 != asdu)) + {// 直控方式 + YkYtParam.m_iYkYtPnt = ykytpnt; + YkYtParam.m_iYkYtStep = buf[8]; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + YkYtParam.m_iYkYtOperate = buf[9]; + SendYkYtCommand2(commid, &YkYtParam); + } + else + { + ykytpnt -= pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + bCAsdu20.nTYP = asdu; //类型标识 + bCAsdu20.nVSQ = 0x01; //可变结构限定词 + bCAsdu20.nCOT = 0x0c; //传送原因 + bCAsdu20.nADDR = pDevParam->m_sDevParam.m_u8DevAddr; //应用服务数据单元公共地址 + bCAsdu20.nFUN = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Fun;//功能类型 + bCAsdu20.nINF = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Inf;//信息序号 + if(buf[9] == 2) + { + bCAsdu20.nDCO = 0x81; //控制断路器(控分) + } + else + { + bCAsdu20.nDCO = 0x82; //控制断路器(控合) + } + bCAsdu20.nRII = (BYTE)sAddrParam.m_iLinkIdx;//返回信息标识符 + + if(pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, pDevParam->m_sDevParam.m_u8DevAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, \ + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + YkYtParam.m_iYkYtPnt = ykytpnt; + YkYtParam.m_iYkYtStep = buf[8]; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + YkYtParam.m_iYkYtOperate = buf[9]; + SendYkYtCommand2(commid, &YkYtParam); + } + break; + case STEP_YKYT_EXEC: + case STEP_YKYT_EXEC+3://执行 + //pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + ykytpnt -= pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + // 遥控遥调不仅仅只用asdu20,还有asdu64/65等 yizhonghu 20060803 + //bCAsdu20.nTYP = 20; //类型标识 + bCAsdu20.nTYP = asdu; //类型标识 + bCAsdu20.nVSQ = 0x81; //可变结构限定词 + if(asdu == 20) + { + bCAsdu20.nCOT = 0x14; //传送原因 + bCAsdu20.nVSQ = 0x81; //可变结构限定词 + } + else + { + bCAsdu20.nCOT = 0x0c; //传送原因 + bCAsdu20.nVSQ = 0x01; //可变结构限定词 + } + bCAsdu20.nADDR = pDevParam->m_sDevParam.m_u8DevAddr; //应用服务数据单元公共地址 + bCAsdu20.nFUN = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Fun;//功能类型 + bCAsdu20.nINF = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Inf;//信息序号 + dco = 0; + if(buf[9] == 2) + { + bCAsdu20.nDCO = (1 | dco); //控制断路器(控分) + } + else + { + bCAsdu20.nDCO = (2 | dco); //控制断路器(控合) + } + bCAsdu20.nRII = (BYTE)sAddrParam.m_iLinkIdx;//返回信息标识符 + + if(pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, pDevParam->m_sDevParam.m_u8DevAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, \ + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + break; + case STEP_YKYT_CANCEL: + case STEP_YKYT_CANCEL+3://取消 + //pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + ykytpnt -= pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + bCAsdu20.nTYP = asdu; //类型标识 + bCAsdu20.nVSQ = 0x01; //可变结构限定词 + bCAsdu20.nCOT = 0x0c; //传送原因 + bCAsdu20.nADDR = pDevParam->m_sDevParam.m_u8DevAddr; //应用服务数据单元公共地址 + bCAsdu20.nFUN = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Fun;//功能类型 + bCAsdu20.nINF = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Inf;//信息序号 + dco = 0xc0; + if(buf[9] == 2) + { + bCAsdu20.nDCO = (1 | dco); //控制断路器(控分) + } + else + { + bCAsdu20.nDCO = (2 | dco); //控制断路器(控合) + } + bCAsdu20.nRII = (BYTE)sAddrParam.m_iLinkIdx;//返回信息标识符 + + if(pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, pDevParam->m_sDevParam.m_u8DevAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, \ + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + break; + case STEP_YKYT_DIRECT:// 直控 + break; + case STEP_YKYT_STOP:// 急停 + //pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + ykytpnt -= pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + bCAsdu20.nTYP = asdu; //类型标识 + bCAsdu20.nVSQ = 0x01; //可变结构限定词 + bCAsdu20.nCOT = 0x0c; //传送原因 + bCAsdu20.nADDR = pDevParam->m_sDevParam.m_u8DevAddr; //应用服务数据单元公共地址 + bCAsdu20.nFUN = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Fun;//功能类型 + bCAsdu20.nINF = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Inf;//信息序号 + dco = 0x00; + bCAsdu20.nDCO = (3 | dco); //遥调急停 + bCAsdu20.nRII = (BYTE)sAddrParam.m_iLinkIdx;//返回信息标识符 + + if(pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, pDevParam->m_sDevParam.m_u8DevAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, \ + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), INSERT_POLL_CMD); + } + break; + default: + break; + } +} + +//******************************************************************** +//* 系统下发对时函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban103SendSystemTime(int commid) // 系统对时 +{ + int i, j; + CMDPARAM sCmdParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + char szbuf[128]; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + + if(2 != pPortParam->m_psBaoHu->CheckTime) + { + return; + } + sprintf(szbuf, "port=%d,CheckTime=%d",commid+1, pPortParam->m_psBaoHu->CheckTime); + DebugPrint(szbuf); + + + // 针对所有的装置发送对时命令 + for(i=0; im_iLinkNum; i++) + { + pLinkParam = &pPortParam->m_psLink[i]; + for(j=0; jm_iDevNum; j++) + { + pDevParam = &pLinkParam->m_psDev[j]; + sCmdParam.m_sDevAddr.m_uchLinkAddr = pLinkParam->m_uchLinkAddr; + sCmdParam.m_sDevAddr.m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + sCmdParam.m_uchFun = (u_char)pDevParam->m_sDevParam.m_sSyncTimeInfo.m_u8Fun; + sCmdParam.m_uchInf = (u_char)pDevParam->m_sDevParam.m_sSyncTimeInfo.m_u8Inf; + sCmdParam.m_uchRII = pDevParam->m_u8RII; + MakeTimeSyn_CAsdu6(commid, &sCmdParam); + } + } +} + +//******************************************************************** +//* 系统退出时规约处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban103Exit(int commid) +{ + int i, j, k; + DBORIENTATION *pDB; + GROUPDEF *pGroup; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(SioParam[commid].ExtInfo == NULL) + { + return; + } + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + if(pPortParam->m_psLink == NULL) + { + return; + } + + for(i=0; im_iLinkNum; i++) + { + pLinkParam = (BUBAN103LINKDEF *)(&pPortParam->m_psLink[i]); + if(pLinkParam->m_psDev != NULL) + { + for(j=0; jm_iDevNum; j++) + { + // ai + for(k=0; km_psDev[j].m_sDevParam.m_sAiDBOrientation[k]; + if(pDB->m_psDataInfo != NULL) + { + HEAP_FREE(pDB->m_psDataInfo); + pDB->m_psDataInfo = NULL; + } + } + + // di + pDB = &pLinkParam->m_psDev[j].m_sDevParam.m_sDiDBOrientation; + if(pDB->m_psDataInfo != NULL) + { + HEAP_FREE(pDB->m_psDataInfo); + pDB->m_psDataInfo = NULL; + } + + // pi + pDB = &pLinkParam->m_psDev[j].m_sDevParam.m_sPiDBOrientation; + if(pDB->m_psDataInfo != NULL) + { + HEAP_FREE(pDB->m_psDataInfo); + pDB->m_psDataInfo = NULL; + } + + // yk + pDB = &pLinkParam->m_psDev[j].m_sDevParam.m_sYkDBOrientation; + if(pDB->m_psDataInfo != NULL) + { + HEAP_FREE(pDB->m_psDataInfo); + pDB->m_psDataInfo = NULL; + } + + // group + for(k=0; km_psDev[j].m_sDevParam.m_iCfgGroupNum; k++) + { + pGroup = &pLinkParam->m_psDev[j].m_sDevParam.m_saGroupDef[k]; + if(pGroup->m_psDataInfo != NULL) + { + HEAP_FREE(pGroup->m_psDataInfo); + pGroup->m_psDataInfo = NULL; + } + if(pGroup->m_psEventInfo != NULL) + { + HEAP_FREE(pGroup->m_psEventInfo); + pGroup->m_psEventInfo = NULL; + } + if(pGroup->m_pu8DataLen != NULL) + { + HEAP_FREE(pGroup->m_pu8DataLen); + pGroup->m_pu8DataLen = NULL; + } + if(pGroup->m_pu8DataType != NULL) + { + HEAP_FREE(pGroup->m_pu8DataType); + pGroup->m_pu8DataType = NULL; + } + if(pGroup->m_pu8GIN != NULL) + { + HEAP_FREE(pGroup->m_pu8GIN); + pGroup->m_pu8GIN = NULL; + } + } + + if(pLinkParam->m_psDev[j].m_sDisturbanceParam.m_pshValue != NULL) + { + HEAP_FREE(pLinkParam->m_psDev[j].m_sDisturbanceParam.m_pshValue); + pLinkParam->m_psDev[j].m_sDisturbanceParam.m_pshValue = NULL; + } + } + HEAP_FREE(pLinkParam->m_psDev); + pLinkParam->m_psDev = NULL; + } + + if(pLinkParam->m_psProvDev != NULL) + { + for(j=0; jm_iDevNum; j++) + { + if(pLinkParam->m_psProvDev[j].m_sYxInfo.m_psDataInfo != NULL) + { + HEAP_FREE(pLinkParam->m_psProvDev[j].m_sYxInfo.m_psDataInfo); + pLinkParam->m_psProvDev[j].m_sYxInfo.m_psDataInfo = NULL; + } + if(pLinkParam->m_psProvDev[j].m_sYcInfo.m_psDataInfo != NULL) + { + HEAP_FREE(pLinkParam->m_psProvDev[j].m_sYcInfo.m_psDataInfo); + pLinkParam->m_psProvDev[j].m_sYcInfo.m_psDataInfo = NULL; + } + if(pLinkParam->m_psProvDev[j].m_sYmInfo.m_psDataInfo != NULL) + { + HEAP_FREE(pLinkParam->m_psProvDev[j].m_sYmInfo.m_psDataInfo); + pLinkParam->m_psProvDev[j].m_sYmInfo.m_psDataInfo = NULL; + } + + SingleListDelAllData(&pLinkParam->m_psProvDev[j].m_sBaoHuData); + } + HEAP_FREE(pLinkParam->m_psProvDev); + pLinkParam->m_psProvDev = NULL; + } + + HEAP_FREE(pLinkParam->m_pbLinkOk); + pLinkParam->m_pbLinkOk = NULL; + HEAP_FREE(pLinkParam->m_pu32LinkOkCnt); + pLinkParam->m_pu32LinkOkCnt = NULL; + HEAP_FREE(pLinkParam->m_pu8CtlByte); + pLinkParam->m_pu8CtlByte = NULL; + } + + HEAP_FREE(pPortParam->m_psLink); + pPortParam->m_psLink = NULL; +} + +// 该函数用来驱动由转发端口下发到实际装置的保护命令 +void Buban103BaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData) +{ + int iProvAddr; + PROVDEVDEF *pProvDevParam; + DEVADDRPARAM sAddrParam; + BUBAN103PORTPARAM *pPortParam; + char szbuf[128]; + + if((MSGTYPE_BAOHU_SCADACMD == rtumsg->MsgType) + || (MSGTYPE_BAOHU_SCADADATA == rtumsg->MsgType)) + { + sprintf(szbuf, "commid%d 收到定值指令", commid); + DebugPrint(szbuf); + + Buban103ScadaProtocolExchange(commid, rtumsg); + return; + } + + if(FALSE == GetPortParamPtr(commid, &pPortParam)) + { + return; + } + + switch(rtumsg->MsgData[0]) + { + case 0x68:// 长帧 + iProvAddr = rtumsg->MsgData[9]; + break; + case 0x10:// 短帧 + default: + iProvAddr = -1; + break; + } + + if(iProvAddr < 0) + { + return; + } + + if(FALSE == FindProtectDevFromProvAddr(pPortParam, &sAddrParam, iProvAddr)) + { + return; + } + + // 上行数据 + //if(MSGTYPE_BAOHU_103DATA == rtumsg->MsgType) + if(bUpData == TRUE) + { + // ??? 在这里存储保护数据(应该只有asdu10的数据类型) + pProvDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psProvDev[sAddrParam.m_iDevIdx]; + SingleListAddData(&pProvDevParam->m_sBaoHuData, rtumsg->MsgData, rtumsg->MsgLen); + return; + } + + // 要进行转发数据的判断,需要在这里增加数据格式的存储,来确定转发数据的来源 + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_iBaoHuCommid = rtumsg->PortIdx; + memcpy((void *)&pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_sRealAddrParam, + (void *)&sAddrParam, sizeof(DEVADDRPARAM)); + GetLocalTimeEx(&pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_sBaoHuCmdStartTime); + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_iBaoHuMsgType = MSGTYPE_BAOHU_103CMD; + + // 修改要下发的指令的地址 + if(sAddrParam.m_uchLinkAddr != 0xFF) + { + rtumsg->MsgData[5] = sAddrParam.m_uchLinkAddr; + } + else + { + rtumsg->MsgData[5] = sAddrParam.m_uchCommAddr; + } + rtumsg->MsgData[9] = sAddrParam.m_uchCommAddr; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)rtumsg->MsgData, rtumsg->MsgLen); +} + +int Buban103GetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB) +{ + DEVDEF *pDevParam; + DEVADDRPARAM sAddrParam; + BUBAN103PORTPARAM *pPortParam; + + if(FALSE == GetPortParamPtr(commid, &pPortParam)) + { + return 0; + } + + if(FALSE == FindProtectDevFromProvAddr(pPortParam, &sAddrParam, iProvAddr)) + { + return 0; + } + + pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + + *ppBaoHuDB = pDevParam->m_sDevParam.m_saGroupDef; + + return pDevParam->m_sDevParam.m_iCfgGroupNum; +} +/////////////////////////通用函数接口结束/////////////////////////////// + +void Buban103ProvMakeYkYtCommand(int commid, u_char *buf, int len) +{ + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分, 0=失败) + // (最高位为1时,为返校命令) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + int ykytpnt; + u_char asdu; + CASDU20 bCAsdu20; + DEVDEF *pDevParam; + DEVADDRPARAM sAddrParam; + BUBAN103PORTPARAM *pPortParam; + + if((buf[8] != STEP_YKYT_EXEC)\ + && (buf[8] != STEP_YKYT_EXEC+3) + && (buf[8] != STEP_YKYT_DIRECT)) + { + return; + } + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + ykytpnt = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; + + if(FALSE == FindProtectDevFromYkYtPnt(pPortParam, &sAddrParam, ykytpnt)) + { + return; + } + + pDevParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_psDev[sAddrParam.m_iDevIdx]; + ykytpnt -= pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + asdu = pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Asdu; + // 遥控的类型标识不仅仅有20还有64/65 yizhonghu 20060803 + //bCAsdu20.nTYP = 20; //类型标识 + bCAsdu20.nTYP = asdu; //类型标识 + if(asdu != 20) + { + bCAsdu20.nVSQ = 0x01; //可变结构限定词 + bCAsdu20.nCOT = 0x0c; //传送原因 + } + else + { + bCAsdu20.nVSQ = 0x81; //可变结构限定词 + bCAsdu20.nCOT = 0x14; //传送原因 + } + bCAsdu20.nADDR = pDevParam->m_sDevParam.m_u8DevAddr; //应用服务数据单元公共地址 + bCAsdu20.nFUN = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Fun;//功能类型 + bCAsdu20.nINF = (u_char)pDevParam->m_sDevParam.m_sYkDBOrientation.m_psDataInfo[ykytpnt].m_u8Inf;//信息序号 + if(buf[9] == 2) + { + bCAsdu20.nDCO = 1; //控制断路器(控分) + } + else + { + bCAsdu20.nDCO = 2; //控制断路器(控合) + } + bCAsdu20.nRII = pDevParam->m_u8RII;//返回信息标识符 + + if(pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, pDevParam->m_sDevParam.m_u8DevAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), FAST_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, \ + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu20, sizeof(CASDU20), FAST_POLL_CMD); + } +} + +//******************************************************************** +//* 初始化装置参数函数 * +//*参数:DEVPARAMDEF *psDevParam : 装置参数指针 * +//******************************************************************** +void SetProtectDevStatus(BUBAN103LINKDEF *psLinkParam, int iDevNo, BOOL bStatus) +{ + DI_DEF pntmsg; + DEVDEF *psDevDef; + + if(psLinkParam->m_psDev == NULL) + { + return; + } + + if(bStatus == TRUE) + { + pntmsg.Status = 1; + } + else + { + pntmsg.Status = 0; + } + psDevDef = &psLinkParam->m_psDev[iDevNo]; + + if(psLinkParam->m_iInputStationOfDevStatus > 0) + { + SetPntMsg(psLinkParam->m_iInputStationOfDevStatus-1, + psLinkParam->m_iInputStartPntOfDevStatus+iDevNo, + (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } +} +//===========================以下为装置初始化函数===================== +//******************************************************************** +//* 初始化装置参数函数 * +//*参数:DEVPARAMDEF *psDevParam : 装置参数指针 * +//******************************************************************** +void InitDevParam(DEVPARAMDEF *psDevParam) +{ + psDevParam->m_u8SCN = 0; + psDevParam->m_sSyncTimeInfo.m_u8Fun = 255; + psDevParam->m_u8CPUNo = 1; + psDevParam->m_u8FixNo = 1; +} + +//******************************************************************** +//* 读取模板文件信息函数 * +//*参数:int commid : 端口号 * +//* char *ptrTemplate : 模板文件名称 * +//* BUBAN103LINKDEF *psLink : 要配置端口的参数指针 * +//******************************************************************** +BOOL InitBuban103InfoFromTempletFile(int commid, + char *ptrTemplate, + BUBAN103LINKDEF *psLink) +{ + int i; + char *ptr; + char szBuf[512]; + BOOL bVal; + HDSFILE hFile; + enum Param_Type ParamType; + + hFile = DSOpenFileEx(ptrTemplate); + if(hFile == NULL) + { + // test + sprintf(szBuf, "open<%s> is failed.", ptrTemplate); + DebugPrint(szBuf); + return FALSE; + } + + // test + sprintf(szBuf, "open<%s> is succeed.", ptrTemplate); + DebugPrint(szBuf); + + ParamType = PARAM_NO; + while(TRUE) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(!ptr) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "链路描述") != NULL) + { + //处理链路参数 + ParamType = PARAM_LINK; + } + else if(strstr(ptr, "设备描述") != NULL) + { + ParamType = PARAM_DEV; + } + else if(PARAM_NO == ParamType) + { + continue; + } + + switch(ParamType) + { + case PARAM_LINK: + bVal = GetLinkParamFromTemplateFile(commid, hFile, psLink); + if(TRUE == bVal) + { + if(psLink->m_iDevNum > 0) + { + psLink->m_psDev = (DEVDEF *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(DEVDEF)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(DEVDEF)); + + if(psLink->m_psDev == NULL) + { + psLink->m_iDevNum = 0; + } + memset((void *)psLink->m_psDev, 0, psLink->m_iDevNum*sizeof(DEVDEF)); + + if(psLink->m_uchLinkAddr == 0xFF) + { + psLink->m_pbLinkOk = (BOOL *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(BOOL)); + memset((void *)psLink->m_pbLinkOk, 0, psLink->m_iDevNum*sizeof(BOOL)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(BOOL)); + + psLink->m_pu32LinkOkCnt = (u_32 *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(u_32)); + memset((void *)psLink->m_pu32LinkOkCnt, 0, psLink->m_iDevNum*sizeof(u_32)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(u_32)); + + psLink->m_pu8CtlByte = (BYTE *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(u_char)); + memset(psLink->m_pu8CtlByte, 0, psLink->m_iDevNum*sizeof(u_char)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(u_char)); + } + else + { + psLink->m_pbLinkOk = (BOOL *)HEAP_MALLOC(sizeof(BOOL)); + psLink->m_pbLinkOk[0] = FALSE; + Buban103DispMalloc(commid, sizeof(BOOL)); + + psLink->m_pu32LinkOkCnt = (u_32 *)HEAP_MALLOC(sizeof(u_32)); + psLink->m_pu32LinkOkCnt[0] = 0; + Buban103DispMalloc(commid, sizeof(u_32)); + + psLink->m_pu8CtlByte = (BYTE *)HEAP_MALLOC(sizeof(u_char)); + psLink->m_pu8CtlByte[0] = 0; + Buban103DispMalloc(commid, sizeof(u_char)); + } + + for(i=0; im_iDevNum; i++) + { + InitDevParam(&psLink->m_psDev[i].m_sDevParam); + } + } + } + break; + + case PARAM_DEV: + bVal = GetDevParamFromTemplateFile(commid, hFile, psLink); + break; + + default: + break; + } + } + + DSCloseFile(hFile); + return TRUE; +} + +BOOL InitBuban103InfoFromTempletFileEx(int commid, + char *ptrTemplate, + BUBAN103LINKDEF *psLink, + BOOL bMaster) +{ + char *ptr; + char szBuf[512]; + BOOL bVal; + HDSFILE hFile; + enum Param_Type ParamType; + + if(bMaster == TRUE) + { + return InitBuban103InfoFromTempletFile(commid, ptrTemplate, psLink); + } + + hFile = DSOpenFile(ptrTemplate); + if(hFile == NULL) + { + // test + sprintf(szBuf, "open<%s> is failed.", ptrTemplate); + DebugPrint(szBuf); + return FALSE; + } + + // test + sprintf(szBuf, "open<%s> is succeed.", ptrTemplate); + DebugPrint(szBuf); + + ParamType = PARAM_NO; + while(TRUE) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(!ptr) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "链路描述") != NULL) + { + //处理链路参数 + ParamType = PARAM_LINK; + } + else if(strstr(ptr, "设备描述") != NULL) + { + ParamType = PARAM_DEV; + } + else if(PARAM_NO == ParamType) + { + continue; + } + + switch(ParamType) + { + case PARAM_LINK: + bVal = GetLinkParamFromTemplateFile(commid, hFile, psLink); + if(TRUE == bVal) + { + if(psLink->m_iDevNum > 0) + { + psLink->m_psProvDev = (PROVDEVDEF *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(PROVDEVDEF)); + if(psLink->m_psProvDev == NULL) + { + psLink->m_iDevNum = 0; + } + memset((void *)psLink->m_psProvDev, 0, psLink->m_iDevNum*sizeof(PROVDEVDEF)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(PROVDEVDEF)); + + if(psLink->m_uchLinkAddr == 0xFF) + { + psLink->m_pbLinkOk = (BOOL *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(BOOL)); + memset((void *)psLink->m_pbLinkOk, 0, psLink->m_iDevNum*sizeof(BOOL)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(BOOL)); + + psLink->m_pu32LinkOkCnt = (u_32 *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(u_32)); + memset((void *)psLink->m_pu32LinkOkCnt, 0, psLink->m_iDevNum*sizeof(u_32)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(u_32)); + + psLink->m_pu8CtlByte = (BYTE *)HEAP_MALLOC(psLink->m_iDevNum*sizeof(u_char)); + memset(psLink->m_pu8CtlByte, 0, psLink->m_iDevNum*sizeof(u_char)); + Buban103DispMalloc(commid, psLink->m_iDevNum*sizeof(u_char)); + } + else + { + psLink->m_pbLinkOk = (BOOL *)HEAP_MALLOC(sizeof(BOOL)); + psLink->m_pbLinkOk[0] = FALSE; + Buban103DispMalloc(commid, sizeof(BOOL)); + + psLink->m_pu32LinkOkCnt = (u_32 *)HEAP_MALLOC(sizeof(u_32)); + psLink->m_pu32LinkOkCnt[0] = 0; + Buban103DispMalloc(commid, sizeof(u_32)); + + psLink->m_pu8CtlByte = (BYTE *)HEAP_MALLOC(sizeof(u_char)); + psLink->m_pu8CtlByte[0] = 0; + Buban103DispMalloc(commid, sizeof(u_char)); + } + } + } + break; + + case PARAM_DEV: + bVal = GetProvDevParamFromTemplateFile(commid, hFile, psLink); + break; + + default: + break; + } + } + + DSCloseFile(hFile); + return TRUE; +} + +BOOL GetParamItem(char *pSour, char **ppDest) +{ + if(pSour == NULL) + { + return FALSE; + } + + *ppDest = strstr(pSour, ","); + + if(*ppDest == NULL) + { + return FALSE; + } + + return TRUE; +} + +BOOL GetParamItemEx(char *pSour, char **ppDest, const char *pSplit) +{ + if(pSour == NULL) + { + return FALSE; + } + + *ppDest = strstr(pSour, pSplit); + + if(*ppDest == NULL) + { + return FALSE; + } + + return TRUE; +} + +BOOL GetLinkParamFromTemplateFile(int commid, HDSFILE hFile,\ + BUBAN103LINKDEF *psLink) +{ + char *ptr, *ptrSour, *ptrDest; + char szBuf[512]; + int i, ilen; + BOOL bRetVal; + + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + + if(ptr == NULL) + { + return FALSE; + } + + ptrSour = szBuf; + + if(strstr(ptrSour, "LINK") == NULL) + { + return FALSE; + } + + // test + //DebugPrint(szBuf); + + bRetVal = TRUE; + for(i=0; i<13; i++) + { + if(GetParamItem(ptrSour, &ptrDest) == FALSE) + { + bRetVal = FALSE; + break; + } + *ptrDest = 0; + ilen = strlen(ptrSour); + + switch(i) + { + case 0:// 链路描述 + if(ilen > 0) + { + if(ilen >= sizeof(psLink->m_szLinkName)) + { + ilen = sizeof(psLink->m_szLinkName)-1; + } + memcpy(psLink->m_szLinkName, ptrSour, ilen); + psLink->m_szLinkName[ilen] = 0; + } + break; + case 1:// 链路标识 + break; + case 2:// 链路地址 + if(ilen > 0) + { + psLink->m_uchLinkAddr = (BYTE)atoi(ptrSour); + } + else + { + psLink->m_uchLinkAddr = 255; + } + break; + case 3:// 装置数量 + if(ilen > 0) + { + psLink->m_iDevNum = (BYTE)atoi(ptrSour); + } + break; + case 4:// 备用 + break; + case 5:// 备用 + break; + case 6:// 地址偏移 + if(ilen > 0) + { + psLink->m_iProvAddrOffset = atoi(ptrSour); + } + break; + case 7:// 数据类型 + break; + case 8:// 写入数据库站号 + if(ilen > 0) + { + psLink->m_iInputStationOfDevStatus = atoi(ptrSour); + } + break; + case 9:// 写入数据库起始点号 + if(ilen > 0) + { + psLink->m_iInputStartPntOfDevStatus = atoi(ptrSour); + } + break; + case 10:// 是否判断ASDU号 + if(ilen > 0) + { + psLink->m_iJudgeAsduNo = atoi(ptrSour); + } + break; + case 11:// 是否处理扰动数据 + if(ilen > 0) + { + psLink->m_iDisTransDataProcess = atoi(ptrSour); + } + break; + case 12:// 是否屏蔽未配置事件 + if(ilen > 0) + { + psLink->m_iMaskNoMatchString = atoi(ptrSour); + } + break; + case 13:// 一类数据问询次数(该项不可达,在循环外处理) + if(ilen > 0) + { + psLink->m_iQueryNum_CLASS1_Const = atoi(ptrSour); + } + else + { + psLink->m_iQueryNum_CLASS1_Const = 1; + } + break; + } + ptrSour = ptrDest+1; + } + // 最后一项 + if(bRetVal == TRUE) + { + // 一类数据问询次数 + if(strlen(ptrSour) > 0) + { + psLink->m_iQueryNum_CLASS1_Const = atoi(ptrSour); + } + else + { + psLink->m_iQueryNum_CLASS1_Const = 1; + } + } + + return bRetVal; +} + +BOOL GetDevParamFromTemplateFile(int commid, HDSFILE hFile,\ + BUBAN103LINKDEF *psLink) +{ + char *ptr, *ptrSour, *ptrDest; + char szBuf[512]; + int i, j, ilen, iNum; + int iAiNum, iAiStart, iDiStart; + int iPiStart, iYkStart, iPntNo; + BOOL bRetVal; + enum Param_Type ParamType; + + iAiStart = 0; + iDiStart = 0; + iPiStart = 0; + iYkStart = 0; + iAiNum = 0; + ParamType = PARAM_NO; + bRetVal = TRUE; + for(i=0; im_iDevNum;) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(ptr == NULL) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "设备描述") != NULL) + { + i++; + iAiNum = 0; + ParamType = PARAM_NO; + continue; + } + + if(strstr(ptr, "链路描述") != NULL) + { + break; + } + + ptrSour = ptr; + for(j=0; j<8; j++) + { + if(GetParamItem(ptrSour, &ptrDest) == FALSE) + { + bRetVal = FALSE; + break; + } + *ptrDest = 0; + ilen = strlen(ptrSour); + + switch(j) + { + case 0:// 设备描述 + if(ParamType != PARAM_NO) + { + break; + } + if(ilen > 0) + { + if(ilen >= sizeof(psLink->m_psDev[i].m_sDevParam.m_szDevName)) + { + ilen = sizeof(psLink->m_psDev[i].m_sDevParam.m_szDevName)-1; + } + + memcpy(psLink->m_psDev[i].m_sDevParam.m_szDevName, ptrSour, ilen); + psLink->m_psDev[i].m_sDevParam.m_szDevName[ilen] = 0; + } + break; + case 1:// 设备型号 + if(ParamType != PARAM_NO) + { + break; + } + if(ilen > 0) + { + if(ilen >= sizeof(psLink->m_psDev[i].m_sDevParam.m_szType)) + { + ilen = sizeof(psLink->m_psDev[i].m_sDevParam.m_szType)-1; + } + + memcpy(psLink->m_psDev[i].m_sDevParam.m_szType, ptrSour, ilen); + psLink->m_psDev[i].m_sDevParam.m_szType[ilen] = 0; + } + else + { + strcpy(psLink->m_psDev[i].m_sDevParam.m_szType, "dat103"); + } + break; + case 2:// 设备地址 + if(ParamType != PARAM_NO) + { + break; + } + if(ilen > 0) + { + psLink->m_psDev[i].m_sDevParam.m_u8DevAddr = (BYTE)atoi(ptrSour); + } + break; + case 3:// 转发地址 + if(PARAM_NO != ParamType) + { + break; + } + if(ilen > 0) + { + psLink->m_psDev[i].m_sDevParam.m_iProvAddr = atoi(ptrSour); + } + break; + case 4:// 备用 + break; + case 5:// 备用 + break; + case 6:// 数量 + if(ilen > 0) + { + iNum = atoi(ptrSour); + } + break; + case 7:// 数据类型 + if(iNum <= 0) + { + break; + } + if(ilen > 0) + { + if(strcmp(ptrSour, "YC") == 0) + { + ParamType = PARAM_YC; + psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_iStnNo = commid+1; + psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_iStartPntNo = iAiStart; + psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_iPntNum = iNum; + if(NULL != psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo) + { + HEAP_FREE(psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + //psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo + // = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)*iNum); + //memset((void *)psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo, + // 0, sizeof(DBINFO)*iNum); + //======================================================================================== + psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo + = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)); + memset((void *)psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum].m_psDataInfo, + 0, sizeof(DBINFO)); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Buban103DispMalloc(commid, sizeof(DBINFO)*iNum); + + iAiStart += iNum; + iAiNum++; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YX") == 0) + { + ParamType = PARAM_YX; + psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_iStnNo = commid+1; + psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_iStartPntNo = iDiStart; + psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_iPntNum = iNum; + if(NULL != psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_psDataInfo) + { + HEAP_FREE(psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_psDataInfo); + } + psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_psDataInfo + = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)*iNum); + memset((void *)psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation.m_psDataInfo, + 0, sizeof(DBINFO)*iNum); + Buban103DispMalloc(commid, sizeof(DBINFO)*iNum); + + iDiStart += iNum; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YM") == 0) + { + ParamType = PARAM_YM; + psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_iStnNo = commid+1; + psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_iStartPntNo = iPiStart; + psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_iPntNum = iNum; + if(NULL != psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_psDataInfo) + { + HEAP_FREE(psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_psDataInfo); + } + psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_psDataInfo + = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)*iNum); + memset((void *)psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation.m_psDataInfo, + 0, sizeof(DBINFO)*iNum); + Buban103DispMalloc(commid, sizeof(DBINFO)*iNum); + + iPiStart += iNum; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YK") == 0) + { + ParamType = PARAM_YK; + psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_iStnNo = commid+1; + psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_iStartPntNo = iYkStart; + psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_iPntNum = iNum; + if(NULL != psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_psDataInfo) + { + HEAP_FREE(psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_psDataInfo); + } + psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_psDataInfo + = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)*iNum); + memset((void *)psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation.m_psDataInfo, + 0, sizeof(DBINFO)*iNum); + Buban103DispMalloc(commid, sizeof(DBINFO)*iNum); + + iYkStart += iNum; + iPntNo = 0; + } + else if(strcmp(ptrSour, "SYNCTIME") == 0) + { + ParamType = PARAM_SYNCTIME; + iPntNo = 0; + } + else if(strcmp(ptrSour, "ASDU10") == 0) + { + ParamType = PARAM_ASDU10; + psLink->m_psDev[i].m_sDevParam.m_iCfgGroupNum = iNum; + iPntNo = 0; + } + } + break; + default: + break; + } + ptrSour = ptrDest+1; + } + + switch(ParamType) + { + case PARAM_YC: + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + //if(TRUE == GetInfoData(ptrSour, iPntNo, + // (DBORIENTATION *)(&psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation))) + //{ + // iPntNo++; + //} + //=============================================================================================== + if(iAiNum > 0) + { + GetInfoData(ptrSour, 0, (DBORIENTATION *)(&psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[iAiNum-1])); + } + else + { + GetInfoData(ptrSour, 0, (DBORIENTATION *)(&psLink->m_psDev[i].m_sDevParam.m_sAiDBOrientation[0])); + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + break; + case PARAM_YX: + if(TRUE == GetInfoData(ptrSour, iPntNo, + &psLink->m_psDev[i].m_sDevParam.m_sDiDBOrientation)) + { + iPntNo++; + } + break; + case PARAM_YM: + if(TRUE == GetInfoData(ptrSour, iPntNo, + &psLink->m_psDev[i].m_sDevParam.m_sPiDBOrientation)) + { + iPntNo++; + } + break; + case PARAM_YK: + if(TRUE == GetInfoData(ptrSour, iPntNo, + &psLink->m_psDev[i].m_sDevParam.m_sYkDBOrientation)) + { + iPntNo++; + } + break; + case PARAM_SYNCTIME: + GetSyncTimeInfoData(ptrSour, &psLink->m_psDev[i].m_sDevParam.m_sSyncTimeInfo); + break; + case PARAM_ASDU10: + if(TRUE == GetGroupInfoData(ptrSour, iPntNo, &psLink->m_psDev[i].m_sDevParam)) + { + iPntNo++; + } + break; + default: + break; + } + } + return bRetVal; +} + +BOOL GetProvDevParamFromTemplateFile(int commid,HDSFILE hFile,\ + BUBAN103LINKDEF *psLink) +{ + char *ptr, *ptrSour, *ptrDest; + char szBuf[512]; + int i, j, ilen, iNum; + int iAiNum, iAiStart, iDiStart; + int iPiStart, iYkStart, iPntNo; + BOOL bRetVal; + enum Param_Type ParamType; + + iAiStart = 0; + iDiStart = 0; + iPiStart = 0; + iYkStart = 0; + iAiNum = 0; + ParamType = PARAM_NO; + bRetVal = TRUE; + for(i=0; im_iDevNum;) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(ptr == NULL) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "设备描述") != NULL) + { + i++; + iAiNum = 0; + ParamType = PARAM_NO; + continue; + } + + if(strstr(ptr, "链路描述") != NULL) + { + break; + } + + ptrSour = ptr; + for(j=0; j<8; j++) + { + if(GetParamItem(ptrSour, &ptrDest) == FALSE) + { + bRetVal = FALSE; + break; + } + *ptrDest = 0; + ilen = strlen(ptrSour); + + switch(j) + { + case 0:// 设备描述 + break; + case 1:// 设备型号 + break; + case 2:// 设备地址 + break; + case 3:// 转发地址 + if(PARAM_NO != ParamType) + { + break; + } + if(ilen > 0) + { + psLink->m_psProvDev[i].m_iProvAddr = atoi(ptrSour); + } + break; + case 4:// 端口号&状态站号&状态点号 + if(PARAM_NO != ParamType) + { + break; + } + if(ilen > 0) + { + psLink->m_psProvDev[i].m_iRealCommid = atoi(ptrSour); + if(GetParamItemEx(ptrSour, &ptrDest, "&") == FALSE) + { + psLink->m_psProvDev[i].m_iStatusStn = 0; + psLink->m_psProvDev[i].m_iStatusPnt = 0; + break; + } + ptrSour = ptrDest+1; + if(strlen(ptrSour) > 0) + { + psLink->m_psProvDev[i].m_iStatusStn = atoi(ptrSour); + if(GetParamItemEx(ptrSour, &ptrDest, "&") == FALSE) + { + psLink->m_psProvDev[i].m_iStatusStn = 0; + psLink->m_psProvDev[i].m_iStatusPnt = 0; + break; + } + ptrSour = ptrDest+1; + if(strlen(ptrSour) > 0) + { + psLink->m_psProvDev[i].m_iStatusPnt = atoi(ptrSour); + } + } + } + break; + case 5:// 备用 + break; + case 6:// 数量 + if(ilen > 0) + { + iNum = atoi(ptrSour); + } + break; + case 7:// 数据类型 + if(iNum <= 0) + { + break; + } + if(ilen > 0) + { + if(strcmp(ptrSour, "YC") == 0) + { + ParamType = PARAM_YC; + psLink->m_psProvDev[i].m_sYcInfo.m_iPntNum = iNum; + psLink->m_psProvDev[i].m_sYcInfo.m_iStartPntNo = 0; + psLink->m_psProvDev[i].m_sYcInfo.m_iStnNo = 0; + psLink->m_psProvDev[i].m_sYcInfo.m_psDataInfo = NULL; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YX") == 0) + { + ParamType = PARAM_YX; + psLink->m_psProvDev[i].m_sYxInfo.m_iPntNum = iNum; + psLink->m_psProvDev[i].m_sYxInfo.m_iStartPntNo = 0; + psLink->m_psProvDev[i].m_sYxInfo.m_iStnNo = 0; + if(NULL != psLink->m_psProvDev[i].m_sYxInfo.m_psDataInfo) + { + HEAP_FREE(psLink->m_psProvDev[i].m_sYxInfo.m_psDataInfo); + } + psLink->m_psProvDev[i].m_sYxInfo.m_psDataInfo + = (DBINFO *)HEAP_MALLOC(sizeof(DBINFO)*iNum); + memset((void *)psLink->m_psProvDev[i].m_sYxInfo.m_psDataInfo, + 0, sizeof(DBINFO)*iNum); + Buban103DispMalloc(commid, sizeof(DBINFO)*iNum); + + iPntNo = 0; + } + else if(strcmp(ptrSour, "YM") == 0) + { + ParamType = PARAM_YM; + psLink->m_psProvDev[i].m_sYmInfo.m_iPntNum = iNum; + psLink->m_psProvDev[i].m_sYmInfo.m_iStartPntNo = 0; + psLink->m_psProvDev[i].m_sYmInfo.m_iStnNo = 0; + psLink->m_psProvDev[i].m_sYmInfo.m_psDataInfo = NULL; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YK") == 0) + { + ParamType = PARAM_YK; + iPntNo = 0; + } + else if(strcmp(ptrSour, "SYNCTIME") == 0) + { + ParamType = PARAM_SYNCTIME; + iPntNo = 0; + } + else if(strcmp(ptrSour, "ASDU10") == 0) + { + ParamType = PARAM_ASDU10; + psLink->m_psProvDev[i].m_iAsdu10Num = iNum; + iPntNo = 0; + } + } + break; + default: + break; + } + ptrSour = ptrDest+1; + } + + switch(ParamType) + { + case PARAM_YC: + break; + case PARAM_YX: + if(TRUE == GetInfoData(ptrSour, iPntNo, + &psLink->m_psProvDev[i].m_sYxInfo)) + { + iPntNo++; + } + break; + case PARAM_YM: + break; + case PARAM_YK: + break; + case PARAM_SYNCTIME: + break; + case PARAM_ASDU10: + break; + default: + break; + } + } + return bRetVal; +} + +BOOL GetInfoData(char *pInfo, int iPntNo, DBORIENTATION *psDB) +{ + int i; + char *ptr1, *ptr2; + BOOL bRetVal; + + if(pInfo == NULL) + { + return FALSE; + } + if(iPntNo >= psDB->m_iPntNum) + { + return FALSE; + } + + if(psDB->m_psDataInfo == NULL) + { + return FALSE; + } + + bRetVal = TRUE; + ptr1 = pInfo; + for(i=0; i<6; i++) + { + if(GetParamItem(ptr1, &ptr2) == FALSE) + { + //bRetVal = FALSE; + break; + } + + *ptr2 = 0; + switch(i) + { + case 0:// 描述 + break; + case 1:// ASDU + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8Asdu = atoi(ptr1); + } + break; + case 2:// FUN + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8Fun = atoi(ptr1); + } + break; + case 3:// INF + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8Inf = atoi(ptr1); + } + break; + case 4:// PROV_FUN + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8ProvFun = atoi(ptr1); + } + else + { + psDB->m_psDataInfo[iPntNo].m_u8ProvFun\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Fun; + } + break; + case 5:// PROV_INF + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8ProvInf = atoi(ptr1); + } + else + { + psDB->m_psDataInfo[iPntNo].m_u8ProvInf\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Inf; + } + break; + case 6://是否总召唤数据 + if(strlen(ptr1) > 0) + { + psDB->m_psDataInfo[iPntNo].m_u8LoopData = atoi(ptr1); + } + else + { + psDB->m_psDataInfo[iPntNo].m_u8LoopData = 0; + } + break; + default: + bRetVal = FALSE; + break; + } + ptr1 = ptr2+1; + } + + // INF + if(strlen(ptr1) > 0) + { + switch(i) + { + case 3:// INF + psDB->m_psDataInfo[iPntNo].m_u8Inf = atoi(ptr1); + psDB->m_psDataInfo[iPntNo].m_u8ProvFun\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Fun; + psDB->m_psDataInfo[iPntNo].m_u8ProvInf\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Inf; + psDB->m_psDataInfo[iPntNo].m_u8LoopData = 0; + break; + case 4:// PROV_FUN + psDB->m_psDataInfo[iPntNo].m_u8ProvFun = atoi(ptr1); + psDB->m_psDataInfo[iPntNo].m_u8ProvInf\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Inf; + psDB->m_psDataInfo[iPntNo].m_u8LoopData = 0; + break; + case 5:// PROV_INF + psDB->m_psDataInfo[iPntNo].m_u8ProvInf = atoi(ptr1); + psDB->m_psDataInfo[iPntNo].m_u8LoopData = 0; + break; + case 6://是否总召唤数据 + psDB->m_psDataInfo[iPntNo].m_u8LoopData = atoi(ptr1); + break; + default: + if(i < 6) + { + bRetVal = FALSE; + } + break; + } + } + else + { + switch(i) + { + case 4:// PROV_FUN + psDB->m_psDataInfo[iPntNo].m_u8ProvFun\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Fun; + case 5:// PROV_INF + psDB->m_psDataInfo[iPntNo].m_u8ProvInf\ + = (u_char)psDB->m_psDataInfo[iPntNo].m_u8Inf; + case 6://是否总召唤数据 + psDB->m_psDataInfo[iPntNo].m_u8LoopData = 0; + break; + default: + if(i < 6) + { + bRetVal = FALSE; + } + break; + } + } + + return bRetVal; +} + +BOOL GetSyncTimeInfoData(char *pInfo, DBINFO *psSyncInfo) +{ + int i; + char *ptr1, *ptr2; + BOOL bRetVal; + + if(pInfo == NULL) + { + return FALSE; + } + + if(psSyncInfo == NULL) + { + return FALSE; + } + + bRetVal = TRUE; + ptr1 = pInfo; + for(i=0; i<3; i++) + { + if(GetParamItem(ptr1, &ptr2) == FALSE) + { + bRetVal = FALSE; + break; + } + + *ptr2 = 0; + switch(i) + { + case 0:// 描述 + break; + case 1:// ASDU + if(strlen(ptr1) > 0) + { + psSyncInfo->m_u8Asdu = atoi(ptr1); + } + break; + case 2:// FUN + if(strlen(ptr1) > 0) + { + psSyncInfo->m_u8Fun = atoi(ptr1); + } + break; + default: + bRetVal = FALSE; + break; + } + ptr1 = ptr2+1; + } + // INF + if(strlen(ptr1) > 0) + { + psSyncInfo->m_u8Inf = atoi(ptr1); + } + + return bRetVal; +} + +BOOL GetGroupInfoData(char *pInfo, int iPntNo, DEVPARAMDEF *psDevParam) +{ + int i; + char *ptr1, *ptr2; + BOOL bRetVal; + + if(pInfo == NULL) + { + return FALSE; + } + if(iPntNo >= psDevParam->m_iCfgGroupNum) + { + return FALSE; + } + + bRetVal = TRUE; + ptr1 = pInfo; + for(i=0; i<3; i++) + { + if(GetParamItem(ptr1, &ptr2) == FALSE) + { + bRetVal = FALSE; + break; + } + + *ptr2 = 0; + switch(i) + { + case 0:// GROUPNO + if(strlen(ptr1) > 0) + { + psDevParam->m_saGroupDef[iPntNo].m_iGroupNo = atoi(ptr1); + } + break; + case 1:// DATATYPE + if(strlen(ptr1) > 0) + { + psDevParam->m_saGroupDef[iPntNo].m_iDataType = atoi(ptr1); + } + break; + case 2:// STN + if(strlen(ptr1) > 0) + { + psDevParam->m_saGroupDef[iPntNo].m_iStationNo = atoi(ptr1); + } + break; + default: + bRetVal = FALSE; + break; + } + ptr1 = ptr2+1; + } + // START_PNT + if(strlen(ptr1) > 0) + { + psDevParam->m_saGroupDef[iPntNo].m_iStartPntNo = atoi(ptr1); + } + + return bRetVal; +} + +BOOL InitBuban103InfoFromDat(int commid, BUBAN103LINKDEF *psLink) +{ + int i, j, iMallocSize; + char szDatFile[256], szbuf[256]; + //char szDbg[256]; + char szSection[128]; + GROUPDEF *psGroupParam; + + for(i=0; im_iDevNum; i++) + { +#ifdef OS_LINUX + sprintf(szDatFile, "dat/%s.dat", + psLink->m_psDev[i].m_sDevParam.m_szType); +#else + sprintf(szDatFile, "%s\\dat\\%s.dat", + IniFilePath, psLink->m_psDev[i].m_sDevParam.m_szType); +#endif + for(j=0; jm_psDev[i].m_sDevParam.m_iCfgGroupNum; j++) + { + psGroupParam = &psLink->m_psDev[i].m_sDevParam.m_saGroupDef[j]; + //psGroupParam->m_pu8DataLen = NULL; + //psGroupParam->m_pu8DataType = NULL; + //psGroupParam->m_pu8GIN = NULL; + //psGroupParam->m_iPntNum = 0; + psGroupParam->m_u32CurPntNo = 1; + psGroupParam->m_bInit = FALSE; + // (缺省为5,即第一个条目大于5的数据包为中间数据包) + psGroupParam->m_iStartItemNo = 5; + + if(PROTECT_EVENT_PNT_TYPE == psGroupParam->m_iDataType) + { + psGroupParam->m_psEventInfo = (GROUPEVENTDEF *)HEAP_MALLOC(sizeof(GROUPEVENTDEF)); + memset((void *)psGroupParam->m_psEventInfo, 0, sizeof(GROUPEVENTDEF)); + Buban103DispMalloc(commid, sizeof(GROUPEVENTDEF)); + //psGroupParam->m_psDataInfo = NULL; + } + else + { + //psGroupParam->m_psEventInfo = NULL; + //psGroupParam->m_psDataInfo = NULL; + sprintf(szSection, "组号%d", psGroupParam->m_iGroupNo); + szbuf[0] = 0; + GetPrivateProString(szSection, "数量", "0", szbuf, sizeof(szbuf), szDatFile); + + //sprintf(szDbg, "[%s]:[数量] = %s\n", szSection, szbuf); + //DebugPrint(szDbg); + + psGroupParam->m_iPntNum = atoi(szbuf); + if(psGroupParam->m_iPntNum > 0) + { + iMallocSize = psGroupParam->m_iPntNum * sizeof(GROUPDATADEF); + psGroupParam->m_psDataInfo = (GROUPDATADEF *)HEAP_MALLOC(iMallocSize); + memset((void *)psGroupParam->m_psDataInfo, 0, iMallocSize); + Buban103DispMalloc(commid, iMallocSize); + + InitGroupParam(psGroupParam, szDatFile); + + iMallocSize = psGroupParam->m_iPntNum * sizeof(BYTE); + psGroupParam->m_pu8GIN = (BYTE *)HEAP_MALLOC(iMallocSize); + Buban103DispMalloc(commid, iMallocSize); + + if(PROTECT_FIX_PNT_TYPE == psGroupParam->m_iDataType) + { + psGroupParam->m_pu8DataLen = (BYTE *)HEAP_MALLOC(iMallocSize); + Buban103DispMalloc(commid, iMallocSize); + + psGroupParam->m_pu8DataType = (BYTE *)HEAP_MALLOC(iMallocSize); + Buban103DispMalloc(commid, iMallocSize); + } + } + + GetPrivateProString(szSection, "首条目号", "-1", szbuf, sizeof(szbuf), szDatFile); + + + //sprintf(szDbg, "[%s]:[首条目号] = %s\n", szSection, szbuf); + //DebugPrint(szDbg); + + if(atoi(szbuf) > 0) + { + psGroupParam->m_iStartItemNo = atoi(szbuf); + } + } + } + } + + return TRUE; +} + +void InitGroupParam(GROUPDEF *psGroupParam, char *szDatFileName) +{ + i_32 i, iNameLen, iFixDataType; + char szbuf[512], szSection[128], szItem[128]; + char *ptrFirst, *ptrFind; + BOOL bValue; + + bValue = FALSE; + sprintf(szSection, "组号%d", psGroupParam->m_iGroupNo); + for(i=0; im_iPntNum; i++) + { + ptrFirst = (char *)szbuf; + sprintf(szItem, "%d", i+1); + if(GetPrivateProString(szSection, szItem, "未知名称", szbuf, sizeof(szbuf), szDatFileName) < 0) + { + strcpy(szbuf, "未知名称"); + } + + // 名称 + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + { + *ptrFind = 0; + iNameLen = strlen(ptrFirst); + } + else + { + iNameLen = strlen(ptrFirst); + if(iNameLen >= sizeof(psGroupParam->m_psDataInfo[i].m_szName)) + { + iNameLen = sizeof(psGroupParam->m_psDataInfo[i].m_szName)-1; + } + + memcpy(psGroupParam->m_psDataInfo[i].m_szName, ptrFirst, iNameLen); + psGroupParam->m_psDataInfo[i].m_szName[iNameLen] = 0; + continue; + } + if(iNameLen >= sizeof(psGroupParam->m_psDataInfo[i].m_szName)) + { + iNameLen = sizeof(psGroupParam->m_psDataInfo[i].m_szName)-1; + } + + memcpy(psGroupParam->m_psDataInfo[i].m_szName, ptrFirst, iNameLen); + psGroupParam->m_psDataInfo[i].m_szName[iNameLen] = 0; + + if(PROTECT_DI_PNT_TYPE == psGroupParam->m_iDataType) + { + psGroupParam->m_psDataInfo[i].m_fValue = (float)bValue; + bValue = !bValue; + } + else + { + psGroupParam->m_psDataInfo[i].m_fValue = (float)(i+1); + } + + // 其他信息 + if(PROTECT_DI_PNT_TYPE == psGroupParam->m_iDataType) + continue; + + if(PROTECT_AI_PNT_TYPE == psGroupParam->m_iDataType) + { + // 序号 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 占有位 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 系数 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 单位 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + { + *ptrFind = 0; + iNameLen = strlen(ptrFirst); + } + else + { + iNameLen = strlen(ptrFirst); + } + if(iNameLen >= sizeof(psGroupParam->m_psDataInfo[i].m_szUnit)) + { + iNameLen = sizeof(psGroupParam->m_psDataInfo[i].m_szUnit)-1; + } + + memcpy(psGroupParam->m_psDataInfo[i].m_szUnit, ptrFirst, iNameLen); + psGroupParam->m_psDataInfo[i].m_szUnit[iNameLen] = 0; + + continue; + } + + if(PROTECT_FIX_PNT_TYPE == psGroupParam->m_iDataType) + { + // 类型(AI=1, DI=2) + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + iFixDataType = atoi(ptrFirst); + psGroupParam->m_psDataInfo[i].iFixDataType = (u_char)iFixDataType; + + // 序号 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 占有位 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 开关量 + if(iFixDataType == 2) + { + // 可能存在有动作描述 + continue; + } + + // 以下为模拟量初始化 + // 系数(充当步长) + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + psGroupParam->m_psDataInfo[i].m_fStepValue = (float)atof(ptrFirst); + if(ptrFind) + *ptrFind = 0; + else + continue; + + // 单位 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + if(ptrFind) + { + *ptrFind = 0; + iNameLen = strlen(ptrFirst); + } + else + { + iNameLen = strlen(ptrFirst); + } + if(iNameLen >= sizeof(psGroupParam->m_psDataInfo[i].m_szUnit)) + { + iNameLen = sizeof(psGroupParam->m_psDataInfo[i].m_szUnit)-1; + } + + memcpy(psGroupParam->m_psDataInfo[i].m_szUnit, ptrFirst, iNameLen); + psGroupParam->m_psDataInfo[i].m_szUnit[iNameLen] = 0; + if(NULL == ptrFind) + continue; + + // 最小值 + ptrFirst = ptrFind + 1; + ptrFind = strstr(ptrFirst, ","); + psGroupParam->m_psDataInfo[i].m_fMinValue = (float)atof(ptrFirst); + if(ptrFind) + { + *ptrFind = 0; + } + else + { + continue; + } + + // 最大值 + ptrFirst = ptrFind + 1; + psGroupParam->m_psDataInfo[i].m_fMaxValue = (float)atof(ptrFirst); + } + } +} + +void InitBuban103CmdBuf(int commid, BUBAN103PORTPARAM *psPortParam) +{ + int i; + + psPortParam->m_iLinkIdx = 0; + for(i=0; im_iLinkNum; i++) + { + InitBuban103LinkCmdBuf(&psPortParam->m_psLink[i]); + } +} + +void InitBuban103LinkCmdBuf(BUBAN103LINKDEF *psLinkParam) +{ + int i; + + psLinkParam->m_bRstLinkOk = FALSE; + psLinkParam->m_bGotoNext = FALSE; + psLinkParam->m_iQueryNum_CLASS1_Count = 0; + psLinkParam->m_iDevIdx = 0; + psLinkParam->m_iQueryedAddr_CLASS1 = 0; + psLinkParam->m_shCurCmdIdx = 0; + + if(psLinkParam->m_uchLinkAddr != 0xFF) + { + psLinkParam->m_pu8CtlByte[0] = 0x00; + psLinkParam->m_pbLinkOk[0] = FALSE; + psLinkParam->m_pu32LinkOkCnt[0] = 0; + } + else + { + for(i=0; im_iDevNum; i++) + { + psLinkParam->m_pu8CtlByte[i] = 0x00; + psLinkParam->m_pbLinkOk[i] = FALSE; + psLinkParam->m_pu32LinkOkCnt[i] = 0; + } + } + + // 初始化指令队列 + for(i=0; im_sArrayCmdTime[i].m_iCmdTimerConst > 20) + { + psLinkParam->m_sArrayCmdTime[i].m_iCmdTimerCnt + = psLinkParam->m_sArrayCmdTime[i].m_iCmdTimerConst-20; + } + else + { + psLinkParam->m_sArrayCmdTime[i].m_iCmdTimerCnt + = psLinkParam->m_sArrayCmdTime[i].m_iCmdTimerConst; + } + } + + for(i=0; im_iDevNum; i++) + { + InitBuban103DevCmdBuf(psLinkParam, i); + } +} + +void InitBuban103DevCmdBuf(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + DEVDEF *psDevDef; + PROVDEVDEF *psProvDevParam; + + SetProtectDevStatus(psLinkParam, iDevNo, FALSE); + + if(psLinkParam->m_psDev != NULL) + { + psDevDef = &psLinkParam->m_psDev[iDevNo]; + } + else + { + psDevDef = NULL; + } + + if(psLinkParam->m_psProvDev != NULL) + { + psProvDevParam = &psLinkParam->m_psProvDev[iDevNo]; + } + else + { + psProvDevParam = NULL; + } + + // 链路地址为255,则每个装置都是链路装置 + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + psLinkParam->m_pbLinkOk[iDevNo] = FALSE; + psLinkParam->m_pu32LinkOkCnt[iDevNo] = 0; + psLinkParam->m_pu8CtlByte[iDevNo] = 0; + } + + if(psDevDef != NULL) + { + psDevDef->m_bAllQueryOk = TRUE; + psDevDef->m_bInitdata = FALSE; + if(psLinkParam->m_u32TimeOutConst > 10) + { + psDevDef->m_u32CallCnt + = psLinkParam->m_u32TimeOutConst-5; + } + else + { + psDevDef->m_u32CallCnt = 0; + } + psDevDef->m_u8RII = 0; + psDevDef->m_sDevParam.m_iFaultNo = -1; + psDevDef->m_sDevParam.m_u32FuncCode = 0; + if(psDevDef->m_sDisturbanceParam.m_pshValue != NULL) + { + HEAP_FREE(psDevDef->m_sDisturbanceParam.m_pshValue); + } + memset((void *)&psDevDef->m_sDisturbanceParam, 0, sizeof(BUBAN103DISTURBANCEDEF)); + } + + if(psProvDevParam != NULL) + { + memset((void *)&psProvDevParam->m_sProvGroupParam, 0, sizeof(PROV_ALLITEMOFGROUPPARAM)); + psProvDevParam->m_sProvGroupParam.m_bFinished = TRUE; + psProvDevParam->m_sProvSoe.m_shFront = 0; + psProvDevParam->m_sProvSoe.m_shRear = 0; + psProvDevParam->m_sProvSoe.m_shSoeNum = 0; + + // 转发 + psProvDevParam->m_bProvQuery = FALSE; + psProvDevParam->m_iProvAsdu5Cause = 0; + psProvDevParam->m_iProvQueryStepWithASDU = 0; + + // wen 2005.06.22 不可以在这里初始化链表 + // 初始化单向链表,链表最大数量为10个 + //SingleListInit(&psProvDevParam->m_sBaoHuData, 10); + } +} + +void ReCalcDevPntStart(int commid, BUBAN103PORTPARAM *psPortParam) +{ + int i, j, k; + int iAiStart, iDiStart; + int iPiStart, iYkStart; + BOOL bSlave; + DEVDEF *pDevParam=NULL; + PROVDEVDEF *pProvDevParam=NULL; + + iAiStart = 0; + iDiStart = 0; + iPiStart = 0; + iYkStart = 0; + if(psPortParam->m_psLink[0].m_psDev != NULL) + { + bSlave = FALSE; + pProvDevParam = NULL; + } + if(psPortParam->m_psLink[0].m_psProvDev != NULL) + { + bSlave = TRUE; + pDevParam = NULL; + } + for(i=0; im_iLinkNum; i++) + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + if(FALSE == bSlave) + { + pDevParam = &psPortParam->m_psLink[i].m_psDev[j]; + } + else + { + pProvDevParam = &psPortParam->m_psLink[i].m_psProvDev[j]; + } + + if(pDevParam != NULL) + { + // ai + for(k=0; km_sDevParam.m_sAiDBOrientation[k].m_iPntNum <= 0) + { + break; + } + pDevParam->m_sDevParam.m_sAiDBOrientation[k].m_iStartPntNo = iAiStart; + iAiStart += pDevParam->m_sDevParam.m_sAiDBOrientation[k].m_iPntNum; + } + + // di + if(pDevParam->m_sDevParam.m_sDiDBOrientation.m_iPntNum > 0) + { + pDevParam->m_sDevParam.m_sDiDBOrientation.m_iStartPntNo = iDiStart; + iDiStart += pDevParam->m_sDevParam.m_sDiDBOrientation.m_iPntNum; + } + + // pi + if(pDevParam->m_sDevParam.m_sPiDBOrientation.m_iPntNum > 0) + { + pDevParam->m_sDevParam.m_sPiDBOrientation.m_iStartPntNo = iPiStart; + iPiStart += pDevParam->m_sDevParam.m_sPiDBOrientation.m_iPntNum; + } + + if(pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum > 0) + { + pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo = iYkStart; + iYkStart += pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum; + } + } + + if(pProvDevParam != NULL) + { + // ai + if(pProvDevParam->m_sYcInfo.m_iPntNum > 0) + { + pProvDevParam->m_sYcInfo.m_iStartPntNo = iAiStart; + iAiStart += pProvDevParam->m_sYcInfo.m_iPntNum; + } + + // di + if(pProvDevParam->m_sYxInfo.m_iPntNum > 0) + { + pProvDevParam->m_sYxInfo.m_iStartPntNo = iDiStart; + iDiStart += pProvDevParam->m_sYxInfo.m_iPntNum; + } + + // Pi + if(pProvDevParam->m_sYmInfo.m_iPntNum > 0) + { + pProvDevParam->m_sYmInfo.m_iStartPntNo = iPiStart; + iPiStart += pProvDevParam->m_sYmInfo.m_iPntNum; + } + } + } + } +} +//===========================装置初始化函数结束======================= + +//===========================以下为指令生成函数======================= +//************************************************************************** +//* 生成 Buban103协议链路层命令 * +//*参数:u_32 commid:RTU端口号 * +//* BYTE bLinkAddr:链路地址 * +//* u_char link_cmd_idx:链路层命令索引 * +//* u_char *msg:应用层命令信息,即应用服务数据单元,如果使用固定 * +//* 长度的帧格式,则用NULL调用 * +//* u_32 len:应用层命令信息的长度,如果使用固定长度的帧格式,则用0调用* +//* u_32 cmdtype: 指令缓冲区类型 * +//************************************************************************** +void MakeBuban103LinkCommand(u_32 commid, BYTE bLinkAddr, u_char link_cmd_idx, + u_char* msg, u_32 len, u_32 cmdtype) +{ + u_char tmp[MAX_POLL_CMD_BUF_LEN], nCs, nEnd; + CLPDU_FIX bClpdu_fix; + CLPDU_VARR bClpdu_varr; + + memset(&bClpdu_fix, 0, sizeof(CLPDU_FIX)); + memset(&bClpdu_varr, 0, sizeof(CLPDU_VARR)); + memset(tmp, 0, sizeof(tmp)); + + switch(link_cmd_idx) + { + case C_RLK_NA_3: // 请求链路状态 + bClpdu_fix.nSTART = 0x10; + bClpdu_fix.nCONTROL = C_RLK_NA_3 | 0x40; + bClpdu_fix.nADDR = bLinkAddr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + + case C_RFB_NA_3: // 复位帧计数位 + bClpdu_fix.nSTART = 0x10; + bClpdu_fix.nCONTROL = C_RFB_NA_3 | 0x40; + bClpdu_fix.nADDR = bLinkAddr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + + case C_RCU_NA_3: // 复位通讯单元 + bClpdu_fix.nSTART = 0x10; + bClpdu_fix.nCONTROL = C_RCU_NA_3 | 0x40; + bClpdu_fix.nADDR = bLinkAddr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + + case C_PL1_NA_3: // 召唤1级用户数据 + bClpdu_fix.nSTART = 0x10; + bClpdu_fix.nCONTROL = C_PL1_NA_3 | 0x50; + bClpdu_fix.nADDR = bLinkAddr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + + case C_PL2_NA_3: // 召唤2级用户数据 + bClpdu_fix.nSTART = 0x10; + bClpdu_fix.nCONTROL = C_PL2_NA_3 | 0x50; + bClpdu_fix.nADDR = bLinkAddr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + + case C_SD1_NA_3: // 传送数据(发送/确认帧) + bClpdu_varr.nSTART1 = 0x68; + bClpdu_varr.nSTART2 = 0x68; + if(len != 0) + { + bClpdu_varr.nLEN1 = (BYTE)(len + 2); + bClpdu_varr.nLEN2 = bClpdu_varr.nLEN1; + } + bClpdu_varr.nCONTROL = C_SD1_NA_3 | 0x50; + bClpdu_varr.nADDR = bLinkAddr; + memcpy(tmp,(char*)&bClpdu_varr,sizeof(bClpdu_varr)); + memcpy(&tmp[6],msg,len); + nCs = CalBuban103Lpc(tmp, bClpdu_varr.nLEN1); + nEnd = 0x16; + tmp[len+6] = nCs; + tmp[len+7] = nEnd; + PutPollCmdToBuf(commid, cmdtype, 0, (char*)tmp, len+8); + break; + case C_SD2_NA_3: // 传送数据(发送/无回答帧) + bClpdu_varr.nSTART1 = 0x68; + bClpdu_varr.nSTART2 = 0x68; + if(len != 0) + { + bClpdu_varr.nLEN1 = (BYTE)(len + 2); + bClpdu_varr.nLEN2 = bClpdu_varr.nLEN1; + } + bClpdu_varr.nCONTROL = C_SD2_NA_3 | 0x40; + bClpdu_varr.nADDR = bLinkAddr; + memcpy(tmp,(char*)&bClpdu_varr,sizeof(bClpdu_varr)); + memcpy(&tmp[6],msg,len); + nCs = CalBuban103Lpc(tmp, bClpdu_varr.nLEN1); + nEnd = 0x16; + tmp[len+6] = nCs; + tmp[len+7] = nEnd; + PutPollCmdToBuf(commid, cmdtype, 0, (char*)tmp, len+8); + break; + default: + break; + } +} + +//************************************************************* +//* 生成时间同步命令 * +//*参数:u_32 commid:RTU端口号 * +//* u_char addr:间隔设备地址 +//************************************************************* +void MakeTimeSyn_CAsdu6(u_32 commid, CMDPARAM *psCmdParam) +{ + CASDU6 bCAsdu6; + DAY_TIME sCurTime; + char szbuf[128]; + + memset(&bCAsdu6,0,sizeof(CASDU6)); + bCAsdu6.nTYP = C_SYN_TA_3; + bCAsdu6.nVSQ = 0x81; + bCAsdu6.nCOT = 8; + bCAsdu6.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu6.nFUN = psCmdParam->m_uchFun; + bCAsdu6.nINF = psCmdParam->m_uchInf; + + GetLocalTimeEx(&sCurTime); + sCurTime.mSec = sCurTime.Sec*1000 + sCurTime.mSec; + bCAsdu6.nTIME[0] = sCurTime.mSec % 256; + bCAsdu6.nTIME[1] = sCurTime.mSec / 256; + bCAsdu6.nTIME[2] = (u_char)sCurTime.Min; + bCAsdu6.nTIME[3] = (u_char)sCurTime.Hour; + //bCAsdu6.nTIME[4] = (u_char)ControlParam->CurTime.wDayOfWeek; + bCAsdu6.nTIME[4] = (u_char)(sCurTime.Day&0x1F); + bCAsdu6.nTIME[5] = (u_char)sCurTime.Month; + bCAsdu6.nTIME[6] = (u_char)(sCurTime.Year%100); + sprintf(szbuf, "对时时间为:%d年%d月%d日%d点%d分%d秒%d毫秒",sCurTime.Year,sCurTime.Month,bCAsdu6.nTIME[4],sCurTime.Hour,sCurTime.Min,sCurTime.Sec,sCurTime.mSec-sCurTime.Sec*1000); + DebugPrint(szbuf); + + if(psCmdParam->m_sDevAddr.m_uchLinkAddr == 255) + { + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD2_NA_3, (u_char*)&bCAsdu6, sizeof(CASDU6), FAST_POLL_CMD); + } + else + { + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD1_NA_3, (u_char*)&bCAsdu6, sizeof(CASDU6), NORMAL_POLL_CMD); + } +} + +//************************************************************* +//* 生成总查询启动命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//************************************************************* +void MakeAllQuery_CAsdu7(u_32 commid, CMDPARAM *psCmdParam) +{ + BYTE u8SCN; + CASDU7 bCAsdu7; + BUBAN103PORTPARAM *pPortParam; + + if(SioParam[commid].ExtInfo == NULL) + { + return; + } + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + memset(&bCAsdu7,0,sizeof(CASDU7)); + bCAsdu7.nTYP = C_TGI_NA_3; + bCAsdu7.nVSQ = 0x81; + bCAsdu7.nCOT = 9; + bCAsdu7.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu7.nFUN = 255; + bCAsdu7.nINF = 0; + //扫描值需核实 + u8SCN = pPortParam->m_psLink[psCmdParam->m_sDevAddr.m_iLinkIdx].m_psDev[psCmdParam->m_sDevAddr.m_iDevIdx].m_sDevParam.m_u8SCN; + bCAsdu7.nSCN = u8SCN; + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr,\ + C_SD1_NA_3 , (unsigned char*)&bCAsdu7, sizeof(CASDU7), NORMAL_POLL_CMD); + + pPortParam->m_psLink[psCmdParam->m_sDevAddr.m_iLinkIdx].m_psDev[psCmdParam->m_sDevAddr.m_iDevIdx].m_bAllQueryOk = FALSE; + pPortParam->m_psLink[psCmdParam->m_sDevAddr.m_iLinkIdx].m_psDev[psCmdParam->m_sDevAddr.m_iDevIdx].m_sDevParam.m_u8SCN = (u8SCN+1) % 256; +} + +//******************************************************************* +//* 生成通用分类数据命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//* u_char inf:信息序号,取值范围只能是248-251,其中: * +//* 248:写条目 * +//* 249:带确认的写条目 * +//* 250:带执行的写条目 * +//* 251:写条目终止 * +//* unsigned char* dataset:通用分类数据集信息 * +//* u_char ngd:通用分类数据集数目(数目、计数器位、后续状态位) * +//******************************************************************* +void MakeGenIdentData_CAsdu10(u_32 commid, CMDPARAM *psCmdParam, + u_char *dataset, u_char ngd) +{ + CASDU10 bCAsdu10; + u_32 len,len1,i,start; + u_char tmp[MAX_POLL_CMD_BUF_LEN]; + + memset(&bCAsdu10,0,sizeof(CASDU10)); + + bCAsdu10.nTYP = C_GD_NA_3; + bCAsdu10.nVSQ = 0x81; + bCAsdu10.nCOT = 40; + bCAsdu10.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu10.nFUN = 254; + if((psCmdParam->m_uchInf >= 248) + && (psCmdParam->m_uchInf <= 251)) + { + bCAsdu10.nINF = psCmdParam->m_uchInf; + } + bCAsdu10.nRII = psCmdParam->m_uchRII; + bCAsdu10.nNGD = ngd; + //计算数据集的长度 + start = 0; + len = 0; + for(i=0; i 0) && (dataset != NULL)) + { + memcpy((void*)&tmp[len1], dataset, len); + } + + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD1_NA_3 , (unsigned char*)tmp, len + len1, NORMAL_POLL_CMD); +} + +//******************************************************************* +//* 生成通用分类数据命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 * +//* u_char inf:信息序号,取值范围只能是248-251,其中: * +//* 248:写条目 * +//* 249:带确认的写条目 * +//* 250:带执行的写条目 * +//* 251:写条目终止 * +//* unsigned char* dataset:通用分类数据集信息 * +//* u_char ngd:通用分类数据集数目(数目、计数器位、后续状态位) * +//* u_32 cmdtype : 指令缓冲区类型 * +//******************************************************************* +void MakeGenIdentData_CAsdu10Ex(u_32 commid, CMDPARAM *psCmdParam, + u_char *dataset, u_char ngd, u_32 cmdtype) +{ + CASDU10 bCAsdu10; + u_32 len,len1,i,start; + u_char tmp[MAX_POLL_CMD_BUF_LEN]; + + memset(&bCAsdu10,0,sizeof(CASDU10)); + + bCAsdu10.nTYP = C_GD_NA_3; + bCAsdu10.nVSQ = 0x81; + bCAsdu10.nCOT = 40; + bCAsdu10.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu10.nFUN = 254; + if((psCmdParam->m_uchInf >= 248) + && (psCmdParam->m_uchInf <= 251)) + { + bCAsdu10.nINF = psCmdParam->m_uchInf; + } + bCAsdu10.nRII = psCmdParam->m_uchRII; + bCAsdu10.nNGD = ngd; + //计算数据集的长度 + start = 0; + len = 0; + for(i=0; i 0) && (dataset != NULL)) + { + memcpy((void*)&tmp[len1], dataset, len); + } + + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD1_NA_3 , (unsigned char*)tmp, len + len1, cmdtype); +} + +//************************************************************* +//* 生成一般命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//* u_char inf:信息序号,取值范围为16--26 ,包括: * +//* 16=自动重合闸投入/退出(ON/OFF) * +//* 17=远方保护投入/退出(ON/OF) * +//* 18=保护投入/退出(ON/OF) * +//* 19=LED复位 * +//* 23=激活特性1 * +//* 24=激活特性2 * +//* 25=激活特性3 * +//* 26=激活特性4 * +//* 其它值均为非法 * +//* bool cmd:命令状态(true=合,false=开) * +//************************************************************* + +void MakeGenCommand_CAsdu20(u_32 commid, CMDPARAM *psCmdParam, bool cmd) +{ + CASDU20 bCAsdu20; + + memset(&bCAsdu20,0,sizeof(CASDU20)); + + bCAsdu20.nTYP = C_GRC_NA_3; + bCAsdu20.nVSQ = 0x81; + bCAsdu20.nCOT = 20; + bCAsdu20.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu20.nFUN = 128;//需要验证确认 + bCAsdu20.nINF = psCmdParam->m_uchInf; + bCAsdu20.nRII = psCmdParam->m_uchRII; + if(cmd) + { + bCAsdu20.nDCO = 0x02; + } + else + { + bCAsdu20.nDCO = 0x01; + } + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD1_NA_3 , (u_char *)&bCAsdu20, sizeof(CASDU20), NORMAL_POLL_CMD); +} + +//****************************************************************** +//* 生成通用分类命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//* u_char inf:信息序号,取值范围只能是240-245,其中: * +//* 240:读全部被定义的组的标题 * +//* 241:读一个组的全部条目的值或属性 * +//* 242:未用 * +//* 243:读单个条目的目录 * +//* 244:读单个条目的值或属性 * +//* 245:对通用分类数据的总查询(总召唤) * +//* GEN_DATAGROUP* datagroup:通用分类数据组信息 * +//* u_char nog:通用分类标示数目 * +//****************************************************************** +void MakeGenIdentCommand_CAsdu21(u_32 commid, CMDPARAM *psCmdParam, + GEN_DATAGROUP* datagroup ,u_char nog) +{ + CASDU21 bCAsdu21; + u_32 len; + u_char tmp[MAX_POLL_CMD_BUF_LEN]; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + memset(&bCAsdu21, 0, sizeof(CASDU21)); + + bCAsdu21.nTYP = C_GC_NA_3; + bCAsdu21.nVSQ = 0x81; + + if(psCmdParam->m_uchInf == C_INF_QUERYGENERAL) + { + bCAsdu21.nCOT = C_CAUSE_QUERY; + } + else // 通用分类读命令 + { + bCAsdu21.nCOT = C_CAUSE_READWITHVALIDDATA; + } + + bCAsdu21.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu21.nFUN = FUNC_GENERALSORT; + if((psCmdParam->m_uchInf >= C_INF_READGROUPTITLE) + && (psCmdParam->m_uchInf <= C_INF_QUERYGENERAL)) + { + bCAsdu21.nINF = psCmdParam->m_uchInf; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d生成通用分类命令时,INF=%d不在指定的范围内!!!", + commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, psCmdParam->m_sDevAddr.m_uchCommAddr, psCmdParam->m_uchInf); + DebugPrint(szbuf); +#endif + return; + } + bCAsdu21.nRII = psCmdParam->m_uchRII; + bCAsdu21.nNOG = nog; + len = sizeof(CASDU21)-sizeof(GEN_DATAGROUP *); + memcpy((void *)tmp, (void *)&bCAsdu21, len); + if(nog ==0) + { + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr,\ + C_SD1_NA_3, tmp, len, NORMAL_POLL_CMD); + } + else + { + memcpy((void*)&tmp[len], datagroup, sizeof(GEN_DATAGROUP)*nog); + len += sizeof(GEN_DATAGROUP)*nog; + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr,\ + C_SD1_NA_3 , tmp, len, NORMAL_POLL_CMD); + } +} + +//************************************************************* +//* 生成扰动数据传输命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//* u_char too:命令类型,数值范围为1--255,包括: +//* 1=故障的选择 +//* 2=请求扰动数据 +//* 3=中止扰动数据 +//* 4--7 = 备用 +//* 8=通道的请求 +//* 9=通道的中止 +//* 10--15 = 备用 +//* 16=请求带标志的状态变位 +//* 17=中止带标志的状态变位 +//* 18--23 = 备用 +//* 24=请求被记录扰动表 +//* 25--31 =备用 +//* 32=不带中止的扰动数据传输的结束 +//* 33=由控制系统所中止的扰动数据传输的结束 +//* 34=由继电保护设备(或间隔单元)所中止的扰动数据传输的结束 +//* 35=不带中止的通道传输的结束 +//* 36=由控制系统所中止的通道传输的结束 +//* 37=由继电保护设备(或间隔单元)所中止饿通道传输的结束 +//* 38=不带中止的带标志的状态变位的传输结束 +//* 39=由控制系统所中止的带标志的状态变位的传输的结束 +//* 40=由继电保护设备(或间隔单元)所中止的带标志的状态变位传输的结束 +//* 41--63=备用 +//* 64=成功地扰动数据传输(肯定) +//* 65=不成功地扰动数据传输(否定) +//* 66=成功地通道传输(肯定) +//* 67=不成功地通道传输(否定) +//* 68=成功地带标志的状态变位传输(肯定) +//* 69=不成功地带标志的状态变位传输(否定) +//* 70--255=备用 +//* u_char tov:扰动值的类型 +//* u_short fan:故障序号 +//* u_char acc:实际通道序号 +//************************************************************* +void MakeDisTrans_CAsdu24(u_32 commid, CMDPARAM *psCmdParam, + u_char too, u_char tov, u_short fan, u_char acc) +{ + CASDU24 bCAsdu24; + + memset(&bCAsdu24,0,sizeof(CASDU24)); + bCAsdu24.nTYP = C_ODT_NA_3; + bCAsdu24.nVSQ = 0x81; + bCAsdu24.nCOT = 31; + bCAsdu24.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu24.nFUN = psCmdParam->m_uchFun; + bCAsdu24.nTOO = too; + bCAsdu24.nTOV = tov; + bCAsdu24.nFAN = fan; + bCAsdu24.nACC = acc; + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr, \ + C_SD1_NA_3, (u_char *)&bCAsdu24, sizeof(CASDU24), INSERT_POLL_CMD); +} + +//************************************************************* +//* 生成扰动数据传输的认可命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//* u_char too:命令类型,数值范围为1--255,包括: +//* 1=故障的选择 +//* 2=请求扰动数据 +//* 3=中止扰动数据 +//* 4--7 = 备用 +//* 8=通道的请求 +//* 9=通道的中止 +//* 10--15 = 备用 +//* 16=请求带标志的状态变位 +//* 17=中止带标志的状态变位 +//* 18--23 = 备用 +//* 24=请求被记录扰动表 +//* 25--31 =备用 +//* 32=不带中止的扰动数据传输的结束 +//* 33=由控制系统所中止的扰动数据传输的结束 +//* 34=由继电保护设备(或间隔单元)所中止的扰动数据传输的结束 +//* 35=不带中止的通道传输的结束 +//* 36=由控制系统所中止的通道传输的结束 +//* 37=由继电保护设备(或间隔单元)所中止饿通道传输的结束 +//* 38=不带中止的带标志的状态变位的传输结束 +//* 39=由控制系统所中止的带标志的状态变位的传输的结束 +//* 40=由继电保护设备(或间隔单元)所中止的带标志的状态变位传输的结束 +//* 41--63=备用 +//* 64=成功地扰动数据传输(肯定) +//* 65=不成功地扰动数据传输(否定) +//* 66=成功地通道传输(肯定) +//* 67=不成功地通道传输(否定) +//* 68=成功地带标志的状态变位传输(肯定) +//* 69=不成功地带标志的状态变位传输(否定) +//* 70--255=备用 +//* u_char tov:扰动值的类型 +//* u_short fan:故障序号 +//* u_char acc:实际通道序号 +//************************************************************* +void MakeDisTrans_CAsdu25(u_32 commid, CMDPARAM *psCmdParam, + u_char too, u_char tov, u_short fan, u_char acc) +{ + CASDU25 bCAsdu25; + + memset(&bCAsdu25,0,sizeof(CASDU25)); + bCAsdu25.nTYP = C_ADT_NA_3; + bCAsdu25.nVSQ = 0x81; + bCAsdu25.nCOT = 31; + bCAsdu25.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + bCAsdu25.nFUN = psCmdParam->m_uchFun; + bCAsdu25.nTOO = too; + bCAsdu25.nTOV = tov; + bCAsdu25.nFAN = fan; + bCAsdu25.nACC = acc; + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr,\ + C_SD1_NA_3, (unsigned char*)&bCAsdu25, sizeof(CASDU25), INSERT_POLL_CMD); +} + +//************************************************************* +//* 生成脉冲电度的查询命令 * +//*参数:u_32 commid:RTU端口号 * +//*参数:u_char addr:间隔设备地址 +//************************************************************* +void MakeQCC_CAsdu88(u_32 commid, CMDPARAM *psCmdParam) +{ + CASDU88 bCAsdu88; + + memset(&bCAsdu88,0,sizeof(CASDU88)); + bCAsdu88.nTYP = C_CI_NA_3; + bCAsdu88.nVSQ = 0x81; + bCAsdu88.nCOT = C_CAUSE_CYCLE; + bCAsdu88.nADDR = psCmdParam->m_sDevAddr.m_uchCommAddr; + // ??? wen 2003.11.03 bu(1)---bu(6) + bCAsdu88.nFUN = 1;// BU(1) + bCAsdu88.nINF = 0; + // 使用冻结不复位命令yizhonghu 20060803 + //bCAsdu88.nQCC = 5; + bCAsdu88.nQCC = 45; + bCAsdu88.nRII = psCmdParam->m_uchRII; + MakeBuban103LinkCommand(commid, psCmdParam->m_sDevAddr.m_uchLinkAddr,\ + C_SD2_NA_3 , (unsigned char*)&bCAsdu88, sizeof(CASDU88), NORMAL_POLL_CMD); +} + +void MakeBuban103_PL1_NA_3_Cmd(int commid, DEVADDRPARAM *psAddrParam) +{ + BUBAN103PORTPARAM *pPortParam; + BUBAN103LINKDEF *pLinkParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + + pLinkParam = (BUBAN103LINKDEF *)&pPortParam->m_psLink[psAddrParam->m_iLinkIdx]; + + // 多个保护设备装置 + if(pLinkParam->m_iDevNum > 1) + { + if(pLinkParam->m_iQueryedAddr_CLASS1 != (psAddrParam->m_iDevIdx+1)) + { + pLinkParam->m_iQueryedAddr_CLASS1 = psAddrParam->m_iDevIdx+1; + pLinkParam->m_iQueryNum_CLASS1_Count = 1; + MakeBuban103LinkCommand(commid, psAddrParam->m_uchLinkAddr,\ + C_PL1_NA_3, NULL, 0, INSERT_POLL_CMD); + } + // 如果一条链路含有多个装置的情况 + else if(pLinkParam->m_uchLinkAddr != 0xFF) + { + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + MakeBuban103LinkCommand(commid,\ + psAddrParam->m_uchLinkAddr,\ + C_PL1_NA_3,NULL,0,INSERT_POLL_CMD); + } + else + { + if(pLinkParam->m_iQueryNum_CLASS1_Count < pLinkParam->m_iQueryNum_CLASS1_Const) + { + pLinkParam->m_iQueryNum_CLASS1_Count++; + MakeBuban103LinkCommand(commid, psAddrParam->m_uchLinkAddr,\ + C_PL1_NA_3,NULL,0,INSERT_POLL_CMD); + } + else + { + pLinkParam->m_iQueryedAddr_CLASS1 = 0; + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + } + } + } + else + { + MakeBuban103LinkCommand(commid, psAddrParam->m_uchLinkAddr,\ + C_PL1_NA_3,NULL,0,INSERT_POLL_CMD); + } +} + +BOOL IsDevLinkOk(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + return psLinkParam->m_pbLinkOk[iDevNo]; + } + else + { + return psLinkParam->m_pbLinkOk[0]; + } +} + +void SetDevLinkOk(BUBAN103LINKDEF *psLinkParam, int iDevNo, BOOL bFlagOk) +{ + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + psLinkParam->m_pbLinkOk[iDevNo] = bFlagOk; + psLinkParam->m_pu32LinkOkCnt[iDevNo] = 0; + } + else + { + psLinkParam->m_pbLinkOk[0] = bFlagOk; + psLinkParam->m_pu32LinkOkCnt[0] = 0; + } +} + +void ClearLinkCnt(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + psLinkParam->m_pu32LinkOkCnt[iDevNo] = 0; + } + else + { + psLinkParam->m_pu32LinkOkCnt[0] = 0; + } +} + +BYTE GetLinkAddr(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + return psLinkParam->m_psDev[iDevNo].m_sDevParam.m_u8DevAddr; + } + else + { + return psLinkParam->m_uchLinkAddr; + } +} + +BYTE *GetLinkCtrl(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + if(psLinkParam->m_uchLinkAddr == 0xFF) + { + return &psLinkParam->m_pu8CtlByte[iDevNo]; + } + else + { + return &psLinkParam->m_pu8CtlByte[0]; + } +} + +BOOL IsLinkTimeOut(BUBAN103LINKDEF *psLinkParam, int iDevNo) +{ + int iNo; + + iNo = iDevNo; + psLinkParam->m_pu32LinkOkCnt[iNo]++; + if(psLinkParam->m_pu32LinkOkCnt[iNo]\ + >= psLinkParam->m_u32TimeOutConst) + { + return TRUE; + } + + return FALSE; +} + +//*************************************************************** +//* 指令发送 * +//*参数:u_32 commid : RTU端口号 * +//* i_32 iBuIdx : 间隔装置索引 * +//*************************************************************** +void Buban103SendCmdFormPollCmdBuf(int commid) +{ + BYTE fcb = 0x20; + BYTE *pu8CtrlByte, buf[256]; + i_32 len; + DAY_TIME sDateTime; + DEVADDRPARAM DevAddrParam; + BUBAN103PORTPARAM *pPortParam; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->m_psBaoHu->ForceWaitFlag + && pPortParam->m_psBaoHu->ForceWaitCnt) + { + pPortParam->m_psBaoHu->ForceWaitCnt--; + if(pPortParam->m_psBaoHu->ForceWaitCnt == 0) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + } + } + if(pPortParam->m_psBaoHu->SendCmdFlag + && (pPortParam->m_psBaoHu->RevCmdFlag == 0)) + { + pPortParam->m_psBaoHu->RetryTimeCnt++; + if(pPortParam->m_psBaoHu->RetryTimeCnt + < pPortParam->m_psBaoHu->RetryTime) + { + return; + } + pPortParam->m_psBaoHu->RetryTimeCnt = 0; + + pPortParam->m_psBaoHu->RetryCnt++; + if(pPortParam->m_psBaoHu->RetryCnt + > pPortParam->m_psBaoHu->Retry) + { + len = ReGetCmdFormPollCmdBuf(commid, buf, MAX_MSG_BUF_SIZE); + if(buf[2] == 0x10) + { + DevAddrParam.m_uchLinkAddr = buf[4]; + if(FindProtectDev(pPortParam, &DevAddrParam, TRUE) == TRUE) + { + if(pPortParam->m_psLink[DevAddrParam.m_iLinkIdx].m_uchLinkAddr != 0xFF) + { + InitBuban103LinkCmdBuf(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx]); + } + else + { + DevAddrParam.m_uchCommAddr = buf[4]; + InitBuban103DevCmdBuf(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + } + } + } + else if(buf[2] == 0x68) + { + DevAddrParam.m_uchLinkAddr = buf[7]; + DevAddrParam.m_uchCommAddr = buf[11]; + if(FindProtectDev(pPortParam, &DevAddrParam, FALSE) == TRUE) + { + InitBuban103DevCmdBuf(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + } + } + else + { + pPortParam->m_psBaoHu->RevCmdFlag = 1; + } + + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + } + else + { + pPortParam->m_psBaoHu->SendCmdFlag = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 0; + pPortParam->m_psBaoHu->ReSendCmdFlag = 1; + } + } + + if(pPortParam->m_psBaoHu->SendCmdFlag + && pPortParam->m_psBaoHu->RevCmdFlag) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + } + + if(pPortParam->m_psBaoHu->WaitTime) + { + pPortParam->m_psBaoHu->WaitTimeCnt++; + if(pPortParam->m_psBaoHu->WaitTimeCnt + < pPortParam->m_psBaoHu->WaitTime) + { + return; + } + } + pPortParam->m_psBaoHu->WaitTimeCnt = 0; + + if(pPortParam->m_psBaoHu->ReSendCmdFlag) + { + len = ReGetCmdFormPollCmdBuf(commid, buf, MAX_MSG_BUF_SIZE); + } + else + { + len = GetCmdFormPollCmdBuf(commid, buf, MAX_MSG_BUF_SIZE); + } + + if(len < 7) + { + return; + } + +#ifndef OS_LINUX + if(isUdpSocketExist() == TRUE) +#endif + { + if(buf[2] == 0x10) + { + DevAddrParam.m_uchLinkAddr = buf[4]; + if(FindProtectDev(pPortParam, &DevAddrParam, TRUE) == FALSE) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + return; + } + + if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) + { + if(pPortParam->m_psBaoHu->ReSendCmdFlag) + { + pu8CtrlByte = GetLinkCtrl(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + *pu8CtrlByte = ~(*pu8CtrlByte); + } + pu8CtrlByte = GetLinkCtrl(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + + buf[3] |= (fcb & *pu8CtrlByte); + *pu8CtrlByte = ~(*pu8CtrlByte); + } + else + { + if(ProvHaveClassOne(commid, &DevAddrParam, pPortParam->m_bSendChangeDi) == TRUE) + { + buf[3] |= 0x20; + } + } + buf[5] = CalBuban103Lpc(&buf[3], 2); + } + else if(buf[2] == 0x68) + { + DevAddrParam.m_uchLinkAddr = buf[7]; + DevAddrParam.m_uchCommAddr = buf[11]; + if(0xFF != DevAddrParam.m_uchLinkAddr) + { + if(FindProtectDev(pPortParam, &DevAddrParam, FALSE) == FALSE) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + return; + } + + if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) + { + if(pPortParam->m_psBaoHu->ReSendCmdFlag) + { + pu8CtrlByte = GetLinkCtrl(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + *pu8CtrlByte = ~(*pu8CtrlByte); + } + pu8CtrlByte = GetLinkCtrl(&pPortParam->m_psLink[DevAddrParam.m_iLinkIdx], DevAddrParam.m_iDevIdx); + + buf[6] |= (fcb & *pu8CtrlByte); + + //if(buf[7] != 0xFF) + //{ + // *pu8CtrlByte = ~(*pu8CtrlByte); + //} + *pu8CtrlByte = ~(*pu8CtrlByte); + } + else + { + if(ProvHaveClassOne(commid, &DevAddrParam, pPortParam->m_bSendChangeDi) == TRUE) + { + buf[6] |= 0x20; + } + } + } + + if((buf[8] == C_SYN_TA_3) && (buf[3] == 15)) + { + GetLocalTimeEx(&sDateTime); + sDateTime.mSec = sDateTime.Sec*1000 + sDateTime.mSec; + buf[14] = sDateTime.mSec % 256; + buf[15] = sDateTime.mSec / 256; + buf[16] = (u_char)sDateTime.Min; + buf[17] = (u_char)sDateTime.Hour; + buf[18] = (u_char)(sDateTime.Day&0x1F); + buf[19] = (u_char)sDateTime.Month; + buf[20] = (u_char)(sDateTime.Year%100); + } + buf[buf[3]+6] = CalBuban103Lpc(&buf[6], buf[3]); + } + else + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + return; + } + + SendDataToPort(commid, (char *)&buf[2], len-2); + + pPortParam->m_psBaoHu->SendCmdFlag = 1; + pPortParam->m_psBaoHu->ReSendCmdFlag = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 0; + } + +#ifdef OS_LINUX + if(pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE) +#else + if((pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE) + || !isUdpSocketExist()) +#endif + { + pPortParam->m_psBaoHu->ForceWaitCnt = BYTE1(buf[0])+BYTE0(buf[1])+TIMER_CNT-1; + pPortParam->m_psBaoHu->ForceWaitCnt /= TIMER_CNT; + if(pPortParam->m_psBaoHu->ForceWaitCnt) + { + pPortParam->m_psBaoHu->ForceWaitFlag = 1; + } + else + { + ClearCmdFormPollCmdBuf(commid); // 清除当前命令 + //ClearCmdAllFlag(commid); // 清除当前命令 + } + } +} + +/*! + \brief 寻找并生成下一条命令 + \param u_32 portno : RTU端口号 + \param i_32 iBuIdx : 间隔装置索引 +*/ +void Buban103FindNextCmd(int commid) +{ + int i, j, iCurCmdIdx; + BYTE *pu8CtrlByte; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + + //所有的命令定时计数器+1 + for(i=0; im_iLinkNum; i++) + { + pLinkParam = &pPortParam->m_psLink[i]; + for(j=0; jm_sArrayCmdTime[j].m_iCmdTimerConst > 0) + { + pLinkParam->m_sArrayCmdTime[j].m_iCmdTimerCnt++; + } + } + } + + //如果命令缓冲区仍有命令,则退出本函数 + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + //每个地址下发一次命令,循环进行 + if(pLinkParam->m_iDevIdx >= pLinkParam->m_iDevNum-1) + { + pLinkParam->m_iDevIdx = 0; + pPortParam->m_iLinkIdx = (pPortParam->m_iLinkIdx+1) % pPortParam->m_iLinkNum; + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + pLinkParam->m_iDevIdx = 0; + } + else + { + pLinkParam->m_iDevIdx++; + } + + //判断链路的状态,如果链路服务未工作或链路服务未实现,则发送请求链路状态命令继续查询链路状态,并退出本函数 + // 如果链路工作正常,则继续本函数的后续工作 + pDevParam = &pLinkParam->m_psDev[pLinkParam->m_iDevIdx]; + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == FALSE) + { + // 一条链路一次循环只进行一次链路复位 + if((pLinkParam->m_uchLinkAddr != 0xFF) + && (pLinkParam->m_iDevIdx != 0)) + { + pLinkParam->m_iDevIdx = pLinkParam->m_iDevNum - 1; + return; + } + pu8CtrlByte = GetLinkCtrl(pLinkParam, pLinkParam->m_iDevIdx); + *pu8CtrlByte = 0; + MakeBuban103LinkCommand(commid, + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx), + C_RCU_NA_3, NULL, 0, NORMAL_POLL_CMD); + return; + } + + //如果发送了保护程序传送过来的命令,且仍未收到结束帧,则继续召唤二级用户数据 + if(pDevParam->m_bInitdata == TRUE) + { + pDevParam->m_u32CallCnt++; + if(pDevParam->m_u32CallCnt < pLinkParam->m_u32TimeOutConst) + { + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + { + MakeBuban103LinkCommand(commid,\ + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx),\ + C_PL2_NA_3, NULL, 0, NORMAL_POLL_CMD); + return; + } + } + else + { + pDevParam->m_u32CallCnt = 0; + pDevParam->m_bInitdata = FALSE; + } + } + + //判断有否保护程序传来的命令 + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + { + // wen 2004.02.11 修改保护数据下发(暂时没有下发) + //seladdr = (u_char)(*(WORD*)&gBuban103_RtuMsg.MsgData[0]); + //if((gBuban103_RtuMsg.MsgLen > 0) && (gBuban103_RtuMsg.PortNumber == commid)) + //{ + // itmpBuIdx = FindMatchingBuIdx(commid, seladdr); + // if(itmpBuIdx >= 0) + // { + // MakeBuban103BaohuCommand(); + // Buban103PortParam[commid][selidx][iBuIdx].CallCnt = 0; + // Buban103PortParam[commid][selidx][iBuIdx].RstLinkOk = true; + // memset((char*)&gBuban103_RtuMsg, 0, sizeof(gBuban103_RtuMsg)); + // return; + // } + //} + } + + iCurCmdIdx = pLinkParam->m_shCurCmdIdx; + if(pDevParam->m_bAllQueryOk == TRUE) + { + for(i=0; im_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerConst > 0) + { + if(pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerCnt\ + > pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerConst) + { + break; + } + } + iCurCmdIdx = (iCurCmdIdx+1) % BUBAN103_TIMER_CMD_NUM; + } + + pLinkParam->m_shCurCmdIdx = iCurCmdIdx; + if(i >= BUBAN103_TIMER_CMD_NUM) + { + pPortParam->m_iLinkIdx = (pPortParam->m_iLinkIdx+1) % pPortParam->m_iLinkNum; + } + else + { + MakeBuban103PollingCmd(commid, pLinkParam, iCurCmdIdx); + + pLinkParam->m_iDevIdx = (pLinkParam->m_iDevIdx+1) % pLinkParam->m_iDevNum; + if(pLinkParam->m_iDevIdx == 0) + { + pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerCnt = 0; + pLinkParam->m_shCurCmdIdx = (pLinkParam->m_shCurCmdIdx+1) % BUBAN103_TIMER_CMD_NUM; + pPortParam->m_iLinkIdx = (pPortParam->m_iLinkIdx+1) % pPortParam->m_iLinkNum; + } + } + } + + //空闲时间不停地召唤二级数据 + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + { + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + MakeBuban103LinkCommand(commid,\ + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx),\ + C_PL2_NA_3, NULL, 0, NORMAL_POLL_CMD); + } +} + +BOOL Buban103FindNextCmdEx(int commid) +{ + int i, j, iCurCmdIdx; + BYTE *pu8CtrlByte; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + //char szbuf[128]; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return FALSE; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return FALSE; + } + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + + /* + char szbuf[256]; + FILE *fp; + DAY_TIME sTime; + fp = NULL; + if(commid == 6) + { + getcwd(szbuf, sizeof(szbuf)); + sprintf(szbuf, "%s/log/cmdtime.txt", szbuf); + fp = fopen(szbuf, "a"); + GetLocalTimeEx(&sTime); + sprintf(szbuf, "wen: %02d:%02d:%02d.%03d, commid=%d calc pollcmd count.\n", sTime.Hour, sTime.Min, sTime.Sec, sTime.mSec, commid); + //DebugPrint(szbuf); + if(fp) + fwrite(szbuf, 1, strlen(szbuf), fp); + } + */ + + //所有的命令定时计数器+1 + for(i=0; im_iLinkNum; i++) + { + pLinkParam = &pPortParam->m_psLink[i]; + + if(!IsDevLinkOk(pLinkParam, i)) + { + continue; + } + + for(j=0; jm_sArrayCmdTime[j].m_iCmdTimerConst > 0) + { + pLinkParam->m_sArrayCmdTime[j].m_iCmdTimerCnt++; + } + } + } + + //如果命令缓冲区仍有命令,则退出本函数 + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return FALSE; + } + + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[pLinkParam->m_iDevIdx]; + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == FALSE) + { + // 一条链路一次循环只进行一次链路复位 + if((pLinkParam->m_uchLinkAddr != 0xFF)\ + && (pLinkParam->m_iDevIdx != 0)) + { + pLinkParam->m_iDevIdx = pLinkParam->m_iDevNum - 1; + return TRUE; + } + pu8CtrlByte = GetLinkCtrl(pLinkParam, pLinkParam->m_iDevIdx); + *pu8CtrlByte = 0; + MakeBuban103LinkCommand(commid, + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx), + C_RCU_NA_3, NULL, 0, NORMAL_POLL_CMD); + return TRUE; + } + + //如果发送了保护程序传送过来的命令,且仍未收到结束帧,则继续召唤二级用户数据 + if(pDevParam->m_bInitdata == TRUE) + { + pDevParam->m_u32CallCnt++; + if(pDevParam->m_u32CallCnt < pLinkParam->m_u32TimeOutConst) + { + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + { + MakeBuban103LinkCommand(commid,\ + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx),\ + C_PL2_NA_3, NULL, 0, NORMAL_POLL_CMD); + return TRUE; + } + } + else + { + pDevParam->m_u32CallCnt = 0; + pDevParam->m_bInitdata = FALSE; + } + } + + //判断有否保护程序传来的命令 + if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + { + // wen 2004.02.11 修改保护数据下发(暂时没有下发) + //seladdr = (u_char)(*(WORD*)&gBuban103_RtuMsg.MsgData[0]); + //if((gBuban103_RtuMsg.MsgLen > 0) && (gBuban103_RtuMsg.PortNumber == commid)) + //{ + // itmpBuIdx = FindMatchingBuIdx(commid, seladdr); + // if(itmpBuIdx >= 0) + // { + // MakeBuban103BaohuCommand(); + // Buban103PortParam[commid][selidx][iBuIdx].CallCnt = 0; + // Buban103PortParam[commid][selidx][iBuIdx].RstLinkOk = true; + // memset((char*)&gBuban103_RtuMsg, 0, sizeof(gBuban103_RtuMsg)); + // return; + // } + //} + } + + if(pLinkParam->m_shCurCmdIdx < BUBAN103_TIMER_CMD_NUM) + { + iCurCmdIdx = pLinkParam->m_shCurCmdIdx; + } + else + { + iCurCmdIdx = 0; + } + + if(pDevParam->m_bAllQueryOk == TRUE) + { + for(i=0; i= BUBAN103_TIMER_CMD_NUM) + { + break; + } + if(pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerConst > 0) + { + if(pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerCnt\ + > pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerConst) + { + break; + } + } + iCurCmdIdx++; + } + + // 如果是一条新的轮询指令,则从第一个装置开始生成指令 + if(pLinkParam->m_shCurCmdIdx != iCurCmdIdx) + { + pLinkParam->m_iDevIdx = 0; + pLinkParam->m_shCurCmdIdx = iCurCmdIdx; + } + + if(iCurCmdIdx < BUBAN103_TIMER_CMD_NUM) + { + //if(iCurCmdIdx == 0) + //{ + // sprintf(szbuf, "%d端口时间同步过程=%d,计数=%d",commid+1,pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerConst,\ + // pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerCnt); + // DebugPrint(szbuf); + // } + MakeBuban103PollingCmd(commid, pLinkParam, iCurCmdIdx); + if(pLinkParam->m_iDevIdx >= (pLinkParam->m_iDevNum-1)) + { + pLinkParam->m_sArrayCmdTime[iCurCmdIdx].m_iCmdTimerCnt = 0; + } + return TRUE; + } + } + + //空闲时间不停地召唤二级数据 + //if(IsDevLinkOk(pLinkParam, pLinkParam->m_iDevIdx) == TRUE) + //{ + //if(CheckPollCmdBufEmpty(commid) <= 0) + //{ + // return; + //} + + // MakeBuban103LinkCommand(commid,\ + // GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx),\ + // C_PL2_NA_3, NULL, 0, NORMAL_POLL_CMD); + + // return TRUE; + //} + MakeBuban103LinkCommand(commid,\ + GetLinkAddr(pLinkParam, pLinkParam->m_iDevIdx),\ + C_PL2_NA_3, NULL, 0, NORMAL_POLL_CMD); + return TRUE; +} + +void Buban103CalcNextDev(int commid, BOOL bFlag) +{ + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + //printf("Buban103CalcNextDev: commid_%d\n", commid); + if(FALSE == GetPortParamPtr(commid, &pPortParam)) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + //printf("Buban103CalcNextDev: LinkIdx=%d, LinkNum=%d\n", pPortParam->m_iLinkIdx, pPortParam->m_iLinkNum); + //return; + + if(pPortParam->m_iLinkIdx >= pPortParam->m_iLinkNum) + { + pPortParam->m_iLinkIdx = 0; + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + pLinkParam->m_iDevIdx = 0; + } + else + { + // 常规的下一个装置计算 + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + if(FALSE == bFlag) + { + if((pLinkParam->m_uchLinkAddr != 0xFF)\ + && (pLinkParam->m_iDevNum > 1)) + { + pDevParam = &pLinkParam->m_psDev[pLinkParam->m_iDevIdx]; + if(pDevParam->m_bAllQueryOk == FALSE) + { + pLinkParam->m_bGotoNext = TRUE; + return; + } + // else if(增加其他的多帧传输不进行装置切换的判断) + } + } + // 在一个装置总召唤完成以后的计算 + else + { + pDevParam = &pLinkParam->m_psDev[pLinkParam->m_iDevIdx]; + if(pLinkParam->m_bGotoNext == FALSE) + { + return; + } + if(pDevParam->m_bAllQueryOk == TRUE) + { + return; + } + // else if(增加其他的多帧传输不进行装置切换的判断) + } + + pLinkParam->m_bGotoNext = FALSE; + pLinkParam->m_iDevIdx++; + if(pLinkParam->m_iDevIdx >= pLinkParam->m_iDevNum) + { + pLinkParam->m_iDevIdx = 0; + pPortParam->m_iLinkIdx = (pPortParam->m_iLinkIdx+1) % pPortParam->m_iLinkNum; + pLinkParam = &pPortParam->m_psLink[pPortParam->m_iLinkIdx]; + pLinkParam->m_iDevIdx = 0; + } + } +} + +//***************************************************************************/ +//* 定时轮询标准103指令生成函数 */ +//*参数:u_32 commid : 厂站端口号 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//* i_32 CmdIdx : 指令生成码索引号 */ +//*返回值:BOOL retval : 指令生成成功标识 */ +//***************************************************************************/ +void MakeBuban103PollingCmd(int commid, BUBAN103LINKDEF *psLinkParam, i_32 CmdIdx) +{ + i_32 i; + DEVDEF *pDevParam; + CMDPARAM CmdParam; + GEN_DATAGROUP sGenDataGroup; +//#ifdef _DEBUG_MSG_ + char szbuf[256]; +//#endif + + pDevParam = &psLinkParam->m_psDev[psLinkParam->m_iDevIdx]; + switch(CmdIdx) + { + case 0:// 时间同步 + // 广播对时仅执行一次 + sprintf(szbuf, "port=%d,广播对时命令下发",commid+1); + DebugPrint(szbuf); + psLinkParam->m_sArrayCmdTime[CmdIdx].m_iCmdTimerCnt = 0; + CmdParam.m_sDevAddr.m_uchLinkAddr = 0xFF; + CmdParam.m_sDevAddr.m_uchCommAddr = 0xFF; + CmdParam.m_uchFun = (u_char)pDevParam->m_sDevParam.m_sSyncTimeInfo.m_u8Fun; + CmdParam.m_uchInf = (u_char)pDevParam->m_sDevParam.m_sSyncTimeInfo.m_u8Inf; + CmdParam.m_uchRII = pDevParam->m_u8RII; + MakeTimeSyn_CAsdu6(commid, &CmdParam); + // 清除当前指令,指向下一个链路 + psLinkParam->m_iDevIdx = psLinkParam->m_iDevNum - 1; + break; + + case 1:// 总查询 + CmdParam.m_sDevAddr.m_uchLinkAddr = psLinkParam->m_uchLinkAddr; + CmdParam.m_sDevAddr.m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + if(FALSE == FindProtectDev((BUBAN103PORTPARAM *)SioParam[commid].ExtInfo, &CmdParam.m_sDevAddr, FALSE)) + { + break; + } + MakeAllQuery_CAsdu7(commid, &CmdParam); + break; + + case 2:// 电度量查询 + CmdParam.m_sDevAddr.m_uchLinkAddr = psLinkParam->m_uchLinkAddr; + CmdParam.m_sDevAddr.m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + if(FALSE == FindProtectDev((BUBAN103PORTPARAM *)SioParam[commid].ExtInfo, &CmdParam.m_sDevAddr, FALSE)) + { + break; + } + CmdParam.m_uchRII = pDevParam->m_u8RII; + MakeQCC_CAsdu88(commid, &CmdParam); + break; + + case 3:// 模拟量轮询(通用分类数据) + CmdParam.m_sDevAddr.m_uchLinkAddr = psLinkParam->m_uchLinkAddr; + CmdParam.m_sDevAddr.m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + if(FALSE == FindProtectDev((BUBAN103PORTPARAM *)SioParam[commid].ExtInfo, &CmdParam.m_sDevAddr, FALSE)) + { + break; + } + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(AI_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + break; + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不存在通用分类数据模拟量,不能生成轮询指令!!!\n", + commid, CmdParam.m_sDevAddr.m_uchLinkAddr, CmdParam.m_sDevAddr.m_uchCommAddr); + //前置机站号=1 + DebugPrint(szbuf); +#endif + break; + } + CmdParam.m_uchInf = C_INF_READGROUPALLITEMS; + sGenDataGroup.m_u8Grp = (BYTE)pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + sGenDataGroup.m_u8Itm = 0; + sGenDataGroup.m_u8KOD = KOD_ACTUALVALUE; + CmdParam.m_uchRII = pDevParam->m_u8RII; + MakeGenIdentCommand_CAsdu21(commid, &CmdParam, &sGenDataGroup, 1); + break; + + case 4:// 状态量轮询(通用分类数据) + CmdParam.m_sDevAddr.m_uchLinkAddr = psLinkParam->m_uchLinkAddr; + CmdParam.m_sDevAddr.m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + if(FALSE == FindProtectDev((BUBAN103PORTPARAM *)SioParam[commid].ExtInfo, &CmdParam.m_sDevAddr, FALSE)) + { + break; + } + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(DI_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + break; + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不存在通用分类数据开关量,不能生成轮询指令!!!\n", + commid, CmdParam.m_sDevAddr.m_uchLinkAddr, CmdParam.m_sDevAddr.m_uchCommAddr); + DebugPrint(szbuf); +#endif + break; + } + CmdParam.m_uchInf = C_INF_READGROUPALLITEMS; + sGenDataGroup.m_u8Grp = (BYTE)pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + sGenDataGroup.m_u8Itm = 0; + sGenDataGroup.m_u8KOD = KOD_ACTUALVALUE; + CmdParam.m_uchRII = pDevParam->m_u8RII; + MakeGenIdentCommand_CAsdu21(commid, &CmdParam, &sGenDataGroup, 1); + break; + + default: + break; + } +} + +//===========================指令生成函数结束========================= + +//===========================以下为数据处理函数======================= +//*************************************************************** +//* 计算 Buban103 累加和检验码 * +//* 参数:BYTE* msg:准备计算的数据帧信息 * +//* u_32 len:准备计算的数据帧长度 * +//*************************************************************** +BYTE CalBuban103Lpc(BYTE *msg, u_32 len) +{ + u_32 i; + char retval; + + retval = 0; + for(i=0; im_iRecvLen; + memcpy(msg.MsgData, psPortParam->m_achRecvBuf, msg.MsgLen); + msg.MsgData[msg.MsgLen] = CHECK_WHOLE; + msg.MsgData[msg.MsgLen+1] = 0; + + // 子站数据处理 + if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType) + { + ProvRtuProtocolDataProcess(commid, &msg); + return; + } + + // 主站数据处理 + switch(msg.MsgData[0]) + { + case 0x68: + Buban103longprocess(&msg); + break; + case 0x10: + Buban103shortprocess(&msg); + break; + default: + break; + } + } + + // 总召唤完成后指向下一个地址 + Buban103CalcNextDev(commid, TRUE); +} + +BOOL FindProtectDev(BUBAN103PORTPARAM *psPortParam, \ + DEVADDRPARAM *psAddrParam, \ + BOOL bJudgeLinkOnly) +{ + int i, j; + BYTE uchAddr; + BOOL bRetVal; + + bRetVal = FALSE; + for(i=0; im_iLinkNum; i++) + { + if(psPortParam->m_psLink[i].m_uchLinkAddr != 0xFF) + { + if(psPortParam->m_psLink[i].m_uchLinkAddr != psAddrParam->m_uchLinkAddr) + { + continue; + } + uchAddr = psAddrParam->m_uchCommAddr; + + if(bJudgeLinkOnly == TRUE) + { + bRetVal = TRUE; + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_iDevIdx = 0; + break; + } + } + else + { + // 装置地址就是链路地址 + uchAddr = psAddrParam->m_uchLinkAddr; + if(psAddrParam->m_uchLinkAddr == 0xFF) + { + uchAddr = psAddrParam->m_uchCommAddr; + psAddrParam->m_uchLinkAddr = uchAddr; + } + } + + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + if(psPortParam->m_psLink[i].m_psDev != NULL) + { + if(psPortParam->m_psLink[i].m_psDev[j].m_sDevParam.m_u8DevAddr == uchAddr) + { + break; + } + } + else if(psPortParam->m_psLink[i].m_psProvDev != NULL) + { + if(psPortParam->m_psLink[i].m_psProvDev[j].m_iProvAddr == (int)uchAddr) + { + break; + } + } + } + + if(j < psPortParam->m_psLink[i].m_iDevNum) + { + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_iDevIdx = j; + bRetVal = TRUE; + break; + } + } + + return bRetVal; +} + +BOOL FindProtectDevFromProvAddr(BUBAN103PORTPARAM *psPortParam, \ + DEVADDRPARAM *psAddrParam, \ + int iProvAddr) +{ + int i, j; + BOOL bRetVal; + DEVDEF *pDevParam; + PROVDEVDEF *pProvDevParam; + + bRetVal = FALSE; + for(i=0; im_iLinkNum; i++) + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + if(psPortParam->m_psLink[i].m_psDev != NULL) + { + pDevParam = &psPortParam->m_psLink[i].m_psDev[j]; + if(iProvAddr == pDevParam->m_sDevParam.m_iProvAddr) + { + psAddrParam->m_iDevIdx = j; + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_uchLinkAddr = psPortParam->m_psLink[i].m_uchLinkAddr; + psAddrParam->m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + bRetVal = TRUE; + break; + } + } + else if(psPortParam->m_psLink[i].m_psProvDev != NULL) + { + pProvDevParam = &psPortParam->m_psLink[i].m_psProvDev[j]; + if(iProvAddr == pProvDevParam->m_iProvAddr) + { + psAddrParam->m_iDevIdx = j; + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_uchLinkAddr = 0; + psAddrParam->m_uchCommAddr = 0; + bRetVal = TRUE; + break; + } + } + else + { + return FALSE; + } + } + + if(bRetVal == TRUE) + { + break; + } + } + + return bRetVal; +} + +BOOL FindProtectDevFromPntNo(BUBAN103PORTPARAM *psPortParam, \ + DEVADDRPARAM *psAddrParam, \ + DBINFO *psDBInfo,\ + int iPntNo, int itype) +{ + int i, j, inum, ipnt; + BOOL bRetVal, bProv; + DEVDEF *pDevParam=NULL; + PROVDEVDEF *pProvDevParam=NULL; + DBORIENTATION *pDataUnit=NULL; + + bRetVal = FALSE; + if(psPortParam->m_psLink[0].m_psDev != NULL) + { + pProvDevParam = NULL; + bProv = FALSE; + } + else if(psPortParam->m_psLink[0].m_psProvDev != NULL) + { + pDevParam = NULL; + bProv = TRUE; + } + else + { + return FALSE; + } + + for(i=0; im_iLinkNum; i++) + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + if(bProv == FALSE) + { + pDevParam = &psPortParam->m_psLink[i].m_psDev[j]; + switch(itype) + { + case AI_PNT_TYPE: + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[0]; + break; + case DI_PNT_TYPE: + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + break; + case PI_PNT_TYPE: + pDataUnit = &pDevParam->m_sDevParam.m_sPiDBOrientation; + break; + default: + pDataUnit = NULL; + break; + } + } + else + { + pProvDevParam = &psPortParam->m_psLink[i].m_psProvDev[j]; + switch(itype) + { + case DI_PNT_TYPE: + pDataUnit = &pProvDevParam->m_sYxInfo; + break; + case AI_PNT_TYPE: + case PI_PNT_TYPE: + default: + pDataUnit = NULL; + break; + } + } + + if(pDataUnit == NULL) + { + continue; + } + + if(AI_PNT_TYPE == itype) + { + for(inum=0; inum= 0) && (ipnt < pDataUnit[inum].m_iPntNum)) + { + pDataUnit = &pDataUnit[inum]; + bRetVal = TRUE; + break; + } + } + } + else + { + if(pDataUnit->m_iPntNum <= 0) + { + break; + } + + ipnt = iPntNo - pDataUnit->m_iStartPntNo; + if((ipnt >= 0) && (ipnt < pDataUnit->m_iPntNum)) + { + bRetVal = TRUE; + } + } + + if(TRUE == bRetVal) + { + break; + } + } + + if(bRetVal == TRUE) + { + break; + } + } + + if(TRUE == bRetVal) + { + psAddrParam->m_iDevIdx = j; + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_uchLinkAddr = psPortParam->m_psLink[i].m_uchLinkAddr; + + //if(pDevParam != NULL) + //{ + // psAddrParam->m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + //} + //else if(pProvDevParam != NULL) + //{ + // psAddrParam->m_uchCommAddr = (BYTE)pProvDevParam->m_iProvAddr; + //} + //else + //{ + // bRetVal = FALSE; + //} + if(FALSE == bProv) + { + psAddrParam->m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + } + else + { + psAddrParam->m_uchCommAddr = (BYTE)pProvDevParam->m_iProvAddr; + } + if(psDBInfo != NULL) + { + memcpy((void *)psDBInfo, (void *)&pDataUnit->m_psDataInfo[ipnt], sizeof(DBINFO)); + } + } + + return bRetVal; +} + +BOOL FindProtectDevFromYkYtPnt(BUBAN103PORTPARAM *psPortParam, \ + DEVADDRPARAM *psAddrParam, \ + int iYkYtPnt) +{ + int i, j, iYkNo; + BOOL bRetVal; + DEVDEF *pDevParam; + + bRetVal = FALSE; + for(i=0; im_iLinkNum; i++) + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + pDevParam = &psPortParam->m_psLink[i].m_psDev[j]; + if(pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum <= 0) + { + continue; + } + + iYkNo = iYkYtPnt - pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + if(iYkNo < 0) + { + continue; + } + + if(iYkNo < pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum) + { + psAddrParam->m_iDevIdx = j; + psAddrParam->m_iLinkIdx = i; + psAddrParam->m_uchLinkAddr = psPortParam->m_psLink[i].m_uchLinkAddr; + psAddrParam->m_uchCommAddr = pDevParam->m_sDevParam.m_u8DevAddr; + bRetVal = TRUE; + break; + } + } + + if(bRetVal == TRUE) + { + break; + } + } + + return bRetVal; +} + +int FindYkPointFromDev(DBORIENTATION *psYkYtDBUnit, BYTE u8Fun, BYTE u8Inf) +{ + int i, iYkNo; + + if(psYkYtDBUnit->m_iPntNum <= 0) + { + return -1; + } + + for(i=0; im_iPntNum; i++) + { + if((psYkYtDBUnit->m_psDataInfo[i].m_u8Fun == u8Fun)\ + && (psYkYtDBUnit->m_psDataInfo[i].m_u8Inf == u8Inf)) + { + break; + } + } + + if(i >= psYkYtDBUnit->m_iPntNum) + { + return -1; + } + + iYkNo = psYkYtDBUnit->m_iStartPntNo+i; + + return iYkNo; +} + +BOOL GetSpecialPtr(int commid, DEVADDRPARAM *psDevAddrParam,\ + BUBAN103PORTPARAM **ppsPortParam,\ + BUBAN103LINKDEF **ppsLinkParam, DEVDEF **ppsDevParam) +{ + if(IsExtInfoPtr(commid) == FALSE) + { + return FALSE; + } + + // wen 2005.06.22 修改指针判断为直接赋值 + /* + if((*ppsPortParam) != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + + if((*ppsLinkParam) != NULL) + { + *ppsLinkParam = &((*ppsPortParam)->m_psLink[psDevAddrParam->m_iLinkIdx]); + } + + if((*ppsDevParam) != NULL) + { + *ppsDevParam = &((*ppsLinkParam)->m_psDev[psDevAddrParam->m_iDevIdx]); + } + */ + if(ppsPortParam != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + + if(ppsLinkParam != NULL) + { + *ppsLinkParam = &((*ppsPortParam)->m_psLink[psDevAddrParam->m_iLinkIdx]); + } + + if(ppsDevParam != NULL) + { + *ppsDevParam = &((*ppsLinkParam)->m_psDev[psDevAddrParam->m_iDevIdx]); + } + + return TRUE; +} + +BOOL GetSpecialProvPtr(int commid, DEVADDRPARAM *psDevAddrParam,\ + BUBAN103PORTPARAM **ppsPortParam,\ + BUBAN103LINKDEF **ppsLinkParam, PROVDEVDEF **ppsProvDevParam) +{ + if(IsExtInfoPtr(commid) == FALSE) + { + return FALSE; + } + + // wen 2005.06.22 修改指针判断为直接赋值 + /* + if((*ppsPortParam) != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + + if((*ppsLinkParam) != NULL) + { + *ppsLinkParam = &((*ppsPortParam)->m_psLink[psDevAddrParam->m_iLinkIdx]); + } + + if((*ppsProvDevParam) != NULL) + { + *ppsProvDevParam = &((*ppsLinkParam)->m_psProvDev[psDevAddrParam->m_iDevIdx]); + } + */ + if(ppsPortParam != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + if(ppsLinkParam != NULL) + { + *ppsLinkParam = &((*ppsPortParam)->m_psLink[psDevAddrParam->m_iLinkIdx]); + } + if(ppsProvDevParam != NULL) + { + *ppsProvDevParam = &((*ppsLinkParam)->m_psProvDev[psDevAddrParam->m_iDevIdx]); + } + + return TRUE; +} + +BOOL GetPortParamPtr(int commid, BUBAN103PORTPARAM **ppsPortParam) +{ + if(IsExtInfoPtr(commid) == FALSE) + { + return FALSE; + } + + // wen 2005.06.22 修改指针判断为直接赋值 + /* + if((*ppsPortParam) != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + else + { + printf("*ppsPortParam is NULL.\n"); + return FALSE; + } + */ + if(ppsPortParam != NULL) + { + *ppsPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + } + else + { + return FALSE; + } + + return TRUE; +} + +BOOL GetOneValueOfASDU10(BYTE *pu8SourData, VALUEDEF *psValue, BYTE u8DataType, BYTE u8DataLen) +{ + BOOL bRetVal; + BYTE i, u8Len; + float fValue; + double dfValue; + + psValue->m_unValue.m_dwValue = 0; + psValue->m_iDataType = DT_NO; + u8Len = u8DataLen; + + bRetVal = TRUE; + switch(u8DataType) + { + case DATAID_OS8ASCII: // 8位ASCII + psValue->m_iDataType = DT_STRING; + if(u8Len >= MAXSTRINGLEN) + { + u8Len = MAXSTRINGLEN-1; + } + for(i=0; im_szValue[i] = pu8SourData[i]; + } + psValue->m_szValue[i] = 0; + psValue->m_iDataNum = u8Len; + break; + case DATAID_BSTRING: // 8位2进制数 + psValue->m_iDataType = DT_CONTROL; + psValue->m_iDataNum = u8Len; + u8Len = (u8DataLen+7) / 8; + if(u8Len > sizeof(DWORD)) + { + u8Len = sizeof(DWORD); + psValue->m_iDataNum = u8Len*8; + } + for(i=0; im_unValue.m_dwValue += (pu8SourData[i] << (i*8)); + } + break; + case DATAID_UI: // 无符号整数 + psValue->m_iDataType = DT_UINT; + for(i=0; im_unValue.m_uValue += (pu8SourData[i] << (i*8)); + } + break; + case DATAID_INT: // 整数 + case DATAID_EXDATA_0X24: + psValue->m_iDataType = DT_INT; + for(i=0; im_unValue.m_iValue += (pu8SourData[i] << (i*8)); + } + break; + case DATAID_UFLOAT: // 无符号浮点数 + psValue->m_iDataType = DT_FLOAT; + fValue = *(float *)(pu8SourData); + SequenceRtuToHost((char *)(&fValue), sizeof(float)); + psValue->m_unValue.m_fValue = fabs(fValue); + break; + case DATAID_FLOAT: // 浮点数 + psValue->m_iDataType = DT_FLOAT; + fValue = *(float *)(pu8SourData); + SequenceRtuToHost((char *)(&fValue), sizeof(float)); + psValue->m_unValue.m_fValue = fValue; + break; + case DATAID_754SHORT: // R32.23 IEEE 标准754短实数 + psValue->m_iDataType = DT_FLOAT; + fValue = *(float *)(pu8SourData); + SequenceRtuToHost((char *)(&fValue), sizeof(float)); + psValue->m_unValue.m_fValue = fValue; + break; + case DATAID_754REAL: // R64.53 IEEE 标准754实数 + psValue->m_iDataType = DT_FLOAT; + dfValue = *(double *)(pu8SourData); + SequenceRtuToHost((char *)(&dfValue), sizeof(dfValue)); + psValue->m_unValue.m_fValue = dfValue; + break; + case DATAID_DOUBLE: // 双点信息 + psValue->m_iDataType = DT_BINARY; + psValue->m_iDataNum = 2; + psValue->m_unValue.m_dwValue = pu8SourData[0] & 0x03; + break; + case DATAID_SINGLE: // 单点信息 + psValue->m_iDataType = DT_BINARY; + psValue->m_iDataNum = 1; + psValue->m_unValue.m_dwValue = pu8SourData[0] & 0x01; + break; + case DATAID_13BITS: // 带品质描述的被测值(13BITS) + psValue->m_iDataType = DT_UINT; + psValue->m_unValue.m_uValue = pu8SourData[0]; + psValue->m_unValue.m_uValue = (pu8SourData[1] & 0x1f) * 256; + break; + case DATAID_WITHTIME: // 带时标的报文 + case DATAID_WITHTIMESPACE:// 带相对时标的报文 + case DATAID_SORTIDNO: // 通用分类标识序号 + case DATAID_STRUCT: // 数据结构 + default: + bRetVal = FALSE; + break; + } + + return bRetVal; +} + +int FindAiGroupIdx(DBORIENTATION *pAiDB, int iMaxNum, BYTE u8Asdu, BYTE u8Fun, BYTE u8Inf) +{ + int idx; + + for(idx = 0; idx < iMaxNum; idx++) + { + if(pAiDB[idx].m_psDataInfo == NULL) + { + continue; + } + + if(u8Asdu == pAiDB[idx].m_psDataInfo[0].m_u8Asdu) + { + if((u8Fun == pAiDB[idx].m_psDataInfo[0].m_u8Fun)\ + && (u8Inf == pAiDB[idx].m_psDataInfo[0].m_u8Inf)) + { + break; + } + } + } + + return idx; +} +//*************************************************************** +//* 接收的数据为固定帧长时的处理程序 +//*参数 RTUMSG* rtumsg:接收到的数据信息 +//*************************************************************** +void Buban103shortprocess(RTUMSG *rtumsg) +{ + BOOL bHaveClass1; + int commid; + DEVADDRPARAM sDevAddrParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + sDevAddrParam.m_uchLinkAddr = rtumsg->MsgData[2]; + sDevAddrParam.m_uchCommAddr = 0; + + if(FindProtectDev(pPortParam, &sDevAddrParam, TRUE) == FALSE) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不在端口配置保护范围内!!!", + commid, sDevAddrParam.m_uchLinkAddr, sDevAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + return; + } + else + { + //printf("find is right and exit.\n"); + //return; + +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d linkidx=%d, iDevIdx=%d.", + commid, sDevAddrParam.m_uchLinkAddr, sDevAddrParam.m_uchCommAddr, + sDevAddrParam.m_iLinkIdx, sDevAddrParam.m_iDevIdx); + DebugPrint(szbuf); +#endif + //Buban103DispConfig(commid, pPortParam); + //return; + + pLinkParam = &pPortParam->m_psLink[sDevAddrParam.m_iLinkIdx]; + SetProtectDevStatus(pLinkParam, sDevAddrParam.m_iDevIdx, TRUE); + + ClearLinkCnt(pLinkParam, sDevAddrParam.m_iDevIdx); + } + + bHaveClass1 = FALSE; + if(rtumsg->MsgData[1] & 0x10) + { + pLinkParam->m_iQueryedAddr_CLASS1 = 0; + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + } + else + { + if(rtumsg->MsgData[1] & 0x20) + { + bHaveClass1 = TRUE; + MakeBuban103_PL1_NA_3_Cmd(commid, &sDevAddrParam); + } + else + { + pLinkParam->m_iQueryedAddr_CLASS1 = 0; + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + } + } + + switch(rtumsg->MsgData[1] & 0x0f) + { + case M_CON_NA_3://确认帧 + SetDevLinkOk(pLinkParam, sDevAddrParam.m_iDevIdx, TRUE); + if(pLinkParam->m_bRstLinkOk == TRUE) + { + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = TRUE; + } + break; + case M_BY_NA_3://忙帧(确认帧) + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = TRUE; + break; + case M_NV_NA_3://无所要求的数据帧回答 + if(FALSE == bHaveClass1) + { + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = TRUE; + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bAllQueryOk = TRUE; + } + break; + case M_LKR_NA_3_1://链路工作正常 + SetDevLinkOk(pLinkParam, sDevAddrParam.m_iDevIdx, TRUE); + break; + case M_LKR_NA_3_2://链路服务未工作 + SetDevLinkOk(pLinkParam, sDevAddrParam.m_iDevIdx, FALSE); + break; + case M_LKR_NA_3_3://链路服务未实现 + SetDevLinkOk(pLinkParam, sDevAddrParam.m_iDevIdx, FALSE); + break; + default: +#ifdef _DEBUG_MSG_ + //OutputDebugString("接收到不认识的命令,请检查程序.\n"); + DebugPrint("接收到不认识的命令,请检查程序.\n"); +#endif + break; + } +} + +//*************************************************************** +//* 接收的数据为可变帧长时的处理程序 +//*参数 RTUMSG* rtumsg:接收到的数据信息 +//*************************************************************** +void Buban103longprocess(RTUMSG *rtumsg) +{ + int commid; + DEVADDRPARAM sDevAddrParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + sDevAddrParam.m_uchLinkAddr = rtumsg->MsgData[5]; + sDevAddrParam.m_uchCommAddr = rtumsg->MsgData[9]; + if(FindProtectDev(pPortParam, &sDevAddrParam, FALSE) == FALSE) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不在端口配置保护范围内!!!", + commid, sDevAddrParam.m_uchLinkAddr, sDevAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + return; + } + else + { + pLinkParam = &pPortParam->m_psLink[sDevAddrParam.m_iLinkIdx]; + SetProtectDevStatus(pLinkParam, sDevAddrParam.m_iDevIdx, TRUE); + ClearLinkCnt(pLinkParam, sDevAddrParam.m_iDevIdx); + } + + if(rtumsg->MsgData[4] & 0x10) + { + pLinkParam->m_iQueryedAddr_CLASS1 = 0; + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + } + else + { + if(rtumsg->MsgData[4] & 0x20) + { + MakeBuban103_PL1_NA_3_Cmd(commid, &sDevAddrParam); + } + else + { + if(pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bAllQueryOk == FALSE) + { + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bAllQueryOk = TRUE; + } + + pLinkParam->m_iQueryedAddr_CLASS1 = 0; + pLinkParam->m_iQueryNum_CLASS1_Count = 0; + } + } + + switch(rtumsg->MsgData[6])//类型标识域 + { + case M_TM_TA_3: // 1带时标的报文 + Buban103TMprocess(rtumsg, &sDevAddrParam); + break; + + case M_TMR_TA_3: // 2带相对时间的时标报文 + Buban103TMRprocess(rtumsg, &sDevAddrParam); + break; + + case M_MEI_NA_3: // 3被测值I报文 + Buban103MEIprocess(rtumsg, &sDevAddrParam); + break; + + case M_TME_TA_3: // 4带相对时间的有时标的被测值报文 + Buban103TMEprocess(rtumsg, &sDevAddrParam); + break; + + case M_IRC_NA_3: // 5标识报文 + Buban103IRCprocess(rtumsg, &sDevAddrParam); + break; + + case M_SYN_TA_3: // 6时间同步报文 + Buban103SynTime(rtumsg, &sDevAddrParam); + break; + + case M_TGI_NA_3: // 8总查询(总召唤)中止报文 + pLinkParam->m_bRstLinkOk = FALSE; + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = FALSE; + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bAllQueryOk = TRUE; + break; + + case M_MEII_NA_3: // 9被测值II报文 + Buban103MEIINAprocess(rtumsg, &sDevAddrParam); + break; + + case M_GD_NTA_3: // 10通用分类数据报文 + //如果NGD的COUNT位为零,则表示该批通用分类数据传输结束 + if((rtumsg->MsgData[13] & 0x80) == 0) + { + pLinkParam->m_bRstLinkOk = FALSE; + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = FALSE; + } + Buban103GDprocess(rtumsg, &sDevAddrParam); + break; + + case M_GI_NTA_3: // 11通用分类标识报文 + Buban103GIprocess(rtumsg, &sDevAddrParam); + break; + + // wen 2003.10.27 增加扰动数据的处理 + case M_LRD_TA_3: // 23被记录扰动表报文 + Buban103LRDprocess(rtumsg); + break; + + case M_RTD_TA_3: // 26扰动数据传输准备就绪报文 + Buban103RTDprocess(rtumsg); + break; + + case M_RTC_NA_3: // 27被记录的通道传输准备就绪报文 + Buban103RTCprocess(rtumsg); + break; + + case M_RTT_NA_3: // 28带标志的状态变位的传输准备就绪报文 + Buban103RTTprocess(rtumsg); + break; + + case M_TOT_TA_3: // 29带标志的状态变位传输报文 + Buban103TOTprocess(rtumsg); + break; + + case M_TOV_NA_3: // 30传输扰动值报文 + Buban103TOVprocess(rtumsg); + break; + + case M_EOT_TA_3: // 31传输结束报文 + Buban103EOTprocess(rtumsg); + pLinkParam->m_bRstLinkOk = FALSE; + pLinkParam->m_psDev[sDevAddrParam.m_iDevIdx].m_bInitdata = FALSE; + break; + + case M_MEIII_TA_3: // 32带时标的被测值Ⅲ + Buban103MEIIITAprocess(rtumsg, &sDevAddrParam); + break; + + case M_MEIV_TA_3: // 33带时标的被测值Ⅳ + Buban103MEIVTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_MEV_TA_3: // 34带时标的被测值Ⅴ + Buban103MEVTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_MEVI_TA_3: // 35带时标的被测值Ⅵ + Buban103MEVITAprocess(rtumsg, &sDevAddrParam); + break; + + case M_IT_NA_3: // 36电能脉冲计数值 + Buban103ITNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_IT_TA_3: // 37带时标的电能脉冲计数值 + //Buban103MEITTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_ST_NA_3: // 38步位置信息 + Buban103STNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_ST_TA_3: // 39带时标的步位置信息 + //Buban103STTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_SP_NA_3: // 40单点状态信息 + Buban103SPNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_SP_TA_3: // 41带时标的单点状态信息 + Buban103SPTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_DP_NA_3: // 42双点状态信息 + Buban103DPNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_DP_TA_3: // 43带时标的双点状态信息 + Buban103DPTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_SS_NA_3: // 44单点状态和状态变位检出 + Buban103SSNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_SS_TA_3: // 45带时标的单点状态和状态变位检出 + Buban103SSTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_DS_NA_3: // 46双点状态和状态变位检出 + Buban103DSNAprocess(rtumsg, &sDevAddrParam); + break; + + case M_DS_TA_3: // 47带时标的双点状态和状态变位检出 + Buban103DSTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_WL_TA_3: // 48水位 + Buban103WLTAprocess(rtumsg, &sDevAddrParam); + break; + + case M_MEVII_NA_3: // 50被测值Ⅶ + Buban103MEVIINAprocess(rtumsg, &sDevAddrParam); + break; + + case C_DC_NA_3: // 64控制断路器命令 + Buban103YkAck(rtumsg, &sDevAddrParam); + break; + + case C_RC_NA_3: // 65升降命令 + Buban103YtAck(rtumsg, &sDevAddrParam); + break; + + case C_SE_NA_3: // 66设定命令 + break; + + case C_CC_NA_3: // 67控制命令 + break; + + case M_EX_PI_3: // 205西门子公司扩展电度数据 + Buban103EXPIprocess(rtumsg, &sDevAddrParam); + break; + + default: +#ifdef _DEBUG_MSG_ + DebugPrint("接收到不认识的命令,请检查程序.\n"); +#endif + break; + } +} + +void Buban103TMprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + // 可变结构限定词(VSQ)=0x81 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // DPI + //rtumsg->MsgData[12]; + // 四个八位位组二进制时间 + //rtumsg->MsgData[13]; + // 附加信息 + //rtumsg->MsgData[17]; + + Buban103TMprocessOfSoe(rtumsg, psDevAddrParam); + + // wen 2004.01.12 上送给保护管理程序 + //Buban103TMprocessOfPEvent(rtumsg, psDevAddrParam); +} + +void Buban103TMprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int i, dipnt, commid, iYkNo; + BYTE buf[16], st; + // 事件发生时间毫秒数 + time_t iTime; + WORD wMillSeconds; + struct tm *ptrtm; + + DI_DEF pntmsg; + SOE_DEF sSoeData; + + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=0x81 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // DPI + //rtumsg->MsgData[12]; + // 四个八位位组二进制时间 + //rtumsg->MsgData[13]; + // 附加信息 + //rtumsg->MsgData[17]; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[psDevAddrParam->m_iDevIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU1信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + // wen 2004.04.11 增加asdu类型判断 + if(pLinkParam->m_iJudgeAsduNo != 0) + { + if(M_TM_TA_3 != pDataUnit->m_psDataInfo[i].m_u8Asdu) + { + continue; + } + } + + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + //遥控遥调返校 + if(M_CAUSE_REMOTE != rtumsg->MsgData[8]) + { + return; + } + + iYkNo = FindYkPointFromDev(&pDevParam->m_sDevParam.m_sYkDBOrientation, rtumsg->MsgData[10], rtumsg->MsgData[11]); + + if(iYkNo >= 0) + { + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + buf[0] = (BYTE)(commid & 0xFF); + buf[1] = (BYTE)((commid & 0xFF00) << 8); + buf[2] = (BYTE)((commid & 0xFF0000) << 16); + buf[3] = (BYTE)((commid & 0xFF000000) << 24); + + buf[4] = (BYTE)(iYkNo & 0xFF); + buf[5] = (BYTE)((iYkNo & 0xFF00) << 8); + buf[6] = (BYTE)((iYkNo & 0xFF0000) << 16); + buf[7] = (BYTE)((iYkNo & 0xFF000000) << 24); + + buf[8] = STEP_YKYT_EXEC; + buf[9] = rtumsg->MsgData[12] | 0x80; + + if(ShmGetDispYkYtFlag()) + { +#ifdef _DEBUG_MSG_ + //sprintf(szbuf, "端口%d 链路地址=%d 装置地址%d RII=0x%02x, 遥控点号=%d, op=0x%02x!!!\n", + // commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYkNo, rtumsg->MsgData[12]); + //DebugPrint(szbuf); + sprintf(szbuf, "TIP_(%04d): commid=%d linkaddr=%d devaddr=%d RII=0x%02x ykytpnt=%d, op=0x%02x.\n", + _getpid(), commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYkNo, rtumsg->MsgData[12]); + DebugPrint(szbuf); +#endif + } + + Buban103YkYtProcess(commid, buf, 10); + } + return; + } + + dipnt = pDataUnit->m_iStartPntNo + i; + + st = rtumsg->MsgData[12] & 0x03; + if((st == 0) || (st == 3)) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d 链路地址=%d 装置地址%d RII=%d, 点号=%d, status=%d!!!\n", + commid, rtumsg->MsgData[5], rtumsg->MsgData[9], dipnt, rtumsg->MsgData[12]); + DebugPrint(szbuf); +#endif + return; + } + + st--; + + pntmsg.Status = st; + // 属于自发或者突发事件就是soe + //if(rtumsg->MsgData[8] == M_CAUSE_AUTOSEND) + if(rtumsg->MsgData[8] != M_CAUSE_QUERY) + { + // 事件发生时间毫秒数 + time(&iTime); + ptrtm = localtime(&iTime); + if(ptrtm->tm_hour < (rtumsg->MsgData[16] & 0x1f)) + { + iTime -= 24 * 3600; + ptrtm = localtime(&iTime); + } + ptrtm->tm_hour = rtumsg->MsgData[16] & 0x1f; + ptrtm->tm_min = rtumsg->MsgData[15] & 0x3f; + wMillSeconds = rtumsg->MsgData[13] + rtumsg->MsgData[14]*256; + ptrtm->tm_sec = wMillSeconds / 1000; + wMillSeconds %= 1000; + + sSoeData.bStatus = st; + sSoeData.iPntNo = dipnt; + sSoeData.u8Type = 1;// ASDU1 + sSoeData.wFaultNo = 0; + sSoeData.u8ProvFun = pDataUnit->m_psDataInfo[i].m_u8ProvFun; + sSoeData.u8ProvInf = pDataUnit->m_psDataInfo[i].m_u8ProvInf; + sSoeData.wRelativeTime = 0; + sSoeData.SoeTime.Year = ptrtm->tm_year+1900; + sSoeData.SoeTime.Month = (BYTE)(ptrtm->tm_mon+1); + sSoeData.SoeTime.Day = (BYTE)(ptrtm->tm_mday); + sSoeData.SoeTime.Hour = (BYTE)(ptrtm->tm_hour); + sSoeData.SoeTime.Min = (BYTE)(ptrtm->tm_min); + sSoeData.SoeTime.Sec = (BYTE)(ptrtm->tm_sec); + sSoeData.SoeTime.mSec = wMillSeconds; + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&sSoeData, DI_PNT_TYPE, PNT_SOE_TIME_EX); + } + + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); +} + +void Buban103TMRprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=0x81 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // DPI + //rtumsg->MsgData[12]; + // 相对时间 + //rtumsg->MsgData[13]; + // 故障序号 + //rtumsg->MsgData[15]; + // 四个八位位组二进制时间 + //rtumsg->MsgData[17]; + // 附加信息 + //rtumsg->MsgData[21]; + + Buban103TMRprocessOfSoe(rtumsg, psDevAddrParam); + + // wen 2004.01.12 上送给保护管理程序 + //Buban103TMRprocessOfPEvent(rtumsg, psDevAddrParam); +} + +void Buban103TMRprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int i, dipnt, commid; + BYTE st; + // 事件发生时间毫秒数 + time_t iTime; + WORD wMillSeconds, wTime, wFault; + struct tm *ptrtm; + DI_DEF pntmsg; + SOE_DEF sSoeData; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=0x81 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // DPI + //rtumsg->MsgData[12]; + // 相对时间 + //rtumsg->MsgData[13]; + // 故障序号 + //rtumsg->MsgData[15]; + // 四个八位位组二进制时间 + //rtumsg->MsgData[17]; + // 附加信息 + //rtumsg->MsgData[21]; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[psDevAddrParam->m_iDevIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU2信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + // wen 2004.04.11 增加asdu类型判断 + if(pLinkParam->m_iJudgeAsduNo != 0) + { + if(M_TMR_TA_3 != pDataUnit->m_psDataInfo[i].m_u8Asdu) + { + continue; + } + } + + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + return; + } + + dipnt = pDataUnit->m_iStartPntNo + i; + if(rtumsg->MsgData[8] == M_CAUSE_QUERY) + { + // 相对时间和故障序号是无关的 + } + else + { + // 相对时间和故障序号是相关的 + } + + st = rtumsg->MsgData[12] & 0x03; + if((st == 0) || (st == 3)) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d 链路地址=%d 装置地址%d 点号=%d, status=%d!!!\n", + commid, rtumsg->MsgData[5], rtumsg->MsgData[9], dipnt, rtumsg->MsgData[12]); + DebugPrint(szbuf); +#endif + return; + } + + wTime = rtumsg->MsgData[13] + rtumsg->MsgData[14]*256; + wFault= rtumsg->MsgData[15] + rtumsg->MsgData[16]*256; + + st--; + + pntmsg.Status = st; + // 属于自发或者突发事件就是soe + //if(rtumsg->MsgData[8] == M_CAUSE_AUTOSEND) + if(rtumsg->MsgData[8] != M_CAUSE_QUERY) + { + // 事件发生时间毫秒数 + time(&iTime); + ptrtm = localtime(&iTime); + if(ptrtm->tm_hour < (rtumsg->MsgData[20] & 0x1f)) + { + iTime -= 24 * 3600; + ptrtm = localtime(&iTime); + } + ptrtm->tm_hour = rtumsg->MsgData[20] & 0x1f; + ptrtm->tm_min = rtumsg->MsgData[19] & 0x3f; + wMillSeconds = rtumsg->MsgData[17] + rtumsg->MsgData[18]*256; + ptrtm->tm_sec = wMillSeconds / 1000; + wMillSeconds %= 1000; + + sSoeData.bStatus = st; + sSoeData.iPntNo = dipnt; + sSoeData.u8Type = 2;// ASDU2 + sSoeData.wFaultNo = wFault; + sSoeData.wRelativeTime = wTime; + sSoeData.u8ProvFun = pDataUnit->m_psDataInfo[i].m_u8ProvFun; + sSoeData.u8ProvInf = pDataUnit->m_psDataInfo[i].m_u8ProvInf; + sSoeData.SoeTime.Year = ptrtm->tm_year+1900; + sSoeData.SoeTime.Month = (BYTE)(ptrtm->tm_mon+1); + sSoeData.SoeTime.Day = (BYTE)(ptrtm->tm_mday); + sSoeData.SoeTime.Hour = (BYTE)(ptrtm->tm_hour); + sSoeData.SoeTime.Min = (BYTE)(ptrtm->tm_min); + sSoeData.SoeTime.Sec = (BYTE)(ptrtm->tm_sec); + sSoeData.SoeTime.mSec = wMillSeconds; + + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&sSoeData, DI_PNT_TYPE, PNT_SOE_TIME_EX); + } + + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); +} + +void Buban103MEIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int commid; + int i, aipnt, iNum, idx; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // B相电流 + //rtumsg->MsgData[12]; + // AB相线电流 + //rtumsg->MsgData[14]; + // 有功功率 + //rtumsg->MsgData[16]; + // 无功功率 + //rtumsg->MsgData[18]; + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // wen 2004.02.04 配置与测量值类型不固定关联 + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEI_NA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEI_NA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU3(%d,%d) 测量值Ⅰ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU3(%d,%d) 测量值Ⅰ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; + for(i=0; iMsgData[12+2*i]&0xf8) + rtumsg->MsgData[13+2*i] * 256); + pntmsg.RawValue /= 8; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt+i, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban103TMEprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int commid; + int idx; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=0x81 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // DPI + //rtumsg->MsgData[12]; + // 相对时间 + //rtumsg->MsgData[13]; + // 故障序号 + //rtumsg->MsgData[15]; + // 四个八位位组二进制时间 + //rtumsg->MsgData[17]; + // 附加信息 + //rtumsg->MsgData[21]; + + return; + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // wen 2004.02.04 配置与测量值类型不固定关联 + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_TME_TA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_TME_TA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU4(%d,%d) 不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU4(%d,%d) 不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } +} + +void Buban103IRCprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int commid; + CMDPARAM sCmdParam; + + // 传送原因 + if(rtumsg->MsgData[8] == M_CAUSE_POWERON) + { + commid = rtumsg->PortIdx; + memcpy((void *)&sCmdParam.m_sDevAddr, (void *)psDevAddrParam, sizeof(DEVADDRPARAM)); + sCmdParam.m_uchFun = 255; + sCmdParam.m_uchInf = 0; + MakeAllQuery_CAsdu7(commid, &sCmdParam); + } +} + +void Buban103MEIINAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + //rtumsg->MsgData[11]; + // A相电流 + //rtumsg->MsgData[12]; + // B相电流 + //rtumsg->MsgData[14]; + // C相电流 + //rtumsg->MsgData[16]; + // A相电压 + //rtumsg->MsgData[18]; + // B相电压 + //rtumsg->MsgData[20]; + // C相电压 + //rtumsg->MsgData[22]; + // 有功功率 + //rtumsg->MsgData[24]; + // 无功功率 + //rtumsg->MsgData[26]; + // 频率 + //rtumsg->MsgData[28]; + + int commid; + int i, aipnt, iNum, idx; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEII_NA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEII_NA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU9(%d,%d) 测量值Ⅱ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU9(%d,%d) 测量值Ⅱ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; + for(i=0; iMsgData[12+2*i] & 0x01); + + // 品质描述,数据无效 + //if(rtumsg->MsgData[12+2*i] & 0x02); + + // 最低3位为品质描述 + pntmsg.RawValue = (short)((rtumsg->MsgData[12+2*i]&0xf8) + rtumsg->MsgData[13+2*i] * 256); + pntmsg.RawValue /= 8; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt+i, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban103MEIIITAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + // = 144 --- 147 + //rtumsg->MsgData[11]; + // L2电流 + //rtumsg->MsgData[12]; + // L1-L2电流 + //rtumsg->MsgData[14]; + // 有功功率 + //rtumsg->MsgData[16]; + // 无功功率 + //rtumsg->MsgData[18]; + // 被测谐波值1(3 BYTES) + //rtumsg->MsgData[20]; + // ... ... + // 被测谐波值N(3 BYTES) + // 四个八位位组的二进制时标 + + int commid; + int i, aipnt, iNum, idx; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEIII_TA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEIII_TA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU32(%d,%d) 测量值Ⅲ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU32(%d,%d) 测量值Ⅲ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; + + // wen 2003.11.01 大于4以后的为谐波值和二进制时标 + iNum = 4; + for(i=0; iMsgData[12+2*i]&0xf8) + rtumsg->MsgData[13+2*i] * 256); + pntmsg.RawValue /= 8; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt+i, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban103MEIVTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) = 148 + //rtumsg->MsgData[11]; + // L1电流 + //rtumsg->MsgData[12]; + // L2电流 + //rtumsg->MsgData[14]; + // L3电流 + //rtumsg->MsgData[16]; + // Ul1电压 + //rtumsg->MsgData[18]; + // Ul2电压 + //rtumsg->MsgData[20]; + // Ul3电压 + //rtumsg->MsgData[22]; + // 有功功率 + //rtumsg->MsgData[24]; + // 无功功率 + //rtumsg->MsgData[26]; + // 频率 + //rtumsg->MsgData[28]; + // 被测谐波值1(3 BYTES) + //rtumsg->MsgData[30]; + // ... ... + // 被测谐波值N(3 BYTES) + // 四个八位位组的二进制时标 + + int commid; + int i, aipnt, iNum, idx; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEIV_TA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEIV_TA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU33(%d,%d) 测量值Ⅳ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU33(%d,%d) 测量值Ⅳ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; + + // wen 2003.11.01 大于9以后的为谐波值和二进制时标 + iNum = 9; + for(i=0; iMsgData[12+2*i]&0xf8) + rtumsg->MsgData[13+2*i] * 256); + pntmsg.RawValue /= 8; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt+i, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } +} + +// 被测值V报文 +void Buban103MEVTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) + // = 144 --- 147 + //rtumsg->MsgData[11]; + // 以下值为向量 + // L2电流 + //rtumsg->MsgData[12]; + // L1-L2电流 + //rtumsg->MsgData[16]; + // 有功功率 + //rtumsg->MsgData[20]; + // 无功功率 + //rtumsg->MsgData[24]; + // 被测谐波值1(4 BYTES) + //rtumsg->MsgData[28]; + // ... ... + // 被测谐波值N(4 BYTES) + // 四个八位位组的二进制时标 + + int commid; + int aipnt, iNum, idx; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEV_TA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEV_TA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU34(%d,%d) 测量值Ⅴ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU34(%d,%d) 测量值Ⅴ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; +} + +// 被测值VI报文 +void Buban103MEVITAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF) = 148 + //rtumsg->MsgData[11]; + // L1电流 + //rtumsg->MsgData[12]; + // L2电流 + //rtumsg->MsgData[16]; + // L3电流 + //rtumsg->MsgData[20]; + // Ul1电压 + //rtumsg->MsgData[24]; + // Ul2电压 + //rtumsg->MsgData[28]; + // Ul3电压 + //rtumsg->MsgData[32]; + // 视在功率 + //rtumsg->MsgData[36]; + // 频率 + //rtumsg->MsgData[38]; + // 频率变化率 df/dt + //rtumsg->MsgData[40]; + // 被测谐波值向量1(3 BYTES) + //rtumsg->MsgData[42]; + // ... ... + // 被测谐波值向量N(3 BYTES) + // 四个八位位组的二进制时标 + + int commid; + int aipnt, iNum, idx; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + /*for(idx = 0; idx < DEV_AI_MAXNUM; idx++) + { + if(pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo == NULL) + { + continue; + } + + if(M_MEVI_TA_3 == pDevParam->m_sDevParam.m_sAiDBOrientation[idx].m_psDataInfo[0].m_u8Asdu) + { + break; + } + }*/ + //=================================================================================================== + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEVI_TA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU35(%d,%d) 测量值Ⅵ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU35(%d,%d) 测量值Ⅵ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + //if((rtumsg->MsgData[10] != pDataUnit->m_psDataInfo[0].m_u8Fun)\ + // || (rtumsg->MsgData[11] != pDataUnit->m_psDataInfo[0].m_u8Inf)) + //{ + // return; + //} + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; +} + +// 被测值VII报文 +void Buban103MEVIINAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(92 --- 148) + //rtumsg->MsgData[11]; + // 被测值1 + //rtumsg->MsgData[12]; + // 被测值2 + //rtumsg->MsgData[14]; + // ... ... + // 被测值n + //rtumsg->MsgData[10+2*N]; + + int commid; + int i, aipnt, iNum, idx; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 总共7组被测值 + idx = FindAiGroupIdx(pDevParam->m_sDevParam.m_sAiDBOrientation, DEV_AI_MAXNUM, M_MEVII_NA_3, rtumsg->MsgData[10], rtumsg->MsgData[11]); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(idx >= DEV_AI_MAXNUM) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU50(%d,%d) 测量值Ⅶ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + else + { + pDataUnit = &pDevParam->m_sDevParam.m_sAiDBOrientation[idx]; + } + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU50(%d,%d) 测量值Ⅶ不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, rtumsg->MsgData[10], rtumsg->MsgData[11]); + DebugPrint(szbuf); +#endif + return; + } + + iNum = rtumsg->MsgData[7] & 0x7f; + if(iNum > pDataUnit->m_iPntNum) + { + iNum = pDataUnit->m_iPntNum; + } + + + aipnt = pDataUnit->m_iStartPntNo; + + // wen 2003.11.01 大于9以后的为谐波值和二进制时标 + // 南瑞103没有此要求 20060803 yizhonghu + // iNum = 9; + for(i=0; iMsgData[12+2*i]&0xf8) + rtumsg->MsgData[13+2*i] * 256); + pntmsg.RawValue /= 8; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt+i, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban103STNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=1 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(76 --- 79) + //rtumsg->MsgData[11]; + // 带瞬变状态指示的值(VTI) + //rtumsg->MsgData[12]; + // 品质描述(QDS) + //rtumsg->MsgData[13]; + + int commid; + int aipnt; + AI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + pDataUnit = &pDevParam->m_sDevParam.m_sStepDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU38 步位置信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + aipnt = pDataUnit->m_iStartPntNo + rtumsg->MsgData[11] - 76; + + if(rtumsg->MsgData[12] & 0x80) + { + // 设备在瞬变状态 + } + else + { + // 设备未在瞬变状态 + } + pntmsg.RawValue = rtumsg->MsgData[12]&0x7F; + SetPntMsg(pDataUnit->m_iStnNo-1, aipnt, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + + //品质描述(QDS) rtumsg->MsgData[13]; +} + +void Buban103SPNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int i, dipnt, commid; + BYTE st; + DI_DEF pntmsg; + + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1 + //rtumsg->MsgData[12]; + // 附加信息 + //rtumsg->MsgData[13]; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[psDevAddrParam->m_iDevIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU1信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + // asdu类型判断 + if(pLinkParam->m_iJudgeAsduNo != 0) + { + if(M_SP_NA_3 != pDataUnit->m_psDataInfo[i].m_u8Asdu) + { + continue; + } + } + + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + return; + } + + dipnt = pDataUnit->m_iStartPntNo + i; + + st = rtumsg->MsgData[12] & 0x01; + pntmsg.Status = st; + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); +} + +void Buban103SPTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + Buban103SPTAprocessOfSoe(rtumsg, psDevAddrParam); +} + +void Buban103SPTAprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + + int i, dipnt, commid; + BYTE st; + // 事件发生时间毫秒数 + time_t iTime; + WORD wMillSeconds; + struct tm *ptrtm; + + DI_DEF pntmsg; + SOE_DEF sSoeData; + + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1 + //rtumsg->MsgData[12]; + // 带品质描述的单点信息1变化时间(4 bytes) + //rtumsg->MsgData[13]; + // 带品质描述的单点信息2 + //rtumsg->MsgData[17]; + // 带品质描述的单点信息2变化时间(4 bytes) + //rtumsg->MsgData[18]; + // ... ... + // 带品质描述的单点信息n + //rtumsg->MsgData[12+5*(n-1)]; + // 带品质描述的单点信息n变化时间(4 bytes) + //rtumsg->MsgData[12+5*(n-1)+1]; + // 附加信息 + //rtumsg->MsgData[12+5*n]; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[psDevAddrParam->m_iDevIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU1信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + // asdu类型判断 + if(pLinkParam->m_iJudgeAsduNo != 0) + { + if(M_SP_TA_3 != pDataUnit->m_psDataInfo[i].m_u8Asdu) + { + continue; + } + } + + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + return; + } + + dipnt = pDataUnit->m_iStartPntNo + i; + + st = rtumsg->MsgData[12] & 0x01; + pntmsg.Status = st; + // 属于自发或者突发事件就是soe + if(rtumsg->MsgData[8] != M_CAUSE_QUERY) + { + // 事件发生时间毫秒数 + time(&iTime); + ptrtm = localtime(&iTime); + if(ptrtm->tm_hour < (rtumsg->MsgData[16] & 0x1f)) + { + iTime -= 24 * 3600; + ptrtm = localtime(&iTime); + } + ptrtm->tm_hour = rtumsg->MsgData[16] & 0x1f; + ptrtm->tm_min = rtumsg->MsgData[15] & 0x3f; + wMillSeconds = rtumsg->MsgData[13] + rtumsg->MsgData[14]*256; + ptrtm->tm_sec = wMillSeconds / 1000; + wMillSeconds %= 1000; + + sSoeData.bStatus = st; + sSoeData.iPntNo = dipnt; + sSoeData.u8Type = 1;// ASDU1 + sSoeData.wFaultNo = 0; + sSoeData.u8ProvFun = pDataUnit->m_psDataInfo[i].m_u8ProvFun; + sSoeData.u8ProvInf = pDataUnit->m_psDataInfo[i].m_u8ProvInf; + sSoeData.wRelativeTime = 0; + sSoeData.SoeTime.Year = ptrtm->tm_year+1900; + sSoeData.SoeTime.Month = (BYTE)(ptrtm->tm_mon+1); + sSoeData.SoeTime.Day = (BYTE)(ptrtm->tm_mday); + sSoeData.SoeTime.Hour = (BYTE)(ptrtm->tm_hour); + sSoeData.SoeTime.Min = (BYTE)(ptrtm->tm_min); + sSoeData.SoeTime.Sec = (BYTE)(ptrtm->tm_sec); + sSoeData.SoeTime.mSec = wMillSeconds; + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&sSoeData, DI_PNT_TYPE, PNT_SOE_TIME_EX); + } + + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); +} + +void Buban103DPNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的双点信息1 + //rtumsg->MsgData[12]; + // 带品质描述的双点信息2 + //rtumsg->MsgData[13]; + // ... ... + // 带品质描述的双点信息n + //rtumsg->MsgData[12+n-1]; + // 附加信息 + //rtumsg->MsgData[12+n]; +} + +void Buban103DPTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1 + //rtumsg->MsgData[12]; + // 带品质描述的单点信息1变化时间(4 bytes) + //rtumsg->MsgData[13]; + // 带品质描述的单点信息2 + //rtumsg->MsgData[17]; + // 带品质描述的单点信息2变化时间(4 bytes) + //rtumsg->MsgData[18]; + // ... ... + // 带品质描述的单点信息n + //rtumsg->MsgData[12+5*(n-1)]; + // 带品质描述的单点信息n变化时间(4 bytes) + //rtumsg->MsgData[12+5*(n-1)+1]; + // 附加信息 + //rtumsg->MsgData[12+5*n]; + + Buban103DPTAprocessOfSoe(rtumsg, psDevAddrParam); +} + +void Buban103DPTAprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1 + //rtumsg->MsgData[12]; + // 带品质描述的单点信息1变化时间(4 bytes) + //rtumsg->MsgData[13]; + // 带品质描述的单点信息2 + //rtumsg->MsgData[17]; + // 带品质描述的单点信息2变化时间(4 bytes) + //rtumsg->MsgData[18]; + // ... ... + // 带品质描述的单点信息n + //rtumsg->MsgData[12+5*(n-1)]; + // 带品质描述的单点信息n变化时间(4 bytes) + //rtumsg->MsgData[12+5*(n-1)+1]; + // 附加信息 + //rtumsg->MsgData[12+5*n]; + + +} + +void Buban103SSNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int i, j, dipnt, commid; + BYTE st, len; + WORD wStatusBit; + + DI_DEF pntmsg; + + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12]; + // QDS + //rtumsg->MsgData[16]; + // 带品质描述的单点信息2状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[17]; + // QDS + //rtumsg->MsgData[21]; + // ... ... + // 带品质描述的单点信息n状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12+5*(n-1)]; + // QDS + //rtumsg->MsgData[12+5*(n-1)+4]; + // 附加信息 + //rtumsg->MsgData[12+5*n]; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[psDevAddrParam->m_iDevIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU1信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + // asdu类型判断 + if(pLinkParam->m_iJudgeAsduNo != 0) + { + if(M_SS_NA_3 != pDataUnit->m_psDataInfo[i].m_u8Asdu) + { + continue; + } + } + + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + return; + } + + dipnt = pDataUnit->m_iStartPntNo + i; + + len = (int)rtumsg->MsgData[1]; + + st = rtumsg->MsgData[12] & 0x01; + pntmsg.Status = st; + SetPntMsg(pDataUnit->m_iStnNo-1, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + + for ( i = 10; i < 4 + len; i += 5, dipnt += 16 ) + { + wStatusBit = rtumsg->MsgData[i+3]; + wStatusBit = (wStatusBit<<8) + rtumsg->MsgData[i+2]; + + for( j = 0; j < 16; j++ ) + { + if( wStatusBit & (0x0001 << j) ) + pntmsg.Status = 1; + else + pntmsg.Status = 0; + SetPntMsg(commid, dipnt+j, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } + } +} + +void Buban103SSTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ) & 0x7f = 测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的单点信息1状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12]; + // QDS + //rtumsg->MsgData[16]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[17]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[21]; + // 带品质描述的单点信息2状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[22]; + // QDS + //rtumsg->MsgData[26]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[27]; + // ... ... + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11+10*(n-1)]; + // 带品质描述的单点信息n状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[11+10*(n-1)+1]; + // QDS + //rtumsg->MsgData[11+10*(n-1)+5]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[11+10*(n-1)+6]; + // 附加信息 + //rtumsg->MsgData[11+10*n]; + +} + +void Buban103DSNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的双点信息1状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12]; + // QDS + //rtumsg->MsgData[16]; + // 带品质描述的双点信息2状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[17]; + // QDS + //rtumsg->MsgData[21]; + // ... ... + // 带品质描述的双点信息n状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12+5*(n-1)]; + // QDS + //rtumsg->MsgData[12+5*(n-1)+4]; + // 附加信息 + //rtumsg->MsgData[12+5*n]; + +} + +void Buban103DSTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ) & 0x7f = 测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11]; + // 带品质描述的双点信息1状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[12]; + // QDS + //rtumsg->MsgData[16]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[17]; + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[21]; + // 带品质描述的双点信息2状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[22]; + // QDS + //rtumsg->MsgData[26]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[27]; + // ... ... + // 信息序号(INF)(149 --- 238) + //rtumsg->MsgData[11+10*(n-1)]; + // 带品质描述的双点信息n状态和状态变化检出=SCD(4 BYTE) + //rtumsg->MsgData[11+10*(n-1)+1]; + // QDS + //rtumsg->MsgData[11+10*(n-1)+5]; + // 四个八位位组的二进制时标 + //rtumsg->MsgData[11+10*(n-1)+6]; + // 附加信息 + //rtumsg->MsgData[11+10*n]; + +} + +void Buban103WLTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int commid; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU48 水位信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif +} + +void Buban103ITNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP) + //rtumsg->MsgData[6]; + // 可变结构限定词(VSQ)=测量量数目 + //rtumsg->MsgData[7]; + // 传送原因(COT) + //rtumsg->MsgData[8]; + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + // 功能类型(FUN) + //rtumsg->MsgData[10]; + // 信息序号(INF)(6 --- 31) + //rtumsg->MsgData[11]; + // 二进制计数器读数CR1(5 BYTES) + //rtumsg->MsgData[12]; + // 二进制计数器读数CR2 + //rtumsg->MsgData[17]; + // ... ... + // 二进制计数器读数CRn + //rtumsg->MsgData[12+5*(N-1)]; + // 返回信息标识符(RII) + //rtumsg->MsgData[12+5*N]; + + int commid; + int i, pipnt, iNum; + PI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + pDataUnit = &pDevParam->m_sDevParam.m_sPiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU36 电度量信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + iNum = rtumsg->MsgData[7] & 0x7f; + pipnt = pDataUnit->m_iStartPntNo + rtumsg->MsgData[11] - 6; + + for(i=0; iMsgData[12+5*i+4] & 0x80) + { + continue; + } + + // 最低3位为品质描述 + pntmsg.RawValue = rtumsg->MsgData[12+5*i] + (rtumsg->MsgData[13+5*i] << 8) + + (rtumsg->MsgData[13+5*i] << 16) + (rtumsg->MsgData[13+5*i] << 24); + SetPntMsg(pDataUnit->m_iStnNo-1, pipnt+i, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + } +} + +// 通用分类数据报文(包括所有的定值、模拟量、开关量(压板、开入开出等)) +void Buban103GDprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP):10 + //rtumsg->MsgData[6]; + + // 可变结构限定词(VSQ):0x81 + //rtumsg->MsgData[7]; + + // 传送原因(COT) + //rtumsg->MsgData[8]; + + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + + // 功能类型(FUN): 254(0xfe) + //rtumsg->MsgData[10]; + + // 信息序号(INF): + // 读组标题 : 240 + // 读一个组的全部条目的值或属性 : 241 + // 读单个条目的目录 : 243 + // 读单个条目的值或属性 : 244 + // 对通用分类数据总查询中止 : 245 + //rtumsg->MsgData[11]; + + // 返回信息标识符(RII) + //rtumsg->MsgData[12]; + + // 通用分类数据集数目 + //rtumsg->MsgData[13]; + + // 以下为多个通用分类数据 + // 通用分类标识序号(GIN):条目号和组号 + //rtumsg->MsgData[14]; + + // 描述类别(KOD) + // 无所指定的描述类别 : KOD_NOSPECIFIED(0) + // 实际值 : KOD_ACTUALVALUE(1) + // 缺省值 : KOD_DEFAULTVALUE(2) + // 量程(最大值、最小值、步长) : KOD_RANGE(3) + // 备用 : KOD_BACKUP1(4) + // 精度(n,m) : KOD_PRECISION(5) + // 因子 : KOD_FACTOR(6) + // 参比 : KOD_REFERENCE(7) + // 列表 : KOD_ENUMERATION(8) + // 量纲 : KOD_DIMENSION(9) + // 描述 : KOD_DESCRIPTION(10) + // 备用 : KOD_BACKUP2(11) + // 口令条目 : KOD_PASSWORD(12) + // 只读 : KOD_READONLY(13) + // 只写 : KOD_WRITEONLY(14) + // 备用 : KOD_BACKUP3(15) + // 备用 : KOD_BACKUP4(16) + // 备用 : KOD_BACKUP5(17) + // 备用 : KOD_BACKUP6(18) + // 相应的功能类型和信息序号 : KOD_CORFUNCANDINF(19) + // 相应的事件 : KOD_COREVENT(20) + // 列表的文本阵列 : KOD_ENUMTEXTARRAY(21) + // 列表的值阵列 : KOD_ENUMVALUEARRAY(22) + // 相关联的条目 : KOD_RELATEDENTRIES(23) + //rtumsg->MsgData[16]; + + // 数据类型描述 + //rtumsg->MsgData[17]; + //DATAID_NO : 无数据 + //DATAID_OS8ASCII : 8位ASCII + //DATAID_BSTRING : 8位2进制数 + //DATAID_UIX : 无符号整数 + //DATAID_INT : 整数 + //DATAID_UFLOAT : 无符号浮点数 + //DATAID_FLOAT : 浮点数 + //DATAID_754SHORT : R32.23 IEEE 标准754短实数 + //DATAID_754REAL : R64.53 IEEE 标准754实数 + //DATAID_DOUBLE : 双点信息 + //DATAID_SINGLE : 单点信息 + //DATAID_13BITS : 带品质描述的被测值(13BITS) + //DATAID_SORTIDNO : 通用分类标识序号 + //DATAID_WITHTIME : 带时标的报文 + //DATAID_WITHTIMESPACE : 带相对时标的报文 + //DATAID_STRUCT : 数据结构 + + // 数据尺寸 + //rtumsg->MsgData[18] + + // 数量 + //rtumsg->MsgData[19] + + // 数据值(长度根据以上描述) + + // 2 ... n 个通用分类数据 + + int commid; + int i, iGroupNo, iCfgGroupIdx; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + // 数据转发在这里处理 + if(rtumsg->MsgData[12] == RII_PROV_ID) + { + if(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid >= 0) + { + if(psDevAddrParam->m_uchCommAddr ==\ + pLinkParam->m_sBaoHuCmdParam.m_sRealAddrParam.m_uchCommAddr) + { + // 判断超时时间为5分钟 + if(JudgeTimeOut(&pLinkParam->m_sBaoHuCmdParam.m_sBaoHuCmdStartTime, 5*60) == FALSE) + { + if(MSGTYPE_BAOHU_103CMD == pLinkParam->m_sBaoHuCmdParam.m_iBaoHuMsgType) + { + // 转储数据到转发端口 + rtumsg->MsgData[9] = (BYTE)pDevParam->m_sDevParam.m_iProvAddr; + rtumsg->PortIdx = pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid; + rtumsg->MsgType = MSGTYPE_BAOHU_103DATA; + PutBaohuDataToPort(rtumsg); + } + else if(MSGTYPE_BAOHU_SCADACMD == pLinkParam->m_sBaoHuCmdParam.m_iBaoHuMsgType) + { + //rtumsg->MsgData[9] = (BYTE)pDevParam->m_sDevParam.m_iProvAddr; + //rtumsg->PortIdx = pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid; + rtumsg->MsgType = MSGTYPE_BAOHU_SCADADATA; + // 按内部保护格式转换 + Buban103ScadaProtocolExchange(commid, rtumsg); + } + + // 没有后续数据 + if((rtumsg->MsgData[13] & 0x80) == 0) + { + pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid = -1; + pLinkParam->m_sBaoHuCmdParam.m_iBaoHuMsgType = 0; + } + return; + } + else + { + pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid = -1; + } + } + } + } + + //组 号 + iGroupNo = rtumsg->MsgData[14]; + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo == iGroupNo) + { + iCfgGroupIdx = i; + break; + } + } + + if(i >= pDevParam->m_sDevParam.m_iCfgGroupNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10 通用分类数据处理时,Group=%d不在处理范围内!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, iGroupNo); + DebugPrint(szbuf); +#endif + return ; + } + + switch(pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iDataType) + { + // 处理模拟量 + case AI_PNT_TYPE: + Buban103GDprocessWithAI(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理开关量 + case DI_PNT_TYPE: + Buban103GDprocessWithDI(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理电度量 + case PI_PNT_TYPE: + Buban103GDprocessWithPI(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护模拟量 + case PROTECT_AI_PNT_TYPE: + Buban103GDprocessWithPAI(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护开关量 + case PROTECT_DI_PNT_TYPE: + Buban103GDprocessWithPDI(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护定值 + case PROTECT_FIX_PNT_TYPE: + Buban103GDprocessWithPFIX(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护事件 + case PROTECT_EVENT_PNT_TYPE: + Buban103GDprocessWithPEVENT(rtumsg, psDevAddrParam, iCfgGroupIdx); + break; + + default: +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10处理时, Group=%d数据类型(=%d)不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, + pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iGroupNo, + pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iDataType); + DebugPrint(szbuf); +#endif + break; + } +} + +void Buban103YkAck(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP):64 + //rtumsg->MsgData[6]; + + // 可变结构限定词(VSQ):0x81 + //rtumsg->MsgData[7]; + + // 传送原因(COT) + //rtumsg->MsgData[8]; + //M_CAUSE_REMOTE : // 远方操作 + + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + + // 功能类型(FUN): 1 + //rtumsg->MsgData[10]; + + // 信息序号(INF): 48 --- 75 + //rtumsg->MsgData[11]; + + // 信息序号(DCC) + //rtumsg->MsgData[12]; + + // 返回信息标识符(RII) + //rtumsg->MsgData[13]; + + int commid; + int iYkNo; + BYTE buf[16]; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + if(pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU64 未配置遥控点!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + iYkNo = rtumsg->MsgData[11] - 48 + pDevParam->m_sDevParam.m_iYkStartPnt; + if(iYkNo >= 0) + { + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + buf[0] = (BYTE)(commid & 0xFF); + buf[1] = (BYTE)((commid & 0xFF00) << 8); + buf[2] = (BYTE)((commid & 0xFF0000) << 16); + buf[3] = (BYTE)((commid & 0xFF000000) << 24); + + buf[4] = (BYTE)(iYkNo & 0xFF); + buf[5] = (BYTE)((iYkNo & 0xFF00) << 8); + buf[6] = (BYTE)((iYkNo & 0xFF0000) << 16); + buf[7] = (BYTE)((iYkNo & 0xFF000000) << 24); + + switch((rtumsg->MsgData[12] & 0xc0) >> 6) + { + case 0:// + buf[8] = STEP_YKYT_EXEC; + break; + case 2: + buf[8] = STEP_YKYT_SELECT; + break; + case 3: + buf[8] = STEP_YKYT_CANCEL; + break; + default: + buf[8] = STEP_YKYT_NOEXEC; + break; + } + switch(rtumsg->MsgData[12] & 0x03) + { + case 0: + case 3: + buf[8] = STEP_YKYT_NOEXEC; + break; + default: + buf[9] = (rtumsg->MsgData[12] & 0x03) | 0x80; + break; + } + + if(ShmGetDispYkYtFlag()) + { +#ifdef _DEBUG_MSG_ + //sprintf(szbuf, "端口%d 链路地址=%d 装置地址%d RII=0x%02x, 遥控点号=%d, op=0x%02x!!!\n", + // commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYkNo, rtumsg->MsgData[12]); + //DebugPrint(szbuf); + sprintf(szbuf, "TIP_(%04d): commid=%d linkaddr=%d devaddr=%d RII=0x%02x ykpnt=%d, op=0x%02x.\n", + _getpid(), commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYkNo, rtumsg->MsgData[12]); + DebugPrint(szbuf); +#endif + } + + Buban103YkYtProcess(commid, buf, 10); + } +} + +void Buban103YtAck(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP):65 + //rtumsg->MsgData[6]; + + // 可变结构限定词(VSQ):0x81 + //rtumsg->MsgData[7]; + + // 传送原因(COT) + //rtumsg->MsgData[8]; + //M_CAUSE_REMOTE : // 远方操作 + + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + + // 功能类型(FUN): 1 + //rtumsg->MsgData[10]; + + // 信息序号(INF): 48 --- 75 + //rtumsg->MsgData[11]; + + // 信息序号(RCC) + //rtumsg->MsgData[12]; + + // 返回信息标识符(RII) + //rtumsg->MsgData[13]; + + int commid; + int iYtNo; + BYTE buf[16]; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + if(pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10 未配置遥控点!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + iYtNo = rtumsg->MsgData[11] - 48 + pDevParam->m_sDevParam.m_iYtStartPnt; + if(iYtNo >= 0) + { + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + buf[0] = (BYTE)(commid & 0xFF); + buf[1] = (BYTE)((commid & 0xFF00) << 8); + buf[2] = (BYTE)((commid & 0xFF0000) << 16); + buf[3] = (BYTE)((commid & 0xFF000000) << 24); + + buf[4] = (BYTE)(iYtNo & 0xFF); + buf[5] = (BYTE)((iYtNo & 0xFF00) << 8); + buf[6] = (BYTE)((iYtNo & 0xFF0000) << 16); + buf[7] = (BYTE)((iYtNo & 0xFF000000) << 24); + + switch((rtumsg->MsgData[12] & 0xc0) >> 6) + { + case 0:// + buf[8] = STEP_YT_EXEC; + break; + case 2: + buf[8] = STEP_YT_SELECT; + break; + case 3: + buf[8] = STEP_YT_CANCEL; + break; + default: + buf[8] = STEP_YKYT_NOEXEC; + break; + } + switch(rtumsg->MsgData[12] & 0x03) + { + case 0: + case 3: + buf[8] = STEP_YKYT_NOEXEC; + break; + default: + buf[9] = (rtumsg->MsgData[12] & 0x03) | 0x80; + break; + } + + if(ShmGetDispYkYtFlag()) + { +#ifdef _DEBUG_MSG_ + //sprintf(szbuf, "端口%d 链路地址=%d 装置地址%d RII=0x%02x, 遥调点号=%d, op=0x%02x!!!\n", + // commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYtNo, rtumsg->MsgData[12]); + //DebugPrint(szbuf); + sprintf(szbuf, "TIP_(%04d): commid=%d linkaddr=%d devaddr=%d RII=0x%02x ytpnt=%d, op=0x%02x.\n", + _getpid(), commid, rtumsg->MsgData[5], rtumsg->MsgData[9], rtumsg->MsgData[13], iYtNo, rtumsg->MsgData[12]); + DebugPrint(szbuf); +#endif + } + + Buban103YkYtProcess(commid, buf, 10); + } +} + +void Buban103GDprocessWithAI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid; + BYTE u8KOD, u8INF, u8NGD, u8DataType; + BYTE u8DataNum, u8DataLen; + int aipnt, aistart, stn, iOffset; + AI_DEF pntmsg; + VALUEDEF sValue; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + iOffset = 14; + if(iOffset >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(AI)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + stn = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStationNo; + if(stn <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(AI)_Group=%d 信息不写入数据库!!!",\ + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr,\ + pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iGroupNo); + DebugPrint(szbuf); +#endif + } + + u8INF = rtumsg->MsgData[11]; + u8NGD = rtumsg->MsgData[13] & 0x3f; + aistart = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStartPntNo; + + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(AI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(AI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + break; + } + + // 组号和条目号 + aipnt = aistart + rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + u8KOD = rtumsg->MsgData[iOffset++]; + if(KOD_ACTUALVALUE != u8KOD) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(AI)处理时,KOD=%d不在处理范围内,只处理实际值数据!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 3; + continue; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; jMsgData[iOffset], &sValue, u8DataType, u8DataLen)) + { + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + pntmsg.RawValue = (WORD)sValue.m_unValue.m_uValue; + SetPntMsg(stn-1, aipnt+j, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_INT: + pntmsg.RawValue = (WORD)sValue.m_unValue.m_iValue; + SetPntMsg(stn-1, aipnt+j, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_FLOAT: + pntmsg.RawValue = (WORD)sValue.m_unValue.m_fValue; + SetPntMsg(stn-1, aipnt+j, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_CONTROL: + pntmsg.RawValue = (WORD)sValue.m_unValue.m_dwValue; + SetPntMsg(stn-1, aipnt+j, &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_NO:// 无数据 + case DT_STRING: + case DT_BINARY: + default: + break; + } + } + iOffset += u8DataLen; + } + } +} + +void Buban103GDprocessWithDI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid; + BYTE u8KOD, u8INF, u8NGD, u8DataType; + BYTE u8DataNum, u8DataLen; + int dipnt, distart, stn, iOffset; + DI_DEF pntmsg; + VALUEDEF sValue; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + iOffset = 14; + if(iOffset >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(DI)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + stn = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStationNo; + if(stn <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(DI)_Group=%d 信息不写入数据库!!!",\ + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr,\ + pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iGroupNo); + DebugPrint(szbuf); +#endif + } + + u8INF = rtumsg->MsgData[11]; + u8NGD = rtumsg->MsgData[13] & 0x3f; + distart = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStartPntNo; + + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(DI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(DI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + break; + } + + // 组号和条目号 + dipnt = distart + rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + u8KOD = rtumsg->MsgData[iOffset++]; + if(KOD_ACTUALVALUE != u8KOD) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(DI)处理时,KOD=%d不在处理范围内,只处理实际值数据!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 3; + continue; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; jMsgData[iOffset], &sValue, u8DataType, u8DataLen)) + { + switch(sValue.m_iDataType) + { + case DT_BINARY: + if(sValue.m_iDataNum > 1) + { + if((sValue.m_unValue.m_dwValue > 0)\ + && (sValue.m_unValue.m_dwValue < 3)) + { + pntmsg.Status = (BYTE)(sValue.m_unValue.m_dwValue - 1); + } + else + { + pntmsg.Status = 0; + } + } + else + { + pntmsg.Status = (BYTE)(sValue.m_unValue.m_dwValue); + } + SetPntMsg(stn-1, dipnt+j, &pntmsg, DI_PNT_TYPE, PNT_STATUS); + break; + case DT_UINT:// 无符号整型数 + if(sValue.m_unValue.m_uValue != 0) + { + pntmsg.Status = 1; + } + else + { + pntmsg.Status = 0; + } + SetPntMsg(stn-1, dipnt+j, &pntmsg, DI_PNT_TYPE, PNT_STATUS); + break; + case DT_INT: + if(sValue.m_unValue.m_iValue != 0) + { + pntmsg.Status = 1; + } + else + { + pntmsg.Status = 0; + } + SetPntMsg(stn-1, dipnt+j, &pntmsg, DI_PNT_TYPE, PNT_STATUS); + break; + case DT_FLOAT: + case DT_CONTROL: + case DT_NO:// 无数据 + case DT_STRING: + default: + break; + } + } + iOffset += u8DataLen; + } + } +} + +void Buban103GDprocessWithPI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid; + BYTE u8KOD, u8INF, u8NGD, u8DataType; + BYTE u8DataNum, u8DataLen; + int pipnt, pistart, stn, iOffset; + PI_DEF pntmsg; + VALUEDEF sValue; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + iOffset = 14; + if(iOffset >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(PI)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + stn = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStationNo; + if(stn <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(PI)_Group=%d 信息不写入数据库!!!",\ + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr,\ + pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iGroupNo); + DebugPrint(szbuf); +#endif + } + + u8INF = rtumsg->MsgData[11]; + u8NGD = rtumsg->MsgData[13] & 0x3f; + pistart = pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx].m_iStartPntNo; + + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(PI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(PI)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + break; + } + + // 组号和条目号 + pipnt = pistart + rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + u8KOD = rtumsg->MsgData[iOffset++]; + if(KOD_ACTUALVALUE != u8KOD) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(PI)处理时,KOD=%d不在处理范围内,只处理实际值数据!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 3; + continue; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; jMsgData[iOffset], &sValue, u8DataType, u8DataLen)) + { + switch(sValue.m_iDataType) + { + + case DT_UINT:// 无符号整型数 + pntmsg.RawValue = sValue.m_unValue.m_uValue; + SetPntMsg(stn-1, pipnt+j, &pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_INT: + pntmsg.RawValue = sValue.m_unValue.m_iValue; + SetPntMsg(stn-1, pipnt+j, &pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_FLOAT: + pntmsg.RawValue = (u_long)sValue.m_unValue.m_fValue; + SetPntMsg(stn-1, pipnt+j, &pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + break; + case DT_CONTROL: + case DT_NO:// 无数据 + case DT_BINARY: + case DT_STRING: + default: + break; + } + } + iOffset += u8DataLen; + } + } +} + +void Buban103GDprocessWithPAI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid, iItemNum, iStrLen; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + int iOffset; + double fValue; + BOOL bFirst, bNumChanged; + VALUEDEF sValue; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + if(pGroupParam->m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据空间为零!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + // 只处理实际值 + if(KOD_ACTUALVALUE != u8KOD) + { + return; + } + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(TRUE == bFirst) + { + if(u8ItemNo == 0) + { + pGroupParam->m_u32CurPntNo = 1; + } + else if(u8ItemNo <= pGroupParam->m_iStartItemNo) + { + pGroupParam->m_u32CurPntNo = 1; + } + + if((M_INF_WRITEITEMWITHACK == u8INF) + && (pGroupParam->m_bInit == FALSE)) + { + for(j=0; jm_iPntNum; j++) + { + if(pGroupParam->m_pu8GIN[j] == u8ItemNo) + { + break; + } + } + + if(j >= pGroupParam->m_iPntNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,不匹配的GIN=%d!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8ItemNo, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + pGroupParam->m_u32CurPntNo = j+1; + } + bFirst = FALSE; + } + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + //pGroupParam->m_pu8DataLen[pGroupParam->m_u32CurPntNo-1] = u8DataLen; + //pGroupParam->m_pu8DataType[pGroupParam->m_u32CurPntNo-1] = u8DataType; + pGroupParam->m_pu8GIN[pGroupParam->m_u32CurPntNo-1] = u8ItemNo+j; + } + + if(GetOneValueOfASDU10(&rtumsg->MsgData[iOffset], &sValue, u8DataType, u8DataLen) == FALSE) + { + iOffset += u8DataLen; + continue; + } + iOffset += u8DataLen; + + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + fValue = sValue.m_unValue.m_uValue; + break; + case DT_INT: + fValue = sValue.m_unValue.m_iValue; + break; + case DT_FLOAT: + fValue = sValue.m_unValue.m_fValue; + break; + case DT_CONTROL: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_STRING: + fValue = -1; + break; + case DT_BINARY: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_NO:// 无数据 + default: + fValue = -1; + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + if((u8ItemNo == 0) && (j == 0)) + { + if((fValue > 0) && (KOD_ACTUALVALUE == u8KOD)) + { + if((int)fValue > pGroupParam->m_iPntNum) + { + //pGroupParam->m_iPntNum = (int)sValue.m_unValue.m_uValue; + bNumChanged = TRUE; + } + else + { + pGroupParam->m_iPntNum = (int)fValue; + } + } + } + } + if(TRUE == bNumChanged) + { + //freeallfixmemory + } + + if(DT_STRING != sValue.m_iDataType) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_fValue = (float)fValue; + } + else + { + // 描述或者量纲 + if(KOD_DESCRIPTION == u8KOD) + { + iStrLen = sizeof(pGroupParam->m_psDataInfo->m_szName)-1; + if(iStrLen > sValue.m_iDataNum) + { + iStrLen = sValue.m_iDataNum; + } + memcpy(pGroupParam->m_psDataInfo->m_szName, sValue.m_szValue, iStrLen); + pGroupParam->m_psDataInfo->m_szName[iStrLen] = 0; + } + else if(KOD_DIMENSION == u8KOD) + { + iStrLen = sizeof(pGroupParam->m_psDataInfo->m_szUnit)-1; + if(iStrLen > sValue.m_iDataNum) + { + iStrLen = sValue.m_iDataNum; + } + memcpy(pGroupParam->m_psDataInfo->m_szUnit, sValue.m_szValue, iStrLen); + pGroupParam->m_psDataInfo->m_szUnit[iStrLen] = 0; + } + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_u32DataID = u8DataType; + } + + pGroupParam->m_u32CurPntNo++; + } + } + + if(pGroupParam->m_iPntNum > 0) + { + if((int)pGroupParam->m_u32CurPntNo >= pGroupParam->m_iPntNum) + { + pGroupParam->m_bInit = TRUE; + pGroupParam->m_u32CurPntNo = 1; + } + } +} + +void Buban103GDprocessWithPDI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + Buban103GDprocessWithPAI(rtumsg, psDevAddrParam, iGroupIdx); +} + +void Buban103GDprocessWithPFIX(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid, iItemNum, iStrLen; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + int iOffset; + double fValue; + BOOL bFirst, bNumChanged; + VALUEDEF sValue; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + if(pGroupParam->m_iPntNum > 0) + { + if(pGroupParam->m_pu8DataLen == NULL) + { + pGroupParam->m_pu8DataLen = (BYTE *)HEAP_MALLOC(pGroupParam->m_iPntNum*sizeof(BYTE)); + Buban103DispMalloc(commid, pGroupParam->m_iPntNum*sizeof(BYTE)); + } + if(pGroupParam->m_pu8DataType == NULL) + { + pGroupParam->m_pu8DataType = (BYTE *)HEAP_MALLOC(pGroupParam->m_iPntNum*sizeof(BYTE)); + Buban103DispMalloc(commid, pGroupParam->m_iPntNum*sizeof(BYTE)); + } + if(pGroupParam->m_pu8GIN == NULL) + { + pGroupParam->m_pu8GIN = (BYTE *)HEAP_MALLOC(pGroupParam->m_iPntNum*sizeof(BYTE)); + Buban103DispMalloc(commid, pGroupParam->m_iPntNum*sizeof(BYTE)); + } + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据空间为零!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + // 只处理实际值 + if(KOD_ACTUALVALUE != u8KOD) + { + return; + } + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(TRUE == bFirst) + { + if(u8ItemNo == 0) + { + pGroupParam->m_u32CurPntNo = 1; + } + else if(u8ItemNo <= pGroupParam->m_iStartItemNo) + { + pGroupParam->m_u32CurPntNo = 1; + } + + if((M_INF_WRITEITEMWITHACK == u8INF) + && (pGroupParam->m_bInit == FALSE)) + { + for(j=0; jm_iPntNum; j++) + { + if(pGroupParam->m_pu8GIN[j] == u8ItemNo) + { + break; + } + } + + if(j >= pGroupParam->m_iPntNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,不匹配的GIN=%d!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8ItemNo, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + pGroupParam->m_u32CurPntNo = j+1; + } + bFirst = FALSE; + } + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_pu8DataLen[pGroupParam->m_u32CurPntNo-1] = u8DataLen; + pGroupParam->m_pu8DataType[pGroupParam->m_u32CurPntNo-1] = u8DataType; + pGroupParam->m_pu8GIN[pGroupParam->m_u32CurPntNo-1] = u8ItemNo+j; + } + + if(GetOneValueOfASDU10(&rtumsg->MsgData[iOffset], &sValue, u8DataType, u8DataLen) == FALSE) + { + iOffset += u8DataLen; + continue; + } + iOffset += u8DataLen; + + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + fValue = sValue.m_unValue.m_uValue; + break; + case DT_INT: + fValue = sValue.m_unValue.m_iValue; + break; + case DT_FLOAT: + fValue = sValue.m_unValue.m_fValue; + break; + case DT_CONTROL: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_STRING: + fValue = -1; + break; + case DT_BINARY: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_NO:// 无数据 + default: + fValue = -1; + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + if((u8ItemNo == 0) && (j == 0)) + { + if((fValue > 0) && (KOD_ACTUALVALUE == u8KOD)) + { + if((int)fValue > pGroupParam->m_iPntNum) + { + //pGroupParam->m_iPntNum = (int)sValue.m_unValue.m_uValue; + bNumChanged = TRUE; + } + else + { + pGroupParam->m_iPntNum = (int)fValue; + } + } + } + } + if(TRUE == bNumChanged) + { + //freeallfixmemory + } + + if(DT_STRING != sValue.m_iDataType) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_fValue = (float)fValue; + } + else + { + // 描述或者量纲 + if(KOD_DESCRIPTION == u8KOD) + { + iStrLen = sizeof(pGroupParam->m_psDataInfo->m_szName)-1; + if(iStrLen > sValue.m_iDataNum) + { + iStrLen = sValue.m_iDataNum; + } + memcpy(pGroupParam->m_psDataInfo->m_szName, sValue.m_szValue, iStrLen); + pGroupParam->m_psDataInfo->m_szName[iStrLen] = 0; + } + else if(KOD_DIMENSION == u8KOD) + { + iStrLen = sizeof(pGroupParam->m_psDataInfo->m_szUnit)-1; + if(iStrLen > sValue.m_iDataNum) + { + iStrLen = sValue.m_iDataNum; + } + memcpy(pGroupParam->m_psDataInfo->m_szUnit, sValue.m_szValue, iStrLen); + pGroupParam->m_psDataInfo->m_szUnit[iStrLen] = 0; + } + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_u32DataID = u8DataType; + } + + pGroupParam->m_u32CurPntNo++; + } + } + + if(pGroupParam->m_iPntNum > 0) + { + if((int)pGroupParam->m_u32CurPntNo >= pGroupParam->m_iPntNum) + { + pGroupParam->m_bInit = TRUE; + pGroupParam->m_u32CurPntNo = 1; + } + } + + // wen 2004.01.06 写定值确认 + if((M_CAUSE_WRITEACK == rtumsg->MsgData[8]) + || (M_CAUSE_WRITECONFIRM == rtumsg->MsgData[8])) + { + //ptrProHead->uFuncCode = hWRITEFIXACK; + //RtuProtocolBaoHuCommand(&msg); + } + else if(M_CAUSE_WRITENAK == rtumsg->MsgData[8]) + { + //ptrProHead->uFuncCode = hWRITEFIXNAK; + //RtuProtocolBaoHuCommand(&msg); + } +} + +void Buban103GDprocessWithPEVENT(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, k, commid, iItemNum; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + int iOffset; + BOOL bFirst, bNumChanged; + + time_t iTime; + WORD wMillSeconds, wTime, wFault; + struct tm *ptrtm; + + SOE_DEF sSoeData; + + DBORIENTATION *pDataUnit; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + pDataUnit = &pDevParam->m_sDevParam.m_sDiDBOrientation; + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + // 只处理实际值 + if(KOD_ACTUALVALUE != u8KOD) + { + return; + } + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + for(k=0; km_iPntNum; k++) + { + if((pDataUnit->m_psDataInfo[k].m_u8Asdu == 10)\ + && (pDataUnit->m_psDataInfo[k].m_u8Inf == (u8ItemNo+j))\ + && (pDataUnit->m_psDataInfo[k].m_u8Fun == pGroupParam->m_iGroupNo)) + { + break; + } + } + + + if(k >= pDataUnit->m_iPntNum) + { + iOffset += u8DataLen; + continue; + } + + switch(u8DataType) + { + case DATAID_WITHTIME: // 带时标的报文 + switch(rtumsg->MsgData[iOffset] & 0x03) + { + case 1: + sSoeData.bStatus = 0; + break; + case 2: + sSoeData.bStatus = 1; + break; + case 3: + case 0: + default: + sSoeData.bStatus = 0; + break; + } + time(&iTime); + ptrtm = localtime(&iTime); + if(ptrtm->tm_hour < (rtumsg->MsgData[iOffset+4] & 0x1f)) + { + iTime -= 24 * 3600; + ptrtm = localtime(&iTime); + } + ptrtm->tm_hour = rtumsg->MsgData[iOffset+4] & 0x1f; + ptrtm->tm_min = rtumsg->MsgData[iOffset+3] & 0x3f; + wMillSeconds = rtumsg->MsgData[iOffset+1] + rtumsg->MsgData[iOffset+2]*256; + ptrtm->tm_sec = wMillSeconds / 1000; + + sSoeData.iPntNo = pDataUnit->m_iStartPntNo+k; + sSoeData.u8Type = 1;// ASDU1 + sSoeData.wFaultNo = 0; + sSoeData.u8ProvFun = pDataUnit->m_psDataInfo[k].m_u8ProvFun; + sSoeData.u8ProvInf = pDataUnit->m_psDataInfo[k].m_u8ProvInf; + sSoeData.wRelativeTime = 0; + sSoeData.SoeTime.Year = ptrtm->tm_year+1900; + sSoeData.SoeTime.Month = (BYTE)(ptrtm->tm_mon+1); + sSoeData.SoeTime.Day = (BYTE)(ptrtm->tm_mday); + sSoeData.SoeTime.Hour = (BYTE)(ptrtm->tm_hour); + sSoeData.SoeTime.Min = (BYTE)(ptrtm->tm_min); + sSoeData.SoeTime.Sec = (BYTE)(ptrtm->tm_sec); + sSoeData.SoeTime.mSec = wMillSeconds; + SetPntMsg(pDataUnit->m_iStnNo-1, pDataUnit->m_iStartPntNo+k, (void *)&sSoeData, DI_PNT_TYPE, PNT_SOE_TIME_EX); + break; + + case DATAID_WITHTIMESPACE:// 带相对时标的报文 + switch(rtumsg->MsgData[iOffset] & 0x03) + { + case 1: + sSoeData.bStatus = 0; + break; + case 2: + sSoeData.bStatus = 1; + break; + case 3: + case 0: + default: + sSoeData.bStatus = 0; + break; + } + wTime = rtumsg->MsgData[iOffset+1] + rtumsg->MsgData[iOffset+2]*256; + wFault= rtumsg->MsgData[iOffset+3] + rtumsg->MsgData[iOffset+4]*256; + time(&iTime); + ptrtm = localtime(&iTime); + if(ptrtm->tm_hour < (rtumsg->MsgData[iOffset+8] & 0x1f)) + { + iTime -= 24 * 3600; + ptrtm = localtime(&iTime); + } + ptrtm->tm_hour = rtumsg->MsgData[iOffset+8] & 0x1f; + ptrtm->tm_min = rtumsg->MsgData[iOffset+7] & 0x3f; + wMillSeconds = rtumsg->MsgData[iOffset+5] + rtumsg->MsgData[iOffset+6]*256; + ptrtm->tm_sec = wMillSeconds / 1000; + + sSoeData.iPntNo = pDataUnit->m_iStartPntNo+k; + sSoeData.u8Type = 2;// ASDU2 + sSoeData.wFaultNo = wFault; + sSoeData.u8ProvFun = pDataUnit->m_psDataInfo[k].m_u8ProvFun; + sSoeData.u8ProvInf = pDataUnit->m_psDataInfo[k].m_u8ProvInf; + sSoeData.wRelativeTime = wTime; + sSoeData.SoeTime.Year = ptrtm->tm_year+1900; + sSoeData.SoeTime.Month = (BYTE)(ptrtm->tm_mon+1); + sSoeData.SoeTime.Day = (BYTE)(ptrtm->tm_mday); + sSoeData.SoeTime.Hour = (BYTE)(ptrtm->tm_hour); + sSoeData.SoeTime.Min = (BYTE)(ptrtm->tm_min); + sSoeData.SoeTime.Sec = (BYTE)(ptrtm->tm_sec); + sSoeData.SoeTime.mSec = wMillSeconds; + SetPntMsg(pDataUnit->m_iStnNo-1, pDataUnit->m_iStartPntNo+k, (void *)&sSoeData, DI_PNT_TYPE, PNT_SOE_TIME_EX); + break; + default: + break; + } + + iOffset += u8DataLen; + } + } +} + +void Buban103GIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + // 类型标识(TYP):11 + //rtumsg->MsgData[6]; + + // 可变结构限定词(VSQ):0x81 + //rtumsg->MsgData[7]; + + // 传送原因(COT) + //rtumsg->MsgData[8]; + //M_CAUSE_READWITHVALIDDATA : 对通用分类读命令有效数据响应 + //M_CAUSE_READWITHINVALIDDATA : 对通用分类读命令无效数据响应 + + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + + // 功能类型(FUN): 254(0xfe) + //rtumsg->MsgData[10]; + + // 信息序号(INF): + // 读单个条目的目录 : 243 + //rtumsg->MsgData[11]; + + // 返回信息标识符(RII) + //rtumsg->MsgData[12]; + + // 通用分类标识序号(GIN):条目号和组号 + //rtumsg->MsgData[13]; + + // 描述元素的数目(NDE) + //rtumsg->MsgData[15]; + + // 以下为多个通用分类数据 + // 描述类别(KOD) + // 无所指定的描述类别 : KOD_NOSPECIFIED(0) + // 实际值 : KOD_ACTUALVALUE(1) + // 缺省值 : KOD_DEFAULTVALUE(2) + // 量程(最大值、最小值、步长) : KOD_RANGE(3) + // 备用 : KOD_BACKUP1(4) + // 精度(n,m) : KOD_PRECISION(5) + // 因子 : KOD_FACTOR(6) + // 参比 : KOD_REFERENCE(7) + // 列表 : KOD_ENUMERATION(8) + // 量纲 : KOD_DIMENSION(9) + // 描述 : KOD_DESCRIPTION(10) + // 备用 : KOD_BACKUP2(11) + // 口令条目 : KOD_PASSWORD(12) + // 只读 : KOD_READONLY(13) + // 只写 : KOD_WRITEONLY(14) + // 备用 : KOD_BACKUP3(15) + // 备用 : KOD_BACKUP4(16) + // 备用 : KOD_BACKUP5(17) + // 备用 : KOD_BACKUP6(18) + // 相应的功能类型和信息序号 : KOD_CORFUNCANDINF(19) + // 相应的事件 : KOD_COREVENT(20) + // 列表的文本阵列 : KOD_ENUMTEXTARRAY(21) + // 列表的值阵列 : KOD_ENUMVALUEARRAY(22) + // 相关联的条目 : KOD_RELATEDENTRIES(23) + //rtumsg->MsgData[16]; + + // 数据类型描述 + //rtumsg->MsgData[17]; + //DATAID_NO : 无数据 + //DATAID_OS8ASCII : 8位ASCII + //DATAID_BSTRING : 字符串 + //DATAID_UIX : 无符号整数 + //DATAID_INT : 整数 + //DATAID_UFLOAT : 无符号浮点数 + //DATAID_FLOAT : 浮点数 + //DATAID_754SHORT : R32.23 IEEE 标准754短实数 + //DATAID_754REAL : R64.53 IEEE 标准754实数 + //DATAID_DOUBLE : 双点信息 + //DATAID_SINGLE : 单点信息 + //DATAID_13BITS : 带品质描述的被测值(13BITS) + //DATAID_SORTIDNO : 通用分类标识序号 + //DATAID_WITHTIME : 带时标的报文 + //DATAID_WITHTIMESPACE : 带相对时标的报文 + //DATAID_STRUCT : 数据结构 + + // 数据尺寸 + //rtumsg->MsgData[18] + + // 数量 + //rtumsg->MsgData[19] + + // 通用分类标识数据(GID) + // 长度根据以上描述 + + // 2 ... n 个通用分类数据 +} + +void Buban103SynTime(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + //char szDbg[128]; + int commid; + DAY_TIME stime; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + //DebugPrint("sync time."); + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + //DebugPrint("sync time hello1."); + // 如果非时间同步原因,则不进行对时 + if(M_CAUSE_CHECKTIME != rtumsg->MsgData[8]) + { + return; + } + + //DebugPrint("sync time hello2."); + // 上对时 + if(1 != pPortParam->m_psBaoHu->CheckTime) + { + return; + } + + stime.mSec = rtumsg->MsgData[12] + rtumsg->MsgData[13]*256; + stime.Sec = stime.mSec / 1000; + stime.mSec = stime.mSec % 1000; + stime.Min = rtumsg->MsgData[14] & 0x3F; + stime.Hour = rtumsg->MsgData[15] & 0x1F; + stime.Day = rtumsg->MsgData[16] & 0x1F; + stime.Month = rtumsg->MsgData[17] & 0x0F; + stime.Year = rtumsg->MsgData[18] & 0x7F + 2000; + + //sprintf(szDbg, "time:%04d-%02d-%02d_%02d:%02d:%02d.%03d\n", + // stime.Year, stime.Month, stime.Day, stime.Hour, + // stime.Min, stime.Sec, stime.mSec); + //DebugPrint(szDbg); + + SetLocalTimeEx(&stime); +} + +void Buban103EXPIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int i, commid; + int pipnt; + PI_DEF pntmsg; + DBORIENTATION *pDataUnit; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + pDataUnit = &pDevParam->m_sDevParam.m_sPiDBOrientation; + + if(pDataUnit->m_iStnNo < 1) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d SIEMENS扩展电度信息不写入数据库!!!", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr); + DebugPrint(szbuf); +#endif + return; + } + + for(i=0; im_iPntNum; i++) + { + if((pDataUnit->m_psDataInfo[i].m_u8Fun == rtumsg->MsgData[10])\ + && (pDataUnit->m_psDataInfo[i].m_u8Inf == rtumsg->MsgData[11])) + { + break; + } + } + + if(i >= pDataUnit->m_iPntNum) + { + return; + } + + pipnt = pDataUnit->m_iStartPntNo + i; + pntmsg.RawValue = rtumsg->MsgData[12] + rtumsg->MsgData[13]*256\ + +rtumsg->MsgData[14]*256*256 + (rtumsg->MsgData[15]&0x0f)*256*256*256; + + // 符号位 + if(rtumsg->MsgData[15] & 0x10) + { + pntmsg.RawValue |= 0xF0000000; + } + + SetPntMsg(pDataUnit->m_iStnNo-1, pipnt, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); +} + +// 扰动数据处理开始 +// 扰动数据表处理 +void Buban103LRDprocess(RTUMSG *rtumsg) +{} + +// 扰动数据传输准备就绪 +void Buban103RTDprocess(RTUMSG *rtumsg) +{} + +// 带标志的状态变位传输准备就绪 +void Buban103RTTprocess(RTUMSG *rtumsg) +{} + +// 带标志的状态变位传输 +void Buban103TOTprocess(RTUMSG *rtumsg) +{} + +// 被记录的通道传输准备就绪 +void Buban103RTCprocess(RTUMSG *rtumsg) +{} + +// 传送扰动值 +void Buban103TOVprocess(RTUMSG *rtumsg) +{} + +// 带标志的状态变位、通道、扰动数据传输结束 +void Buban103EOTprocess(RTUMSG *rtumsg) +{} +// 扰动数据处理结束 + +// 写通道扰动数据到文件中 +BOOL Buban103WriteACCDatatoFile(RTUMSG *rtumsg) +{ + return FALSE; +} + +// 读录波数据文件头 +void Buban103GetFileHead(char *ptrDataHead, size_t *piNOF, size_t *piNOC, size_t *piNOE, size_t *piINT) +{} + +// 读录波数据记录时间 +//void Buban103GetTime(char *ptrDataHead, SYSTEMTIME *ptrtm) +//{} + +// 读录波数据模拟量头 +void Buban103ProcessAiHead(char *ptrDataHead, DISTURBANCEAIDATA *pAiData) +{} + +// 转换临时文件为可用文件 +void Buban103tmpFileChangetodatFile(char *sztmpFileName) +{} + +// 生成CFG文件 +//void Buban103MakeCFGFile(int iStationNo, pDISTURBANCEDIDATA ptrDi, pDISTURBANCEAIDATA ptrAi, FILE *fp, char *szInfFile, SYSTEMTIME *tm) +//{} + +// 生成DAT文件 +void Buban103MakeDATFile(pDISTURBANCEDIDATA ptrDi, pDISTURBANCEAIDATA ptrAi, FILE *fp) +{} + +//=========================以下为Buban103转发数据功能=======================// +//***************************************************************************/ +//* 插入SOE数据函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_32 selidx : 端口索引号 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//* PROV_SOE *pSoeMsg : 转发SOE数据 */ +//*返回值:BOOL retval : 插入SOE数据时是否覆盖(缓冲区是否已满) */ +//***************************************************************************/ +BOOL ProvInsertSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, SOE_DEF *pSoeMsg) +{ + BOOL bReturn; + short front, rear; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + { + return FALSE; + } + + front = pProvDevParam->m_sProvSoe.m_shFront; + rear = pProvDevParam->m_sProvSoe.m_shRear; + if(pProvDevParam->m_sProvSoe.m_shSoeNum >= PROV_SOE_MAX) + { + // 缓冲区已满 + memcpy((void *)&pProvDevParam->m_sProvSoe.m_sSoeData[rear], + (void *)pSoeMsg, sizeof(SOE_DEF)); + pProvDevParam->m_sProvSoe.m_shFront = (front + 1) % PROV_SOE_MAX; + pProvDevParam->m_sProvSoe.m_shRear = (rear + 1) % PROV_SOE_MAX; + bReturn = FALSE; + } + else + { + memcpy((void *)&pProvDevParam->m_sProvSoe.m_sSoeData[rear], + (void *)pSoeMsg, sizeof(SOE_DEF)); + pProvDevParam->m_sProvSoe.m_shRear = (rear + 1) % PROV_SOE_MAX; + pProvDevParam->m_sProvSoe.m_shSoeNum++; + bReturn = TRUE; + } + + return bReturn; +} + +//***************************************************************************/ +//* 从缓冲区取并且删除SOE数据函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_32 selidx : 端口索引号 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//* PROV_SOE *pSoeMsg : SOE数据指针 */ +//*返回值:BOOL retval : 获取SOE数据是否成功 */ +//***************************************************************************/ +BOOL ProvGetAndDelSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, SOE_DEF *pSoeMsg) +{ + short front, rear; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + { + return FALSE; + } + + front = pProvDevParam->m_sProvSoe.m_shFront; + rear = pProvDevParam->m_sProvSoe.m_shRear; + if(pProvDevParam->m_sProvSoe.m_shSoeNum <= 0) + { + pProvDevParam->m_sProvSoe.m_shSoeNum = 0; + pProvDevParam->m_sProvSoe.m_shFront = 0; + pProvDevParam->m_sProvSoe.m_shRear = 0; + return FALSE; + } + + memcpy((void *)pSoeMsg, (void *)&pProvDevParam->m_sProvSoe.m_sSoeData[front], sizeof(SOE_DEF)); + pProvDevParam->m_sProvSoe.m_shFront = (front + 1) % PROV_SOE_MAX; + pProvDevParam->m_sProvSoe.m_shSoeNum--; + + return TRUE; +} + +BOOL ProvGetNoXSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, int iNo, SOE_DEF *pSoeMsg) +{ + short rear; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + { + return FALSE; + } + + if(pProvDevParam->m_sProvSoe.m_shSoeNum <= 0) + { + pProvDevParam->m_sProvSoe.m_shSoeNum = 0; + pProvDevParam->m_sProvSoe.m_shFront = 0; + pProvDevParam->m_sProvSoe.m_shRear = 0; + return FALSE; + } + + iNo = iNo % PROV_SOE_MAX; + rear = pProvDevParam->m_sProvSoe.m_shRear - iNo - 1; + if(rear < 0) + { + rear += PROV_SOE_MAX; + } + memcpy((void *)pSoeMsg, (void *)&pProvDevParam->m_sProvSoe.m_sSoeData[rear], sizeof(SOE_DEF)); + + return TRUE; +} + +//***************************************************************************/ +//* 转发一类数据是否存在函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +BOOL ProvHaveClassOne(u_32 commid, DEVADDRPARAM *psDevAddrParam, BOOL bCheckDiChange) +{ + int i; + BOOL bACD, bQueryAllDev; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + bACD = FALSE; + if(ProvHaveSoeData(commid) > 0) + { + bACD = TRUE; + } + else + { + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + bQueryAllDev = TRUE; + } + else + { + bQueryAllDev = FALSE; + } + + // 是否转发遥信变位,一般将其屏蔽 + if(TRUE == bCheckDiChange) + { + if(pPortParam->m_psBaoHu != NULL) + { + if(pPortParam->m_psBaoHu->DiChange == TRUE) + { + bACD = TRUE; + } + } + } + if(bACD == FALSE) + { + for(i=0; im_iDevNum; i++) + { + if(bQueryAllDev == TRUE) + { + psDevAddrParam->m_iDevIdx = i; + } + else + { + if(i >= 1) + { + break; + } + + // 该项判断应该不需要存在 + //if(psDevAddrParam->m_iDevIdx >= pLinkParam->m_iDevNum) + //{ + // break; + //} + } + pProvDevParam = &pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx]; + + // 如果在总查询过程中 + //if((pProvDevParam->m_bProvQuery == TRUE) || (pProvDevParam->m_sProvGroupParam.m_bFinished == FALSE)) + if(pProvDevParam->m_bProvQuery == TRUE) + { + bACD = TRUE; + break; + } + + if(SingleListHaveData(&pProvDevParam->m_sBaoHuData) > 0) + { + bACD = TRUE; + break; + } + } + } + } + + return bACD; +} + +//***************************************************************************/ +//* 转发链路指令的生成函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_char addr : 间隔设备地址 */ +//* u_char cmdidx : 指令生成索引号 */ +//* BOOL bACD : 一类数据存在标识 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvMakeLinkCommand(u_32 commid, u_char addr, u_char cmdidx, BOOL bACD) +{ + CLPDU_FIX bClpdu_fix; + + memset(&bClpdu_fix, 0, sizeof(CLPDU_FIX)); + switch(cmdidx) + { + case M_CON_NA_3: // 确认帧 + bClpdu_fix.nSTART = 0x10; + if(bACD) + bClpdu_fix.nCONTROL = cmdidx | 0x20; + else + bClpdu_fix.nCONTROL = cmdidx; + bClpdu_fix.nADDR = addr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + case M_BY_NA_3: // 忙帧(确认帧) + case M_NV_NA_3: // 无所要求的数据帧回答 + case M_LKR_NA_3_1: // 链路状态响应帧--链路工作正常 + case M_LKR_NA_3_2: // 链路状态响应帧--链路服务未工作 + case M_LKR_NA_3_3: // 链路状态响应帧--链路服务未实现 + bClpdu_fix.nSTART = 0x10; + if(bACD) + bClpdu_fix.nCONTROL = cmdidx | 0x20; + else + bClpdu_fix.nCONTROL = cmdidx; + bClpdu_fix.nADDR = addr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)&bClpdu_fix, 5); + break; + default: + break; + } +} + +//***************************************************************************/ +//* 转发链路指令的生成函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_char addr : 间隔设备地址 */ +//* u_char cmdidx : 指令生成索引号 */ +//* BOOL bACD : 一类数据存在标识 */ +//* BOOL bClearRecvBuf : 是否清除接收缓冲区 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvMakeLinkCommandEx(u_32 commid, u_char addr, u_char cmdidx, BOOL bACD, BOOL bClearRecvBuf, u_32 cmdtype) +{ + CLPDU_FIX bClpdu_fix; + + memset(&bClpdu_fix, 0, sizeof(CLPDU_FIX)); + switch(cmdidx) + { + case M_CON_NA_3: // 确认帧 + case M_BY_NA_3: // 忙帧(确认帧) + case M_NV_NA_3: // 无所要求的数据帧回答 + case M_LKR_NA_3_1: // 链路状态响应帧--链路工作正常 + case M_LKR_NA_3_2: // 链路状态响应帧--链路服务未工作 + case M_LKR_NA_3_3: // 链路状态响应帧--链路服务未实现 + bClpdu_fix.nSTART = 0x10; + if(bACD) + bClpdu_fix.nCONTROL = cmdidx | 0x20; + else + bClpdu_fix.nCONTROL = cmdidx; + bClpdu_fix.nADDR = addr; + bClpdu_fix.nCS = CalBuban103Lpc(&bClpdu_fix.nCONTROL, 2); + bClpdu_fix.nEnd = 0x16; + PutPollCmdToBuf(commid, cmdtype, 0, (char*)&bClpdu_fix, 5); + break; + default: + break; + } +} + +//***************************************************************************/ +//* 转发链路指令的生成函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_char addr : 间隔设备地址 */ +//* u_char cmdidx : 指令生成索引号 */ +//* BOOL bACD : 一类数据存在标识 */ +//* BYTE bCause : 传送原因 */ +//* u_32 cmdtype : 指令缓冲区类型 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvMakeVarCommand(u_32 commid, u_char linkaddr, u_char addr, \ + u_char cmdidx, BOOL bACD, BYTE bCause, u_32 cmdtype) +{ + u_char tmp[MAX_POLL_CMD_BUF_LEN]; + CLPDU_VARR *ptrClpdu_varr; + i_32 len; + + memset(tmp, 0, sizeof(tmp)); + ptrClpdu_varr = (CLPDU_VARR *)tmp; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = linkaddr; + if(bACD) + ptrClpdu_varr->nCONTROL = 0x28; + else + ptrClpdu_varr->nCONTROL = 0x08; + len = 0; + switch(cmdidx) + { + case M_TM_TA_3://带时标的报文 + break; + case M_TMR_TA_3://具有相对时间的带时标的报文 + break; + case M_MEI_NA_3://被测值I + break; + case M_TME_TA_3://具有相对时间的带时标的被测值 + break; + case M_IRC_NA_3://标识 + len = sizeof(CLPDU_VARR); + tmp[len++] = cmdidx; + tmp[len++] = 0x81; + tmp[len++] = bCause; + tmp[len++] = addr; + tmp[len++] = FUNC_GLOBAL; + tmp[len++] = bCause-1; + tmp[len++] = 2; + memcpy(tmp+len, "SZ-SCADA", 8); + len += 8; + tmp[len++] = 0x01; + len += 3; + break; + case M_SYN_TA_3://时间同步 + break; + case M_TGI_NA_3://总查询(总召唤)终止 + len = sizeof(CLPDU_VARR); + tmp[len++] = cmdidx; + tmp[len++] = 0x81; + tmp[len++] = bCause; + tmp[len++] = addr; + tmp[len++] = FUNC_GLOBAL; + tmp[len++] = 0; + tmp[len++] = 0; + break; + case M_MEII_NA_3://被测值II + break; + case M_GD_NTA_3://通用分类数据 + break; + case M_GI_NTA_3://通用分类标识 + break; + case M_LRD_TA_3://被记录的扰动表 + break; + case M_RTD_TA_3://扰动数据传输准备就绪 + break; + case M_RTC_NA_3://被记录的通道传输准备就绪 + break; + case M_RTT_NA_3://带标志的状态变位传输准备就绪 + break; + case M_TOT_TA_3://传送带标志的状态变位 + break; + case M_TOV_NA_3://传送扰动值 + break; + case M_EOT_TA_3://传送结束 + break; + case M_MEIII_TA_3://带时标的被测值Ⅲ + break; + case M_MEIV_TA_3://带时标的被测值Ⅳ + break; + case M_MEV_TA_3://带时标的被测值Ⅴ + break; + case M_MEVI_TA_3://带时标的被测值Ⅵ + break; + case M_MEVII_NA_3://被测值Ⅶ + break; + case M_IT_NA_3://电能脉冲计数值 + break; + case M_IT_TA_3://带时标的电能脉冲计数值 + break; + case M_ST_NA_3://步位置信息 + break; + case M_ST_TA_3://带时标的步位置信息 + break; + case M_SP_NA_3://单点状态信息 + break; + case M_SP_TA_3://带时标的单点状态信息 + break; + case M_DP_NA_3://双点状态信息 + break; + case M_DP_TA_3://带时标的双点状态信息 + break; + case M_SS_NA_3://单点状态和状态变位检出 + break; + case M_SS_TA_3://带时标的单点状态和状态变位检出 + break; + case M_DS_NA_3://双点状态和状态变位检出 + break; + case M_DS_TA_3://带时标的双点状态和状态变位检出 + break; + case M_WL_TA_3://水位 + break; + case M_DC_NA_3://控制断路器命令 + break; + case M_RC_NA_3://升降命令 + break; + case M_SE_NA_3://设定命令 + break; + case M_CC_NA_3://控制命令 + break; + } + + if(len > 0) + { + ptrClpdu_varr->nLEN1 = len - 4; + ptrClpdu_varr->nLEN2 = len - 4; + tmp[len++] = CalBuban103Lpc(tmp+4, ptrClpdu_varr->nLEN1); + tmp[len++] = 0x16; + PutPollCmdToBuf(commid, cmdtype, 0, (char*)tmp, len); + } +} + +//***************************************************************************/ +//* 转发命令处理 */ +//*参数: u_32 portidx : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvRtuProtocolDataProcess(int commid, RTUMSG *rtumsg) +{ + if(rtumsg->MsgLen == 0) + return; + + // 数据校验错误(附加字节的第二个字节) + if(rtumsg->MsgData[rtumsg->MsgLen+1] > 0) + return; + + // wen 增加限制,以使得指令缓冲区不会生成多条指令 + //if(CheckPollCmdBuf(commid)) return; + + switch(rtumsg->MsgData[0]) + { + case 0x10://shortframe process + Provshortprocess(commid, rtumsg); + break; + + case 0x68: + Provlongprocess(commid, rtumsg); + break; + + default: + break; + } +} + +//***************************************************************************/ +//* 保护命令数据处理函数 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvSendCmdToPort(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + u_32 destport; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + { + return; + } + + + if((C_GD_NA_3 != rtumsg->MsgData[6])\ + && (C_GRC_NA_3 != rtumsg->MsgData[6])\ + && (C_GC_NA_3 != rtumsg->MsgData[6])) + { + return; + } + + // ??? 在这里将保护数据发送到指定的装置下发端口 + if(pProvDevParam->m_iRealCommid > 0) + { + destport = pProvDevParam->m_iRealCommid-1; + } + else + { + return; + } + + rtumsg->MsgData[12] = RII_PROV_ID; + rtumsg->MsgType = MSGTYPE_BAOHU_103CMD; + + SendProtectCmdToDev(destport, rtumsg); +} + +//***************************************************************************/ +//* 数据转发短帧处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//*返回值:无 */ +//***************************************************************************/ +void Provshortprocess(u_32 commid, RTUMSG *rtumsg) +{ + BOOL bFind; + DEVADDRPARAM DevAddrParam; + BUBAN103LINKDEF *pLinkParam=NULL; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + if((rtumsg->MsgData[1] & 0xc0) == 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d(CtrlByte=%02x)接收到的短帧数据不是主站命令!!!\n", + commid, rtumsg->MsgData[2], rtumsg->MsgData[1]); + DebugPrint(szbuf); +#endif + return; + } + + if(!IsExtInfoPtr(commid)) + { + return; + } + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + DevAddrParam.m_uchLinkAddr = rtumsg->MsgData[2]; + if(FindProtectDev(pPortParam, &DevAddrParam, TRUE) == FALSE) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d 不匹配!!!\n", + commid, rtumsg->MsgData[2]); + DebugPrint(szbuf); +#endif + bFind = FALSE; + } + else + { + bFind = TRUE; + } + + //printf("commid=%d, iLinkIdx=%d, iDevIdx=%d\n", commid, DevAddrParam.m_iLinkIdx, DevAddrParam.m_iDevIdx); + + if(TRUE == bFind) + { + pLinkParam = &pPortParam->m_psLink[DevAddrParam.m_iLinkIdx]; + } + + /* + if((rtumsg->MsgData[1] & 0x0f) == C_RCU_NA_3) + { + //InitBuban103LinkCmdBuf(pLinkParam); + //SetDevLinkOk(pLinkParam, DevAddrParam.m_iDevIdx, TRUE); + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_CON_NA_3, TRUE); + //pLinkParam->m_psProvDev[DevAddrParam.m_iDevIdx].m_iProvAsdu5Cause = M_CAUSE_RESET_CU; + } + + return; + */ + + switch(rtumsg->MsgData[1] & 0x0f) + { + case C_RCU_NA_3://复位通信单元 + if(TRUE == bFind) + { + InitBuban103LinkCmdBuf(pLinkParam); + SetDevLinkOk(pLinkParam, DevAddrParam.m_iDevIdx, TRUE); + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_CON_NA_3, TRUE); + pLinkParam->m_psProvDev[DevAddrParam.m_iDevIdx].m_iProvAsdu5Cause = M_CAUSE_RESET_CU; + } + else + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_CON_NA_3, FALSE); + } + break; + case C_RFB_NA_3://复位帧计数位 + if(TRUE == bFind) + { + pLinkParam->m_pu8CtlByte[DevAddrParam.m_iDevIdx] = 0; + pLinkParam->m_psProvDev[DevAddrParam.m_iDevIdx].m_iProvAsdu5Cause = M_CAUSE_RESET_FCB; + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_CON_NA_3, TRUE); + } + else + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_CON_NA_3, FALSE); + } + break; + case C_RLK_NA_3://链路状态请求 + if(TRUE == bFind) + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_LKR_NA_3_1, FALSE); + } + else + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[2], M_LKR_NA_3_2, FALSE); + } + break; + case C_PL1_NA_3://召唤一级数据 + if(FALSE == bFind) + { + break; + } + + if(TRUE == IsDevLinkOk(pLinkParam, DevAddrParam.m_iDevIdx)) + { + // 查找链路中所有的装置 + //if(pLinkParam->m_uchLinkAddr != 0xFF) + //{ + // DevAddrParam.m_iDevIdx = -1; + //} + ProvPL1process(commid, &DevAddrParam); + } + break; + case C_PL2_NA_3://召唤二级数据 + if(FALSE == bFind) + { + break; + } + + if(TRUE == IsDevLinkOk(pLinkParam, DevAddrParam.m_iDevIdx)) + { + // 查找链路中所有的装置 + //if(pLinkParam->m_uchLinkAddr != 0xFF) + //{ + // DevAddrParam.m_iDevIdx = -1; + //} + ProvPL2process(commid, &DevAddrParam); + } + break; + default: + break; + } +} + +//***************************************************************************/ +//* 转发一类数据处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_char addr : 间隔设备地址 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvPL1process(u_32 commid, DEVADDRPARAM *psDevAddrParam) +{ + BOOL bACD; + WORD wValue; + DAY_TIME sCurTime; + SOE_DEF sSoeData; + DI_DEF pntmsg; + PROV_DI_PNT *diprovptr; + DBINFO sDbInfo; + i_32 i, len; + char szDebugbuf[256]; + RTUMSG rtumsg, msg; + DBORIENTATION *pDBUnit; + CLPDU_VARR *ptrClpdu_varr; + DEVADDRPARAM sDevAddrParam; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + memset(szDebugbuf, 0, sizeof(szDebugbuf)); + memset((void *)&rtumsg, 0, sizeof(rtumsg)); + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pProvDevParam = &pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx]; + if(pProvDevParam->m_iProvAsdu5Cause > 0) + { + ProvMakeVarCommand(commid, pLinkParam->m_uchLinkAddr,\ + (BYTE)pProvDevParam->m_iProvAddr, M_IRC_NA_3, FALSE,\ + (BYTE)pProvDevParam->m_iProvAsdu5Cause, FAST_POLL_CMD); + pProvDevParam->m_iProvAsdu5Cause = 0; + return; + } + + // 首先发送突发事件(由于所有装置的信息都在一个缓冲区,所以只能有一个公共链路) + while(ProvHaveSoeData(commid) > 0) + { + ProvAndDelGetSoeData(commid, &sSoeData); + //if(ProvAndDelGetSoeData(commid, &sSoeData) > 0) + //{ + // bACD = TRUE; + //} + //else + //{ + // bACD = ProvHaveClassOne(commid, psDevAddrParam, FALSE); + //} + + if(FALSE == FindProtectDevFromPntNo(pPortParam, &sDevAddrParam, &sDbInfo, sSoeData.iPntNo, DI_PNT_TYPE)) + { + continue; + } + + ptrClpdu_varr = (CLPDU_VARR *)rtumsg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + // 重新赋值链路的转发地址 + ptrClpdu_varr->nADDR = sDevAddrParam.m_uchLinkAddr; + // 如果在总查询过程中 + /* + if(pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx].m_bProvQuery) + { + ptrClpdu_varr->nCONTROL |= 0x20; + } + else + { + // 是否还有一类数据 + if(TRUE == bACD) + { + ptrClpdu_varr->nCONTROL |= 0x20; + } + else + { + ptrClpdu_varr->nCONTROL &= 0xDF; + } + }*/ + // 是否还有一类数据 + //if(TRUE == bACD) + //{ + // ptrClpdu_varr->nCONTROL |= 0x20; + //} + //else + //{ + // ptrClpdu_varr->nCONTROL &= 0xDF; + //} + ptrClpdu_varr->nCONTROL &= 0xDF; + + wValue = sSoeData.SoeTime.mSec + sSoeData.SoeTime.Sec * 1000; + if(sSoeData.u8Type == 1) + { + rtumsg.MsgData[sizeof(CLPDU_VARR)] = 0x01; + len = 14; + + // 四个八位二进制组 + rtumsg.MsgData[sizeof(CLPDU_VARR)+7] = LOBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+8] = HIBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+9] = sSoeData.SoeTime.Min & 0x3F; + rtumsg.MsgData[sizeof(CLPDU_VARR)+10] = sSoeData.SoeTime.Hour & 0x1F; + // SIN + rtumsg.MsgData[sizeof(CLPDU_VARR)+11] = 0; + } + else + { + rtumsg.MsgData[sizeof(CLPDU_VARR)] = 0x02; + len = 18; + // 四个八位二进制组 + rtumsg.MsgData[sizeof(CLPDU_VARR)+7] = LOBYTE(sSoeData.wRelativeTime); + rtumsg.MsgData[sizeof(CLPDU_VARR)+8] = HIBYTE(sSoeData.wRelativeTime); + rtumsg.MsgData[sizeof(CLPDU_VARR)+9] = LOBYTE(sSoeData.wFaultNo); + rtumsg.MsgData[sizeof(CLPDU_VARR)+10] = HIBYTE(sSoeData.wFaultNo); + rtumsg.MsgData[sizeof(CLPDU_VARR)+11] = LOBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+12] = HIBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+13] = sSoeData.SoeTime.Min & 0x3F; + rtumsg.MsgData[sizeof(CLPDU_VARR)+14] = sSoeData.SoeTime.Hour & 0x1F; + // SIN + rtumsg.MsgData[sizeof(CLPDU_VARR)+15] = 0; + } + ptrClpdu_varr->nLEN1 = (BYTE)len; + ptrClpdu_varr->nLEN2 = (BYTE)len; + rtumsg.MsgData[sizeof(CLPDU_VARR)+1] = 0x81; + //COT + rtumsg.MsgData[sizeof(CLPDU_VARR)+2] = M_CAUSE_AUTOSEND; + // 重新赋值 ASDU 公共地址 + rtumsg.MsgData[sizeof(CLPDU_VARR)+3] = sDevAddrParam.m_uchCommAddr; + // FUN + //rtumsg.MsgData[sizeof(CLPDU_VARR)+4] = sSoeData.u8ProvFun; + // INF + //rtumsg.MsgData[sizeof(CLPDU_VARR)+5] = sSoeData.u8ProvInf; + // FUN + rtumsg.MsgData[sizeof(CLPDU_VARR)+4] = sDbInfo.m_u8ProvFun; + // INF + rtumsg.MsgData[sizeof(CLPDU_VARR)+5] = sDbInfo.m_u8ProvInf; + // DPI + rtumsg.MsgData[sizeof(CLPDU_VARR)+6] = sSoeData.bStatus+1; + + + len = ptrClpdu_varr->nLEN1 + 4; + // 发送时会重新计算 + //rtumsg.MsgData[len++] = CalBuban103Lpc(rtumsg.MsgData+4, ptrClpdu_varr->nLEN1); + rtumsg.MsgData[len++] = 0; + rtumsg.MsgData[len++] = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)rtumsg.MsgData, len); + return; + } + + bACD = ProvHaveClassOne(commid, psDevAddrParam, pPortParam->m_bSendChangeDi); + if(bACD == TRUE) + { + // ??? 需要修改为实际信息 + //bACD = FALSE; + pProvDevParam = &pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx]; + if(SingleListHaveData(&pProvDevParam->m_sBaoHuData) > 0) + { + msg.MsgLen = SingleListGetAndDelData(&pProvDevParam->m_sBaoHuData, msg.MsgData, sizeof(msg.MsgData)); + + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + msg.MsgData[5] = pLinkParam->m_uchLinkAddr; + } + else + { + msg.MsgData[5] = (BYTE)pProvDevParam->m_iProvAddr; + } + msg.MsgData[9] = (BYTE)pProvDevParam->m_iProvAddr; + + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)msg.MsgData, msg.MsgLen); + return; + } + + // 是否转发遥信变位,一般将其屏蔽 + if(pPortParam->m_bSendChangeDi == TRUE) + { + if(pPortParam->m_psBaoHu->DiChange == TRUE) + { + if(TRUE == ProvSendChangedDi(commid, psDevAddrParam)) + { + return; + } + } + } + + // 如果在总查询过程中 + if(pProvDevParam->m_bProvQuery == TRUE) + { + pDBUnit = &pProvDevParam->m_sYxInfo; + for(i=pProvDevParam->m_iQueryPntNo; im_iPntNum; i++) + { + // 如果是总召唤数据 + if(pDBUnit->m_psDataInfo[i].m_u8LoopData) + { + break; + } + } + + if(i >= pDBUnit->m_iPntNum) + { + pProvDevParam->m_bProvQuery = FALSE; + pProvDevParam->m_iProvQueryStepWithASDU = 0; + ProvMakeVarCommand(commid, pLinkParam->m_uchLinkAddr,\ + (BYTE)pProvDevParam->m_iProvAddr, M_TGI_NA_3, FALSE,\ + (BYTE)M_CAUSE_STOPQUERY, FAST_POLL_CMD); + pProvDevParam->m_iQueryPntNo = 0; + } + else + { + pProvDevParam->m_iQueryPntNo++; + diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr; + + ptrClpdu_varr = (CLPDU_VARR *)rtumsg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + // 重新赋值链路的转发地址 + ptrClpdu_varr->nADDR = pLinkParam->m_uchLinkAddr; + // 如果在总查询过程中 + ptrClpdu_varr->nCONTROL |= 0x20; + + rtumsg.MsgData[sizeof(CLPDU_VARR)] = 0x01; + len = 14; + + rtumsg.MsgData[sizeof(CLPDU_VARR)+1] = 0x81; + //COT + //rtumsg.MsgData[sizeof(CLPDU_VARR)+2] = M_CAUSE_AUTOSEND; + rtumsg.MsgData[sizeof(CLPDU_VARR)+2] = M_CAUSE_QUERY; + // 重新赋值 ASDU 公共地址 + rtumsg.MsgData[sizeof(CLPDU_VARR)+3] = (BYTE)pProvDevParam->m_iProvAddr; + // FUN + rtumsg.MsgData[sizeof(CLPDU_VARR)+4] = pDBUnit->m_psDataInfo[i].m_u8ProvFun; + // INF + rtumsg.MsgData[sizeof(CLPDU_VARR)+5] = pDBUnit->m_psDataInfo[i].m_u8ProvInf; + + GetPntMsg(diprovptr[pDBUnit->m_iStartPntNo+i].PortNo,\ + diprovptr[pDBUnit->m_iStartPntNo+i].PntNo,\ + (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + + // DPI + rtumsg.MsgData[sizeof(CLPDU_VARR)+6] = pntmsg.Status+1; + + GetLocalTimeEx(&sCurTime); + wValue = sCurTime.Sec*1000+sCurTime.mSec; + // 四个八位二进制组 + rtumsg.MsgData[sizeof(CLPDU_VARR)+7] = LOBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+8] = HIBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+9] = sCurTime.Min & 0x3F; + rtumsg.MsgData[sizeof(CLPDU_VARR)+10] = sCurTime.Hour & 0x1F; + // SIN + rtumsg.MsgData[sizeof(CLPDU_VARR)+11] = 0; + ptrClpdu_varr->nLEN1 = (BYTE)len; + ptrClpdu_varr->nLEN2 = (BYTE)len; + + len = ptrClpdu_varr->nLEN1 + 4; + // 发送时会重新计算 + //rtumsg.MsgData[len++] = CalBuban103Lpc(rtumsg.MsgData+4, ptrClpdu_varr->nLEN1); + rtumsg.MsgData[len++] = 0; + rtumsg.MsgData[len++] = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)rtumsg.MsgData, len); + } + return; + } + } + + /* + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + ProvMakeLinkCommand(commid, pLinkParam->m_uchLinkAddr, M_NV_NA_3, FALSE); + } + else + { + ProvMakeLinkCommand(commid, psDevAddrParam->m_uchLinkAddr, M_NV_NA_3, FALSE); + } + */ + //ProvMakeLinkCommand(commid, psDevAddrParam->m_uchLinkAddr, M_NV_NA_3, bACD); + ProvMakeLinkCommand(commid, psDevAddrParam->m_uchLinkAddr, M_NV_NA_3, FALSE); +} + + +//***************************************************************************/ +//* 转发二类数据处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* u_char addr : 间隔设备地址 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvPL2process(u_32 commid, DEVADDRPARAM *psDevAddrParam) +{ + //BOOL bACD; + //PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + //pProvDevParam = &pLinkParam->m_psProvDev[pLinkParam->m_iDevIdx]; + //psDevAddrParam->m_iDevIdx = pLinkParam->m_iDevIdx; + + /* + // 首先发送突发事件 + if(ProvHaveSoeData(commid) > 0) + { + bACD = TRUE; + } + else if(pProvDevParam->m_bProvQuery == TRUE) + { + bACD = TRUE; + } + else + { + bACD = FALSE; + } + */ + + //bACD = ProvHaveClassOne(commid, psDevAddrParam, FALSE); + //ProvMakeLinkCommand(commid, pLinkParam->m_uchLinkAddr, M_NV_NA_3, bACD); + ProvMakeLinkCommand(commid, pLinkParam->m_uchLinkAddr, M_NV_NA_3, FALSE); +} + +//***************************************************************************/ +//* 数据转发长帧处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//*返回值:无 */ +//***************************************************************************/ +void Provlongprocess(u_32 commid, RTUMSG *rtumsg) +{ + BOOL bFind; + DEVADDRPARAM DevAddrParam; + BUBAN103LINKDEF *pLinkParam=NULL; + BUBAN103PORTPARAM *pPortParam=NULL; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + if((rtumsg->MsgData[4] & 0xc0) == 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d(CtrlByte=%02x)接收到的短帧数据不是主站命令!!!\n", + commid, rtumsg->MsgData[5], rtumsg->MsgData[4]); + DebugPrint(szbuf); +#endif + return; + } + + if(!IsExtInfoPtr(commid)) + { + return; + } + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + DevAddrParam.m_uchLinkAddr = rtumsg->MsgData[5]; + DevAddrParam.m_uchCommAddr = rtumsg->MsgData[9]; + if(0xFF != DevAddrParam.m_uchLinkAddr) + { + if(FindProtectDev(pPortParam, &DevAddrParam, FALSE) == FALSE) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不匹配!!!\n", + commid, rtumsg->MsgData[5], rtumsg->MsgData[9]); + DebugPrint(szbuf); +#endif + bFind = FALSE; + } + else + { + bFind = TRUE; + } + + if(TRUE == bFind) + { + pLinkParam = &pPortParam->m_psLink[DevAddrParam.m_iLinkIdx]; + } + + if(IsDevLinkOk(pLinkParam, DevAddrParam.m_iDevIdx) == FALSE) + { + return; + } + } + else + { + if(C_SYN_TA_3 != rtumsg->MsgData[6]) + { + return; + } + } + + // 长帧数据的功能类型 + switch(rtumsg->MsgData[6]) + { + case C_SYN_TA_3: //时间同步 + ProvSYNprocess(commid, rtumsg); + break; + + case C_TGI_NA_3: //总查询(总召唤) + ProvTGIprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_GD_NA_3: //通用分类数据 + ProvGDprocess(commid, rtumsg, &DevAddrParam); + //ProvSendCmdToPort(commid, rtumsg, &DevAddrParam); + break; + + case C_GRC_NA_3: //一般命令 + ProvGRCprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_GC_NA_3: //通用分类命令 + ProvGCprocess(commid, rtumsg, &DevAddrParam); + //ProvSendCmdToPort(commid, rtumsg, &DevAddrParam); + break; + + case C_ODT_NA_3: //扰动数据传输的命令 + ProvODTprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_ADT_NA_3: //扰动数据传输的认可 + ProvADTprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_DC_NA_3: //控制断路器命令 + ProvDCprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_RC_NA_3: //升降命令 + ProvRCprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_SE_NA_3: //设定命令 + ProvSEprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_CC_NA_3: //控制命令 + ProvCCprocess(commid, rtumsg, &DevAddrParam); + break; + + case C_CI_NA_3: //电能脉冲计数召唤命令 + ProvCIprocess(commid, rtumsg, &DevAddrParam); + break; + + default: + break; + } + + switch(rtumsg->MsgData[4] & 0x0f) + { + case C_SD1_NA_3://传送数据(发送/确认帧) + // 非总查询命令 + /* + if(C_TGI_NA_3 == rtumsg->MsgData[6]) + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, TRUE); + } + else if(C_SYN_TA_3 == rtumsg->MsgData[6]) + { + if(rtumsg->MsgData[5] != 0xFF) + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, TRUE); + } + } + else + { + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, FALSE); + } + */ + + //if(TRUE == ProvHaveClassOne(commid, &DevAddrParam, FALSE)) + //{ + // ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, TRUE); + //} + //else + //{ + // ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, FALSE); + //} + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, FALSE); + break; + + case C_SD2_NA_3://传送数据(发送/无回答帧) + break; + } +} + +//***************************************************************************/ +//* 转发时间同步处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvSYNprocess(u_32 commid, RTUMSG *rtumsg) +{ + i_32 len; + DAY_TIME sTime; + //char szDbg[128]; + u_char tmp[MAX_POLL_CMD_BUF_LEN]; + CLPDU_VARR bClpdu_varr; + BUBAN103PORTPARAM *pPortParam; + + if(!IsExtInfoPtr(commid)) + { + return; + } + pPortParam = (pBUBAN103PORTPARAM)SioParam[commid].ExtInfo; + + sTime.mSec = rtumsg->MsgData[12] + (rtumsg->MsgData[13] << 8); + sTime.Sec = sTime.mSec / 1000; + sTime.mSec = sTime.mSec % 1000; + sTime.Min = rtumsg->MsgData[14] & 0x3F; + sTime.Hour = rtumsg->MsgData[15] & 0x1F; + sTime.Day = rtumsg->MsgData[16] & 0x1F; + sTime.Month= rtumsg->MsgData[17] & 0x0F; + sTime.Year = (rtumsg->MsgData[18] & 0x7F) + 2000; + + //sprintf(szDbg, "time:%04d-%02d-%02d_%02d:%02d:%02d.%03d\n", + // sTime.Year, sTime.Month, sTime.Day, sTime.Hour, + // sTime.Min, sTime.Sec, sTime.mSec); + //DebugPrint(szDbg); + + // 如果时间同步原因,则进行对时 + if((pPortParam->m_psBaoHu->CheckTime == 1) + && (rtumsg->MsgData[8] == M_CAUSE_CHECKTIME)) + { + SetLocalTimeEx(&sTime); + } + + // 广播地址 + if(rtumsg->MsgData[5] == 0xff) + { + return; + } + + memset(&bClpdu_varr, 0 , sizeof(CLPDU_VARR)); + memset(tmp , 0 , sizeof(tmp)); + + bClpdu_varr.nSTART1 = 0x68; + bClpdu_varr.nSTART2 = 0x68; + bClpdu_varr.nLEN1 = 15; + bClpdu_varr.nLEN2 = 15; + + bClpdu_varr.nCONTROL = M_DATA_NA_3; + bClpdu_varr.nADDR = rtumsg->MsgData[5]; + len = sizeof(bClpdu_varr); + memcpy(tmp, (char*)&bClpdu_varr, len); + tmp[len++] = M_SYN_TA_3; + tmp[len++] = 0x81; + tmp[len++] = M_CAUSE_CHECKTIME; + tmp[len++] = rtumsg->MsgData[9]; + tmp[len++] = FUNC_GLOBAL; + tmp[len++] = 0; + memcpy(tmp+len, rtumsg->MsgData+12, 7); + //if(!SetLocalTime(&t)) + // tmp[len+2] |= 0x80; + len += 7; + //tmp[len++] = CalBuban103Lpc(tmp+4, bClpdu_varr.nLEN1); + tmp[len++] = 0; + tmp[len++] = 0x16; + + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)tmp, len); +} + +//***************************************************************************/ +//* 转发总查询(总召唤)处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvTGIprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(GetPortParamPtr(commid, &pPortParam) == FALSE) + { + return; + } + + pPortParam->m_iLinkIdx = psDevAddrParam->m_iLinkIdx; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + pLinkParam->m_iDevIdx = psDevAddrParam->m_iDevIdx; + pProvDevParam = &pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx]; + + // 总查询开始 + pProvDevParam->m_bProvQuery = TRUE; + pProvDevParam->m_iProvQueryStepWithASDU = M_MEVII_NA_3; + + // 存在一类数据,请查询 + //ProvMakeLinkCommand(commid, rtumsg->MsgData[9], M_CON_NA_3, TRUE); + //ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_CON_NA_3, TRUE); +} + +//***************************************************************************/ +//* 转发通用分类数据处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvGDprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + //PROVDEVDEF *pProvDevParam; + //BUBAN103LINKDEF *pLinkParam; + //BUBAN103PORTPARAM *pPortParam; + + if(rtumsg->MsgData[12] != RII_PROV_ID) + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + return; + } + + //if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + //{ + // return; + //} +} + +//***************************************************************************/ +//* 转发一般命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvGRCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + if(rtumsg->MsgData[12] != RII_PROV_ID) + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + return; + } +} + +//***************************************************************************/ +//* 转发通用分类命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvGCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + int iGrpNum; + GROUPDEF *pBaoHuDB; + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + /*wen 2005.06.01 实际情况需要安这样来处理数据,直接转发到装置去 + if(rtumsg->MsgData[12] != RII_PROV_ID) + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + return; + } + */ + + if(FALSE == GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam)) + { + return; + } + + if(rtumsg->MsgData[12] != RII_PROV_ID) + { + pProvDevParam->m_sProvGroupParam.m_u8Group = rtumsg->MsgData[9]; + pProvDevParam->m_sProvGroupParam.m_u8ItemAttr = rtumsg->MsgData[11]; + pProvDevParam->m_sProvGroupParam.m_u8ItemNo = rtumsg->MsgData[10]; + pProvDevParam->m_sProvGroupParam.m_u8RII = rtumsg->MsgData[12]; + + pBaoHuDB = NULL; + iGrpNum = GetBaohuDB(pProvDevParam->m_iRealCommid-1, pProvDevParam->m_iProvAddr, &pBaoHuDB); + // 传送原因(通用分类读数据) + if(rtumsg->MsgData[8] == C_CAUSE_READWITHVALIDDATA) + { + // INF + switch(rtumsg->MsgData[11]) + { + case C_INF_READGROUPTITLE: // 读组标题 + if((pBaoHuDB != NULL) && (iGrpNum > 0)) + { + ProvMakeTitleOfGroups(commid, rtumsg, pProvDevParam, pBaoHuDB, iGrpNum); + } + else + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + } + break; + case C_INF_READGROUPALLITEMS: // 读一个组的全部条目的值或属性 + if((pBaoHuDB != NULL) && (iGrpNum > 0)) + { + ProvMakeAttrOfAllItemInGroup(commid, rtumsg, pProvDevParam, pBaoHuDB, iGrpNum); + } + else + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + } + break; + case C_INF_READDIROFSINGLEITEM: // 读单个条目的目录 + if((pBaoHuDB != NULL) && (iGrpNum > 0)) + { + ProvMakeDirOfItem(commid, rtumsg, pProvDevParam, pBaoHuDB, iGrpNum); + } + else + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + } + break; + case C_INF_READATTROFISNGLEITEM:// 读单个条目的值或属性 + if((pBaoHuDB != NULL) && (iGrpNum > 0)) + { + ProvMakeAttrOfItem(commid, rtumsg, pProvDevParam, pBaoHuDB, iGrpNum); + } + else + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + } + break; + case C_INF_QUERYGENERAL: // 对通用分类数据总查询 + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_NV_NA_3, FALSE); + break; + default: + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + break; + } + } + else + { + ProvSendCmdToPort(commid, rtumsg, psDevAddrParam); + } + return; + } + + // wen test 可以添加保护数据返回做测试用 + if(RII_PROV_ID == rtumsg->MsgData[12]) + { + // test + RTUMSG msg; + BYTE buffix[] = {0x68, 0x46, 0x46, 0x68, 0x08, 0x01, + 0x0A, 0x81, 0x2A, 0x01, 0xFE, 0xF1, + 0xFF, 0x06, 0x50, 0x01, 0x01, 0x07, + 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x02, 0x01, 0x07, 0x04, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, + 0x01, 0x07, 0x04, 0x01, 0x22, 0xDB, + 0x79, 0x3F, 0x50, 0x04, 0x01, 0x07, + 0x04, 0x01, 0x3D, 0x6A, 0x53, 0x43, + 0x50, 0x05, 0x01, 0x07, 0x04, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x06, + 0x01, 0x07, 0x04, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x16 }; + BYTE bufsoe[] = {0x68, 0x0E, 0x0E, 0x68, 0x28, 0x01, + 0x01, 0x81, 0x01, 0x01, 0x64, 0x42, + 0x01, 0x70, 0x94, 0x05, 0x0D, 0x00, + 0x6A, 0x16}; + + msg.MsgLen = sizeof(buffix); + memcpy(msg.MsgData, buffix, msg.MsgLen); + msg.PortIdx = (BYTE)commid; + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + msg.MsgData[5] = pLinkParam->m_uchLinkAddr; + } + else + { + msg.MsgData[5] = (BYTE)pProvDevParam->m_iProvAddr; + } + msg.MsgData[9] = (BYTE)pProvDevParam->m_iProvAddr; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + return; + } +} + +//***************************************************************************/ +//* 转发扰动数据传输的命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvODTprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发扰动数据传输的认可处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvADTprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发控制断路器命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvDCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发升降命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvRCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发设定命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvSEprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发控制命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvCCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + +} + +//***************************************************************************/ +//* 转发电能脉冲计数召唤命令处理 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +void ProvCIprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam) +{ + i_32 iPiNum; + i_32 i; + u_char tmp[MAX_POLL_CMD_BUF_LEN]; + CLPDU_VARR *ptrClpdu_varr; + i_32 len; + PI_DEF pntmsg; + PROV_PI_PNT *piprovptr; + + PROVDEVDEF *pProvDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + + if(GetSpecialProvPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pProvDevParam) == FALSE) + { + return; + } + + memset(tmp, 0, sizeof(tmp)); + ptrClpdu_varr = (CLPDU_VARR *)tmp; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = rtumsg->MsgData[5]; + + //if(ProvHaveClassOne(commid, psDevAddrParam, TRUE)) + //{ + // ptrClpdu_varr->nCONTROL = 0x28; + //} + //else + //{ + // ptrClpdu_varr->nCONTROL = 0x08; + //} + ptrClpdu_varr->nCONTROL = 0x08; + + len = sizeof(CLPDU_VARR); + + tmp[len++] = M_IT_NA_3; + tmp[len++] = 0x00; + tmp[len++] = M_CAUSE_CYCLE; + tmp[len++] = rtumsg->MsgData[9]; + tmp[len++] = 1; + iPiNum = pProvDevParam->m_sYmInfo.m_iPntNum; + if(iPiNum > INF_PI_NUM) + { + iPiNum = INF_PI_NUM; + } + + piprovptr = (PROV_PI_PNT *)pPortParam->m_psBaoHu->PiPtr; + + if((pProvDevParam->m_sYmInfo.m_iStartPntNo+iPiNum)\ + > pPortParam->m_psBaoHu->PiNum) + { + if((pProvDevParam->m_bProvQuery == TRUE)\ + || (CheckPollCmdBufEmpty(commid) == 0)) + { + //ProvMakeLinkCommand(commid, pLinkParam->m_uchLinkAddr, M_NV_NA_3, TRUE); + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_NV_NA_3, TRUE); + } + else + { + //ProvMakeLinkCommand(commid, pLinkParam->m_uchLinkAddr, M_NV_NA_3, FALSE); + ProvMakeLinkCommand(commid, rtumsg->MsgData[5], M_NV_NA_3, FALSE); + } + return; + } + + + tmp[len++] = INF_PI_START; + for(i=0; im_sYmInfo.m_iStartPntNo+i].PortNo,\ + piprovptr[pProvDevParam->m_sYmInfo.m_iStartPntNo+i].PntNo,\ + &pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + tmp[len++] = (BYTE)(pntmsg.RawValue & 0xFF); + tmp[len++] = (BYTE)((pntmsg.RawValue & 0xFF00) >> 8); + tmp[len++] = (BYTE)((pntmsg.RawValue & 0xFF0000) >> 16); + tmp[len++] = (BYTE)((pntmsg.RawValue & 0xFF000000) >> 24); + // IV/CA/CY/顺序号 + len++; + } + + tmp[sizeof(CLPDU_VARR)+1] = (BYTE)(iPiNum); + + // 返回码RII + tmp[len++] = rtumsg->MsgData[13]; + ptrClpdu_varr->nLEN1 = len - 4; + ptrClpdu_varr->nLEN2 = len - 4; + //tmp[len++] = CalBuban103Lpc(tmp+4, ptrClpdu_varr->nLEN1); + tmp[len++] = 0; + tmp[len++] = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)tmp, len); +} + +//***************************************************************************/ +//* 转发全部组标题 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +BOOL ProvMakeTitleOfGroups(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum) +{ + i_32 i, len; + RTUMSG msg; + CLPDU_VARR *ptrClpdu_varr; + + memset((void *)&msg, 0, sizeof(RTUMSG)); + ptrClpdu_varr = (CLPDU_VARR *)msg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = rtumsg->MsgData[5]; + + len = sizeof(CLPDU_VARR); + msg.MsgData[len++] = M_GD_NTA_3; + msg.MsgData[len++] = 0x81; + msg.MsgData[len++] = M_CAUSE_READWITHVALIDDATA; + msg.MsgData[len++] = rtumsg->MsgData[9]; + msg.MsgData[len++] = FUNC_GENERALSORT; + msg.MsgData[len++] = M_INF_READGROUPTITLE; + msg.MsgData[len++] = rtumsg->MsgData[12];//RII + msg.MsgData[len++] = (BYTE)iNum; + for(i=0; inLEN1 = len - 4; + ptrClpdu_varr->nLEN2 = len - 4; + //msg.MsgData[len++] = CalBuban103Lpc(msg.MsgData+4, ptrClpdu_varr->nLEN1); + msg.MsgData[len++] = 0; + msg.MsgData[len++] = 0x16; + msg.MsgLen = (WORD)len; + msg.PortIdx = (BYTE)commid; + + return SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); +} + +//***************************************************************************/ +//* 转发一个组的全部条目的值或属性 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//* BOOL bContinue : 未传送的保护数据继续 */ +//*返回值:无 */ +//*备 注:所有组数据只能转发一帧 */ +//***************************************************************************/ +BOOL ProvMakeAttrOfAllItemInGroup(u_32 commid, RTUMSG *rtumsg,\ + PROVDEVDEF *pProvDevParam,\ + GROUPDEF *pBaoHuDB, int iNum) +{ + BOOL bRetVal; + i_32 i, ifixlen; + RTUMSG msg; + u_char *ptrPntNum; + CLPDU_VARR *ptrClpdu_varr; + i_32 iGroupNo, iPntNum, iNameLen; + float *pfValue, fValue; + + memset((void *)&msg, 0, sizeof(RTUMSG)); + ptrClpdu_varr = (CLPDU_VARR *)msg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = rtumsg->MsgData[5]; + + ifixlen = sizeof(CLPDU_VARR); + + // 组号 + for(iGroupNo=0; iGroupNoMsgData[14]) + { + break; + } + } + if(iGroupNo >= iNum) + { + return FALSE; + } + + msg.MsgData[ifixlen++] = M_GD_NTA_3; + msg.MsgData[ifixlen++] = 0x81; + msg.MsgData[ifixlen++] = M_CAUSE_READWITHVALIDDATA; + msg.MsgData[ifixlen++] = rtumsg->MsgData[9]; + msg.MsgData[ifixlen++] = FUNC_GENERALSORT; + msg.MsgData[ifixlen++] = M_INF_READGROUPALLITEMS; + msg.MsgData[ifixlen++] = rtumsg->MsgData[12];//RII + + iPntNum = pBaoHuDB[iGroupNo].m_iPntNum; + + ptrPntNum = &msg.MsgData[ifixlen++]; + msg.MsgLen = (WORD)ifixlen; + bRetVal = TRUE; + switch(rtumsg->MsgData[16]) + { + case KOD_ACTUALVALUE: // 实际值 + for(i=0; iMsgData[14];// 组 号 + msg.MsgData[msg.MsgLen++] = i+1; // 条目号 + msg.MsgData[msg.MsgLen++] = KOD_ACTUALVALUE; // 实际值 + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 1; + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[i].m_fValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + msg.MsgLen += sizeof(float); + *ptrPntNum++; + + if(msg.MsgLen >= 240) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + msg.MsgLen = (WORD)ifixlen; + *ptrPntNum = 0; + } + } + if(msg.MsgLen > ifixlen) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + } + break; + case KOD_RANGE: // 量程(最大值、最小值、步长) + for(i=0; iMsgData[14];// 组 号 + msg.MsgData[msg.MsgLen++] = i+1; // 条目号 + msg.MsgData[msg.MsgLen++] = KOD_RANGE; // 量程(最大值、最小值、步长) + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 3; + + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[i].m_fMaxValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[i].m_fMinValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[i].m_fStepValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + msg.MsgLen += 3*sizeof(float); + *ptrPntNum++; + + if(msg.MsgLen >= 240) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + msg.MsgLen = (WORD)ifixlen; + *ptrPntNum = 0; + } + } + + if(msg.MsgLen > ifixlen) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + } + break; + case KOD_DIMENSION: // 量 纲 + for(i=0; iMsgData[14];// 组 号 + msg.MsgData[msg.MsgLen++] = i+1; // 条目号 + msg.MsgData[msg.MsgLen++] = KOD_DIMENSION; // 量 纲 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[i].m_szUnit); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[i].m_szUnit, iNameLen); + msg.MsgLen += (WORD)iNameLen; + *ptrPntNum++; + + if(msg.MsgLen >= 240) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + msg.MsgLen = (WORD)ifixlen; + *ptrPntNum = 0; + } + } + + if(msg.MsgLen > ifixlen) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + } + break; + case KOD_DESCRIPTION: // 描 述 + for(i=0; iMsgData[14];// 组 号 + msg.MsgData[msg.MsgLen++] = i+1; // 条目号 + msg.MsgData[msg.MsgLen++] = KOD_DIMENSION; // 量 纲 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[i].m_szName); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[i].m_szName, iNameLen); + msg.MsgLen += (WORD)iNameLen; + *ptrPntNum++; + + if(msg.MsgLen >= 220) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + msg.MsgLen = (WORD)ifixlen; + *ptrPntNum = 0; + } + } + + if(msg.MsgLen > ifixlen) + { + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;// lpc + msg.MsgData[msg.MsgLen++] = 0x16; + SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); + } + break; + default: + bRetVal = FALSE; + break; + } + + return bRetVal; +} + +//***************************************************************************/ +//* 转发一个条目的目录 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +BOOL ProvMakeDirOfItem(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum) +{ + RTUMSG msg; + CLPDU_VARR *ptrClpdu_varr; + i_32 iNameLen, iGroupNo, iItemNo; + float *pfValue, fValue; + + // 条目号 + iItemNo = rtumsg->MsgData[15]; + + for(iGroupNo=0; iGroupNoMsgData[14]) + { + break; + } + } + if(iGroupNo >= iNum) + { + return FALSE; + } + + if(iItemNo <= 0) + { + return FALSE; + } + + if(iItemNo >= pBaoHuDB[iGroupNo].m_iPntNum) + { + return FALSE; + } + + memset((void *)&msg, 0, sizeof(RTUMSG)); + ptrClpdu_varr = (CLPDU_VARR *)msg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = rtumsg->MsgData[5]; + + msg.MsgLen = sizeof(CLPDU_VARR); + + msg.MsgData[msg.MsgLen++] = M_GD_NTA_3; + msg.MsgData[msg.MsgLen++] = 0x81; + msg.MsgData[msg.MsgLen++] = M_CAUSE_READWITHVALIDDATA; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[9]; + msg.MsgData[msg.MsgLen++] = FUNC_GENERALSORT; + msg.MsgData[msg.MsgLen++] = M_INF_READDIROFSINGLEITEM; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[12];//RII + + + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[14]; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[15]; + msg.MsgData[msg.MsgLen++] = 4; + + msg.MsgData[msg.MsgLen++] = KOD_ACTUALVALUE; // 实际值 + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 1; + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + msg.MsgLen += sizeof(float); + + msg.MsgData[msg.MsgLen++] = KOD_RANGE; // 量程(最大值、最小值、步长) + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 3; + + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fMaxValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fMinValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fStepValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + msg.MsgLen += 3*sizeof(float); + + msg.MsgData[msg.MsgLen++] = KOD_DIMENSION; // 量 纲 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szUnit); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szUnit, iNameLen); + msg.MsgLen += (WORD)iNameLen; + + msg.MsgData[msg.MsgLen++] = KOD_DESCRIPTION; // 描 述 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szName); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szName, iNameLen); + msg.MsgLen += (WORD)iNameLen; + + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;//lpc + msg.MsgData[msg.MsgLen++] = 0x16; + + return SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); +} + +//***************************************************************************/ +//* 转发一个条目的值或属性 */ +//*参数: u_32 commid : 厂站端口号 */ +//* RTUMSG *rtumsg : 接收到的数据信息 */ +//* i_32 iBuIdx : 保护装置(间隔)索引 */ +//*返回值:无 */ +//***************************************************************************/ +BOOL ProvMakeAttrOfItem(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum) +{ + RTUMSG msg; + CLPDU_VARR *ptrClpdu_varr; + i_32 iNameLen, iGroupNo, iItemNo; + float *pfValue, fValue; + + // 条目号 + iItemNo = rtumsg->MsgData[15]; + + for(iGroupNo=0; iGroupNoMsgData[14]) + { + break; + } + } + if(iGroupNo >= iNum) + { + return FALSE; + } + + if(iItemNo <= 0) + { + return FALSE; + } + + if(iItemNo >= pBaoHuDB[iGroupNo].m_iPntNum) + { + return FALSE; + } + + memset((void *)&msg, 0, sizeof(RTUMSG)); + ptrClpdu_varr = (CLPDU_VARR *)msg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + ptrClpdu_varr->nADDR = rtumsg->MsgData[5]; + + msg.MsgLen = sizeof(CLPDU_VARR); + + msg.MsgData[msg.MsgLen++] = M_GD_NTA_3; + msg.MsgData[msg.MsgLen++] = 0x81; + msg.MsgData[msg.MsgLen++] = M_CAUSE_READWITHVALIDDATA; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[9]; + msg.MsgData[msg.MsgLen++] = FUNC_GENERALSORT; + msg.MsgData[msg.MsgLen++] = M_INF_READDIROFSINGLEITEM; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[12];//RII + msg.MsgData[msg.MsgLen++] = 1; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[14]; + msg.MsgData[msg.MsgLen++] = rtumsg->MsgData[15]; + + switch(rtumsg->MsgData[16]) + { + case KOD_ACTUALVALUE: // 实际值 + msg.MsgData[msg.MsgLen++] = KOD_ACTUALVALUE; // 实际值 + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 1; + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + msg.MsgLen += sizeof(float); + break; + + case KOD_RANGE: // 量程(最大值、最小值、步长) + msg.MsgData[msg.MsgLen++] = KOD_RANGE; // 量程(最大值、最小值、步长) + msg.MsgData[msg.MsgLen++] = DATAID_FLOAT; // 浮点数 + msg.MsgData[msg.MsgLen++] = sizeof(float); + msg.MsgData[msg.MsgLen++] = 3; + + pfValue = (float*)(&msg.MsgData[msg.MsgLen]); + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fMaxValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fMinValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + pfValue++; + fValue = pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo-1].m_fStepValue; + SequenceHostToRtu((char *)&fValue, sizeof(float)); + *pfValue = fValue; + + msg.MsgLen += 3*sizeof(float); + break; + + case KOD_DIMENSION: // 量 纲 + msg.MsgData[msg.MsgLen++] = KOD_DIMENSION; // 量 纲 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szUnit); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szUnit, iNameLen); + msg.MsgLen += (WORD)iNameLen; + break; + + case KOD_DESCRIPTION: // 描 述 + msg.MsgData[msg.MsgLen++] = KOD_DIMENSION; // 量 纲 + msg.MsgData[msg.MsgLen++] = DATAID_OS8ASCII; + iNameLen = strlen(pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szName); + msg.MsgData[msg.MsgLen++] = (BYTE)iNameLen; + msg.MsgData[msg.MsgLen++] = 1; + memcpy(&msg.MsgData[msg.MsgLen], pBaoHuDB[iGroupNo].m_psDataInfo[iItemNo].m_szName, iNameLen); + msg.MsgLen += (WORD)iNameLen; + break; + } + + ptrClpdu_varr->nLEN1 = msg.MsgLen - 4; + ptrClpdu_varr->nLEN2 = msg.MsgLen - 4; + msg.MsgLen++;//lpc + msg.MsgData[msg.MsgLen++] = 0x16; + + return SingleListAddData(&pProvDevParam->m_sBaoHuData, msg.MsgData, msg.MsgLen); +} + +BOOL ProvSendChangedDi(u_32 commid, DEVADDRPARAM *psDevAddrParam) +{ + int i, j, iStart, len; + WORD wValue; + BOOL bQueryAllDev, bFind; + DAY_TIME sCurTime; + RTUMSG rtumsg; + DI_DEF pntmsg; + PROV_DI_PNT *diprovptr = NULL; + CLPDU_VARR *ptrClpdu_varr = NULL; + PROVDEVDEF *pProvDevParam = NULL; + BUBAN103LINKDEF *pLinkParam = NULL; + BUBAN103PORTPARAM *pPortParam = NULL; + + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + pLinkParam = &pPortParam->m_psLink[psDevAddrParam->m_iLinkIdx]; + diprovptr = (PROV_DI_PNT*)pPortParam->m_psBaoHu->DiPtr; + + bFind = FALSE; + if(pLinkParam->m_uchLinkAddr != 0xFF) + { + bQueryAllDev = TRUE; + } + else + { + bQueryAllDev = FALSE; + } + + for(i=0; im_iDevNum; i++) + { + if(bQueryAllDev == TRUE) + { + psDevAddrParam->m_iDevIdx = i; + } + else + { + if(i >= 1) + { + break; + } + } + pProvDevParam = &pLinkParam->m_psProvDev[psDevAddrParam->m_iDevIdx]; + + iStart = pProvDevParam->m_sYxInfo.m_iStartPntNo; + for(j=0; jm_sYxInfo.m_iPntNum; j++) + { + if(TRUE == diprovptr[iStart+j].ChangeFlag) + { + bFind = TRUE; + diprovptr[iStart+j].ChangeFlag = FALSE; + GetPntMsg(diprovptr[iStart+j].PortNo, diprovptr[iStart+j].PntNo, + (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + break; + } + } + if(TRUE == bFind) + { + break; + } + } + + if(bFind == TRUE) + { + GetLocalTimeEx(&sCurTime); + ptrClpdu_varr = (CLPDU_VARR *)rtumsg.MsgData; + ptrClpdu_varr->nSTART1 = 0x68; + ptrClpdu_varr->nSTART2 = 0x68; + // 重新赋值链路的转发地址 + ptrClpdu_varr->nADDR = psDevAddrParam->m_uchLinkAddr; + ptrClpdu_varr->nCONTROL &= 0xDF; + + // wen 2005.06.10 遥信变位只精确到秒 + //wValue = sCurTime.Sec*1000 + sCurTime.mSec; + wValue = sCurTime.Sec*1000; + + rtumsg.MsgData[sizeof(CLPDU_VARR)] = 0x01; + // 四个八位二进制组 + rtumsg.MsgData[sizeof(CLPDU_VARR)+7] = LOBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+8] = HIBYTE(wValue); + rtumsg.MsgData[sizeof(CLPDU_VARR)+9] = sCurTime.Min & 0x3F; + rtumsg.MsgData[sizeof(CLPDU_VARR)+10] = sCurTime.Hour & 0x1F; + // SIN + rtumsg.MsgData[sizeof(CLPDU_VARR)+11] = 0; + + len = 14; + ptrClpdu_varr->nLEN1 = len; + ptrClpdu_varr->nLEN2 = len; + rtumsg.MsgData[sizeof(CLPDU_VARR)+1] = 0x81; + //COT + rtumsg.MsgData[sizeof(CLPDU_VARR)+2] = M_CAUSE_AUTOSEND; + // 重新赋值 ASDU 公共地址 + rtumsg.MsgData[sizeof(CLPDU_VARR)+3] = (BYTE)pProvDevParam->m_iProvAddr; + // FUN + rtumsg.MsgData[sizeof(CLPDU_VARR)+4] = pProvDevParam->m_sYxInfo.m_psDataInfo[j].m_u8ProvFun; + // INF + rtumsg.MsgData[sizeof(CLPDU_VARR)+5] = pProvDevParam->m_sYxInfo.m_psDataInfo[j].m_u8ProvInf; + // DPI + rtumsg.MsgData[sizeof(CLPDU_VARR)+6] = pntmsg.Status+1; + + len = ptrClpdu_varr->nLEN1 + 4; + // 发送时会重新计算 + //rtumsg.MsgData[len++] = CalBuban103Lpc(rtumsg.MsgData+4, ptrClpdu_varr->nLEN1); + rtumsg.MsgData[len++] = 0; + rtumsg.MsgData[len++] = 0x16; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char*)rtumsg.MsgData, len); + } + else + { + pPortParam->m_psBaoHu->DiChange = FALSE; + } + + return bFind; +} + +i_32 PackOneValueIntoPackage(BYTE *pbDestBuf, u_32 uMaxBufLen, BYTE bDataFormat, + u_32 uDataType, u_32 uDataLen, BYTE *pbSourData) +{ + i_32 iCount, k; + float *ptrfValue, fValue; + double *ptrdbValue; + short *ptri16Value; + i_32 *ptriValue; + + iCount = 0; + + // 数据类型 + switch(bDataFormat) + { + case 0:// 模拟量 + // pbSourData[0] // 数据源长度 + fValue = *(float*)(pbSourData+1); + // 数据长度 + pbDestBuf[iCount++] = (BYTE)uDataLen; + pbDestBuf[iCount++] = 1; + // 数据长度(103中无用) + //rtumsg->MsgData[uOffset++]; + //ptrfValueSour = (float *)&rtumsg->MsgData[uOffset]; + if(uDataType == DATAID_UI)// 无符号整数 + { + if(uDataLen == 1) + { + pbDestBuf[iCount] = (BYTE)((u_32)fabs(fValue)); + } + else if(uDataLen == 2) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = (short)fabs(fValue); + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + else if(uDataLen == 4) + { + ptriValue = (i_32 *)&pbDestBuf[iCount]; + *ptriValue = (i_32)fabs(fValue); + SequenceHostToRtu((char *)ptriValue, sizeof(i_32)); + } + } + // wen 2005.04.05 北京四方扩展数据类型 + //else if(uDataType == DATAID_INT) + else if((DATAID_INT == uDataType) || ( DATAID_EXDATA_0X24 == uDataType)) + { + if(uDataLen == 1) + { + pbDestBuf[iCount] = (BYTE)((i_32)fabs(fValue)); + } + else if(uDataLen == 2) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = (short)fabs(fValue); + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + else if(uDataLen == 4) + { + ptriValue = (i_32 *)&pbDestBuf[iCount]; + *ptriValue = (i_32)fabs(fValue); + SequenceHostToRtu((char *)ptriValue, sizeof(i_32)); + } + } + else if(uDataType == DATAID_UFLOAT)// 无符号浮点数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = (float)fabs(fValue); + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_FLOAT)// 浮点数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = fValue; + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_754SHORT)// R32.23 IEEE 标准754短实数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = fValue; + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_754REAL)// R64.53 IEEE 标准754实数 + { + ptrdbValue = (double *)&pbDestBuf[iCount]; + *ptrdbValue = fValue; + SequenceHostToRtu((char *)ptrdbValue, sizeof(double)); + } + else if(uDataType == DATAID_13BITS) // 带品质描述的被测值(13BITS) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = ((short)(fValue)) & 0x1fff; + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + // wen 2004.07.26 修改该类型数据的处理 + else if(uDataType == DATAID_BSTRING) // 8位2进制码 + { + uDataLen = (uDataLen + 7) / 8; + for(k=0; k<(int)uDataLen; k++); + { + pbDestBuf[iCount+k] = (BYTE)(((int)(fValue)) / 256); + fValue /= 256; + } + } + + iCount += uDataLen; + break; + case 1:// 开关量 + // pbSourData[0] // 数据源长度 + fValue = *(float*)(pbSourData+1); + // 数据长度 + pbDestBuf[iCount++] = (BYTE)uDataLen; + pbDestBuf[iCount++] = 1; + if(uDataType == DATAID_UI)// 无符号整数 + { + if(uDataLen == 1) + { + pbDestBuf[iCount] = (BYTE)((u_32)fabs(fValue)); + } + else if(uDataLen == 2) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = (short)fabs(fValue); + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + else if(uDataLen == 4) + { + ptriValue = (i_32 *)&pbDestBuf[iCount]; + *ptriValue = (i_32)fabs(fValue); + SequenceHostToRtu((char *)ptriValue, sizeof(i_32)); + } + } + else if( uDataType == DATAID_INT) + { + if(uDataLen == 1) + { + pbDestBuf[iCount] = (BYTE)((i_32)fabs(fValue)); + } + else if(uDataLen == 2) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = (short)fabs(fValue); + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + else if(uDataLen == 4) + { + ptriValue = (i_32 *)&pbDestBuf[iCount]; + *ptriValue = (i_32)fabs(fValue); + SequenceHostToRtu((char *)ptriValue, sizeof(i_32)); + } + } + else if(uDataType == DATAID_UFLOAT)// 无符号浮点数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = (float)fabs(fValue); + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_FLOAT)// 浮点数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = fValue; + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_754SHORT)// R32.23 IEEE 标准754短实数 + { + ptrfValue = (float *)&pbDestBuf[iCount]; + *ptrfValue = fValue; + SequenceHostToRtu((char *)ptrfValue, sizeof(float)); + } + else if(uDataType == DATAID_754REAL)// R64.53 IEEE 标准754实数 + { + ptrdbValue = (double *)&pbDestBuf[iCount]; + *ptrdbValue = fValue; + SequenceHostToRtu((char *)ptrdbValue, sizeof(double)); + } + else if(uDataType == DATAID_13BITS) // 带品质描述的被测值(13BITS) + { + ptri16Value = (short *)&pbDestBuf[iCount]; + *ptri16Value = ((short)(fValue)) &0x1fff; + SequenceHostToRtu((char *)ptri16Value, sizeof(short)); + } + // wen 2004.07.26 修改该类型数据的处理 + else if(uDataType == DATAID_BSTRING) // 8位2进制码 + { + uDataLen = (uDataLen + 7) / 8; + for(k=0; k<(int)uDataLen; k++); + { + pbDestBuf[iCount+k] = (BYTE)(((int)(fValue)) / 256); + fValue /= 256; + } + } + else if(uDataType == DATAID_DOUBLE)// 双点信息 + { + pbDestBuf[iCount] = (BYTE)((u_32)(fabs(fValue)+1)); + } + else if(uDataType == DATAID_SINGLE)// 单点信息 + { + pbDestBuf[iCount] = (BYTE)((u_32)fabs(fValue)); + } + + iCount += uDataLen; + break; + case 3:// 字符串 + pbDestBuf[iCount++] = pbSourData[0]; + pbDestBuf[iCount++] = 1; + if(uDataType == DATAID_OS8ASCII)// 8位ASCII + { + memcpy((void *)(pbDestBuf+iCount), (void *)(pbSourData+1), pbSourData[0]); + iCount += pbSourData[0]; + } + break; + } + + return iCount; +} + +// 部颁103和斯凯达内部规约间的格式转换 +void Buban103ScadaCmdchange(int commid, RTUMSG *rtumsg) +{ + u_32 uInterAction, uOffset, uDataLen, uDataType; + u_char bFaultNo; + i_32 i, j, k, iGroupNo, iStartNo, iCPUNo, offset; + BOOL bIsValidCmd; + GEN_DATAGROUP sGenDataGroup; + PROTECTCONTENTHEAD *ptrProHead; + BYTE bSourData[4096]; + i_32 iFixDataNGD; + CMDPARAM sCmdParam; + PROTECTMSG PrtMsg; + int iProvAddr, iYkNo; + DEVDEF *pDevParam; + DEVADDRPARAM sAddrParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + char szbuf[256]; + + memcpy((void *)&PrtMsg, rtumsg->MsgData, rtumsg->MsgLen); + ptrProHead = (PROTECTCONTENTHEAD *)PrtMsg.MsgData; + + if(FALSE == GetPortParamPtr(commid, &pPortParam)) + { + return; + } + iProvAddr = ptrProHead->uAddr; + sprintf(szbuf, "地址=%d ", ptrProHead->uAddr); + DebugPrint(szbuf); + + if(FALSE == FindProtectDevFromProvAddr(pPortParam, &sAddrParam, iProvAddr)) + { + sprintf(szbuf, "地址错误 "); + DebugPrint(szbuf); + return; + } + + // wen 2005.06.06 增加数据返回时的上下文存储 + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_iBaoHuCommid = rtumsg->PortIdx; + memcpy((void *)&pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_sRealAddrParam, + (void *)&sAddrParam, sizeof(DEVADDRPARAM)); + GetLocalTimeEx(&pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_sBaoHuCmdStartTime); + pPortParam->m_psLink[sAddrParam.m_iLinkIdx].m_sBaoHuCmdParam.m_iBaoHuMsgType = MSGTYPE_BAOHU_SCADACMD; + + bIsValidCmd = TRUE; + uOffset = sizeof(PROTECTCONTENTHEAD); + + pLinkParam = &pPortParam->m_psLink[sAddrParam.m_iLinkIdx]; + pDevParam = &pLinkParam->m_psDev[sAddrParam.m_iDevIdx]; + // CPU号与分组号一一对应 + if((ptrProHead->cCPUNo != (char)0xFF) && (ptrProHead->cCPUNo != 0)) + { + pDevParam->m_sDevParam.m_u8CPUNo = ptrProHead->cCPUNo; + } + if((ptrProHead->cFixNo != (char)0xFF) && (ptrProHead->cFixNo != 0)) + { + pDevParam->m_sDevParam.m_u8FixNo = ptrProHead->cFixNo; + } + + iCPUNo = 1; + + // 保护指令记忆 + if(ptrProHead->uAddr != 0xff) + { + pDevParam->m_sDevParam.m_u32FuncCode = ptrProHead->uFuncCode; + } + + memcpy((void *)&sCmdParam.m_sDevAddr, (void *)&sAddrParam, sizeof(DEVADDRPARAM)); + switch(ptrProHead->uFuncCode) + { + case hREADFIX:// 读取定值(只存在一个保护定值组的情况) + uInterAction = hREADINGDATA; + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(PROTECT_FIX_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + sprintf(szbuf, "第%d组CPU号= %d!!!\n", i+1, + pDevParam->m_sDevParam.m_u8CPUNo); + DebugPrint(szbuf); + if(pDevParam->m_sDevParam.m_u8CPUNo == iCPUNo) + { + break; + } + else + { + iCPUNo++; + } + } + } + + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { + bIsValidCmd = FALSE; + + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d不存在保护定值!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); + break; + } + + pDevParam->m_sDevParam.m_saGroupDef[i].m_u32CurPntNo = 1; + sCmdParam.m_uchInf = C_INF_READGROUPALLITEMS; + sGenDataGroup.m_u8Grp = (BYTE)pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + sGenDataGroup.m_u8Itm = 0; + sGenDataGroup.m_u8KOD = PrtMsg.MsgData[uOffset]; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentCommand_CAsdu21(commid, &sCmdParam, &sGenDataGroup, 1); + break; + case hREADFIXNO:// 读取定值区号 + uInterAction = hREADINGDATA; + bIsValidCmd = FALSE; + break; + case hREADPAI:// 读取保护模拟量 + uInterAction = hREADINGDATA; + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(PROTECT_AI_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + break; + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d不存在保护模拟量!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + break; + } + + pDevParam->m_sDevParam.m_saGroupDef[i].m_u32CurPntNo = 1; + sCmdParam.m_uchInf = C_INF_READGROUPALLITEMS; + sGenDataGroup.m_u8Grp = (BYTE)pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + sGenDataGroup.m_u8Itm = 0; + sGenDataGroup.m_u8KOD = PrtMsg.MsgData[uOffset]; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentCommand_CAsdu21(commid, &sCmdParam, &sGenDataGroup, 1); + break; + case hREADPDI:// 读取保护开关量 + uInterAction = hREADINGDATA; + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(PROTECT_DI_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + break; + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d不存在保护开关量!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + break; + } + + pDevParam->m_sDevParam.m_saGroupDef[i].m_u32CurPntNo = 1; + sCmdParam.m_uchInf = C_INF_READGROUPALLITEMS; + sGenDataGroup.m_u8Grp = (BYTE)pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + sGenDataGroup.m_u8Itm = 0; + sGenDataGroup.m_u8KOD = PrtMsg.MsgData[uOffset]; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentCommand_CAsdu21(commid, &sCmdParam, &sGenDataGroup, 1); + break; + case hREADPWAVE:// 读取保护波形数据 + case hQUERYFAULT:// 读取指定故障报告 + bFaultNo = rtumsg->MsgData[sizeof(PROTECTCONTENTHEAD)]; + uInterAction = hREADINGDATA; + bIsValidCmd = FALSE; + break; + case hQUERYSELFCHECK:// 读取指定的自检报告 + bFaultNo = rtumsg->MsgData[sizeof(PROTECTCONTENTHEAD)]; + uInterAction = hREADINGDATA; + bIsValidCmd = FALSE; + break; + case hWRITEALLFIX:// 修改保护定值 + uInterAction = hREADINGDATA; + //uOffset += 12; + pDevParam->m_u32CallCnt = pLinkParam->m_u32TimeOutConst; + + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(PROTECT_FIX_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + if(pDevParam->m_sDevParam.m_u8CPUNo == iCPUNo) + { + break; + } + else + { + iCPUNo++; + } + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d不存在保护定值!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + break; + } + iGroupNo = pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + iStartNo = *((int *)&PrtMsg.MsgData[uOffset]); + sprintf(szbuf, "修改定值组帧开始 组号=%d, 起始点号=%d, uoffset=%d 接收数据:\n",iGroupNo, iStartNo, uOffset); + DebugPrint(szbuf); + for(k=0; kMsgLen; k+=6) + { + sprintf(szbuf, "%2X %2X %2X %2X %2X %2X",rtumsg->MsgData[k],rtumsg->MsgData[k+1],rtumsg->MsgData[k+2],rtumsg->MsgData[k+3],rtumsg->MsgData[k+4],rtumsg->MsgData[k+5]); + DebugPrint(szbuf); + } + + // wen 2004.02.02 当前数据处理时的起始点号 + pDevParam->m_sDevParam.m_saGroupDef[i].m_u32CurPntNo = 1; + + if(pDevParam->m_sDevParam.m_saGroupDef[i].m_bInit == FALSE) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 组号%d 未先读取定值!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr, iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + uOffset += 4; + offset = 0; + + for(j=0, iFixDataNGD=0; (uOffsetMsgLen) && (jm_sDevParam.m_saGroupDef[i].m_iPntNum); j++, iFixDataNGD++) + { + // wen 2004.02.02 如果一帧数据无法全部完成写定值工作,则分成多帧来完成 + if(offset >= 200) + { + sCmdParam.m_uchInf = C_INF_WRITEITEMWITHACK; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentData_CAsdu10(commid, &sCmdParam, bSourData, (BYTE)iFixDataNGD); + offset = 0; + iFixDataNGD = 0; + } + + // wen 2004.01.07 每一个数据都有索引 + bSourData[offset++] = (BYTE)iGroupNo; + + // wen 2004.02.02 用存储的条目号 + //bSourData[offset++] = (BYTE)(iStartNo-1+j); + bSourData[offset++] = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8GIN[iStartNo-1+j]; + bSourData[offset++] = 1; + + uDataType = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8DataType[iStartNo-1+j]; + uDataLen = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8DataLen[iStartNo-1+j]; + bSourData[offset++] = (BYTE)uDataType; + // 不能处理字符串 + offset += PackOneValueIntoPackage(bSourData+offset, sizeof(bSourData)-offset, + PrtMsg.MsgData[uOffset], uDataType, uDataLen, &PrtMsg.MsgData[uOffset+1]); + sprintf(szbuf, "第%d点定值的组号=%d,条目号=%d,数据类型=%d,数据宽度=%d,值=%d; %02X %02X %02X %02X",iStartNo-1+j,\ + iGroupNo,pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8GIN[iStartNo-1+j],\ + uDataType, uDataLen, *(float*)(&PrtMsg.MsgData[uOffset+1+1]), PrtMsg.MsgData[uOffset+2], PrtMsg.MsgData[uOffset+3], PrtMsg.MsgData[uOffset+4], PrtMsg.MsgData[uOffset+5]); + DebugPrint(szbuf); + + uOffset += sizeof(float)+2; + } + if(iFixDataNGD > 0) + { + sCmdParam.m_uchInf = C_INF_WRITEITEMWITHACK; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentData_CAsdu10(commid, &sCmdParam, bSourData, (BYTE)iFixDataNGD); + } + break; + case hWRITEFIXNO:// 修改保护定值区 + uInterAction = hREADINGDATA; + pDevParam->m_u32CallCnt = pLinkParam->m_u32TimeOutConst; + bIsValidCmd = FALSE; + break; + case hRESETPROTECT:// 保护信号复归 + //Param.bCmdIdx = APPLY_REVERT; + uInterAction = hREADDATAEND; + if(pDevParam->m_sDevParam.m_sYkDBOrientation.m_iPntNum <= 0) + { + bIsValidCmd = FALSE; + break; + } + else + { + bIsValidCmd = TRUE; + } + + iYkNo = pDevParam->m_sDevParam.m_sYkDBOrientation.m_iStartPntNo; + bSourData[0] = (BYTE)(commid & 0xFF); + bSourData[1] = (BYTE)((commid & 0xFF00) << 8); + bSourData[2] = (BYTE)((commid & 0xFF0000) << 16); + bSourData[3] = (BYTE)((commid & 0xFF000000) << 24); + + bSourData[4] = (BYTE)(iYkNo & 0xFF); + bSourData[5] = (BYTE)((iYkNo & 0xFF00) << 8); + bSourData[6] = (BYTE)((iYkNo & 0xFF0000) << 16); + bSourData[7] = (BYTE)((iYkNo & 0xFF000000) << 24); + + bSourData[8] = STEP_YKYT_EXEC; + bSourData[9] = 1; + Buban103YkYtProcess(commid, bSourData, 10); + break; + case hCHECKTIME:// 单个装置对时 + //Param.bCmdIdx = CHECK_TIME; + uInterAction = hREADINGDATA; + MakeTimeSyn_CAsdu6(commid, &sCmdParam); + break; + case hBROADCASTCHECKTIME:// 保护装置广播对时 + uInterAction = hREADDATAEND; + sCmdParam.m_sDevAddr.m_uchLinkAddr = 0xFF; + MakeTimeSyn_CAsdu6(commid, &sCmdParam); + break; + + case hWRITEFIXACK: // 修改保护定值确认 + sCmdParam.m_uchInf = C_INF_WRITEITEMWITHEXEC; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentData_CAsdu10(commid, &sCmdParam, NULL, 0); + uInterAction = hREADDATAEND; + break; + + case hWRITEFIXNAK: // 修改保护定值不确认 + sCmdParam.m_uchInf = C_INF_STOPWRITEITEM; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentData_CAsdu10(commid, &sCmdParam, NULL, 0); + uInterAction = hREADDATAEND; + break; + + // wen 2004.09.29 + case hWRITESPECIALFIX:// 修改指定的保护定值 + uInterAction = hREADINGDATA; + pDevParam->m_u32CallCnt = pLinkParam->m_u32TimeOutConst; + + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(PROTECT_FIX_PNT_TYPE == pDevParam->m_sDevParam.m_saGroupDef[i].m_iDataType) + { + if(pDevParam->m_sDevParam.m_u8CPUNo == iCPUNo) + { + break; + } + else + { + iCPUNo++; + } + } + } + if(i == pDevParam->m_sDevParam.m_iCfgGroupNum) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d不存在保护定值!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + break; + } + iGroupNo = pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo; + iStartNo = *((int *)&PrtMsg.MsgData[uOffset]); + + pDevParam->m_sDevParam.m_saGroupDef[i].m_u32CurPntNo = iStartNo; + + if(pDevParam->m_sDevParam.m_saGroupDef[i].m_bInit == FALSE) + { + bIsValidCmd = FALSE; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 组号%d 未先读取定值!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr, iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + uOffset += 4; + offset = 0; + + // wen 2004.01.07 每一个数据都有索引 + bSourData[offset++] = (BYTE)iGroupNo; + + // wen 2004.02.02 用存储的条目号 + bSourData[offset++] = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8GIN[iStartNo-1]; + bSourData[offset++] = 1; + + uDataType = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8DataType[iStartNo-1]; + uDataLen = pDevParam->m_sDevParam.m_saGroupDef[i].m_pu8DataLen[iStartNo-1]; + bSourData[offset++] = (BYTE)uDataType; + + // 不能处理字符串 + offset += PackOneValueIntoPackage(bSourData+offset, sizeof(bSourData)-offset, + PrtMsg.MsgData[uOffset], uDataType, uDataLen, &PrtMsg.MsgData[uOffset+1]); + + uOffset += sizeof(float)+2; + + sCmdParam.m_uchInf = C_INF_WRITEITEMWITHACK; + sCmdParam.m_uchRII = RII_PROV_ID; + MakeGenIdentData_CAsdu10(commid, &sCmdParam, bSourData, 1); + break; + default: + bIsValidCmd = FALSE; + break; + } + + // 保护地址不合法或者指令不合法时或者查询指令错误, 直接退出 + if( !bIsValidCmd ) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d指令不可识别!!!\n", + commid, sAddrParam.m_uchLinkAddr, sAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + + MakeInteractionCmd(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid, commid, hREADDATAEND, ptrProHead, FALSE); + } + else + { + MakeInteractionCmd(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid, commid, uInterAction, ptrProHead, FALSE); + } +} + +void Buban103GDprocessWithPAIToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid, iItemNum; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + u_32 *puStartNo; + int iOffset, offset; + double fValue; + float *pfValue; + BOOL bFirst, bNumChanged; + PROTECTCONTENTHEAD *ptrProHead; + RTUMSG sendmsg; + PROTECTMSG msg; + VALUEDEF sValue; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + + if(pGroupParam->m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据空间为零!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + memset((void *)&msg, 0, sizeof(PROTECTMSG)); + msg.MsgType = fPFV_PROTECT_BYPASS_ACK; + msg.PortNumber = commid; + // 操作用户 + ptrProHead = (pPROTECTCONTENTHEAD)msg.MsgData; + ptrProHead->ummid = 0xFFFFFFFF; + ptrProHead->uAddr = pDevParam->m_sDevParam.m_iProvAddr; + // 定值区号(不需要时,填写0xFF) + ptrProHead->cFixNo = (char)pDevParam->m_sDevParam.m_u8FixNo; + // C P U 号(不需要时,填写0xFF) + ptrProHead->cCPUNo = (char)pDevParam->m_sDevParam.m_u8CPUNo; + + // 操作类型 + ptrProHead->uFuncCode = hPAIDATA; + // 扩展保留 + + offset = sizeof(PROTECTCONTENTHEAD); + // 实际条目类型 + msg.MsgData[offset++] = u8KOD; + + // 起始序号 + puStartNo = (u_32*)&msg.MsgData[offset]; + + offset += sizeof(u_32); + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(TRUE == bFirst) + { + if(u8ItemNo == 0) + { + pGroupParam->m_u32CurPntNo = 1; + } + else if(u8ItemNo <= pGroupParam->m_iStartItemNo) + { + pGroupParam->m_u32CurPntNo = 1; + } + + if((M_INF_WRITEITEMWITHACK == u8INF) + && (pGroupParam->m_bInit == FALSE)) + { + for(j=0; jm_iPntNum; j++) + { + if(pGroupParam->m_pu8GIN[j] == u8ItemNo) + { + break; + } + } + + if(j >= pGroupParam->m_iPntNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,不匹配的GIN=%d!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8ItemNo, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + pGroupParam->m_u32CurPntNo = j+1; + } + + *puStartNo = pGroupParam->m_u32CurPntNo; + bFirst = FALSE; + } + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + // wen 2004.02.01 如果条目号为0,则该条目为该组条目数量,不上送 + if((u8ItemNo == 0) && (j == 0)) + { + iOffset += u8DataLen; + continue; + } + + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + //pGroupParam->m_pu8DataLen[pGroupParam->m_u32CurPntNo-1] = u8DataLen; + //pGroupParam->m_pu8DataType[pGroupParam->m_u32CurPntNo-1] = u8DataType; + pGroupParam->m_pu8GIN[pGroupParam->m_u32CurPntNo-1] = u8ItemNo+j; + } + + if(GetOneValueOfASDU10(&rtumsg->MsgData[iOffset], &sValue, u8DataType, u8DataLen) == FALSE) + { + iOffset += u8DataLen; + continue; + } + iOffset += u8DataLen; + + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + fValue = sValue.m_unValue.m_uValue; + break; + case DT_INT: + fValue = sValue.m_unValue.m_iValue; + break; + case DT_FLOAT: + fValue = sValue.m_unValue.m_fValue; + break; + case DT_CONTROL: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_STRING: + fValue = -1; + break; + case DT_BINARY: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_NO:// 无数据 + default: + fValue = -1; + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + if((u8ItemNo == 0) && (j == 0)) + { + if((fValue > 0) && (KOD_ACTUALVALUE == u8KOD)) + { + if((int)fValue > pGroupParam->m_iPntNum) + { + //pGroupParam->m_iPntNum = (int)sValue.m_unValue.m_uValue; + bNumChanged = TRUE; + } + else + { + pGroupParam->m_iPntNum = (int)fValue; + } + } + } + } + if(TRUE == bNumChanged) + { + //freeallfixmemory + } + + if(DT_STRING != sValue.m_iDataType) + { + pfValue = (float *)&msg.MsgData[offset]; + *pfValue = (float)fValue; + offset += sizeof(float); + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_u32DataID = u8DataType; + } + + pGroupParam->m_u32CurPntNo++; + } + } + + if(pGroupParam->m_iPntNum > 0) + { + if((int)pGroupParam->m_u32CurPntNo >= pGroupParam->m_iPntNum) + { + pGroupParam->m_bInit = TRUE; + pGroupParam->m_u32CurPntNo = 1; + } + } + + msg.MsgLen = offset; + + sendmsg.MsgLen = (WORD)(msg.MsgLen+sizeof(PROTECTMSGHEAD)); + sendmsg.MsgType = MSGTYPE_BAOHU_SCADADATA; + sendmsg.PortIdx = pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid; + memcpy(sendmsg.MsgData, (BYTE *)&msg, sendmsg.MsgLen); + PutBaohuDataToPort(&sendmsg); + + if(pDevParam->m_sDevParam.m_u32FuncCode == hREADPAI) + { + if(TRUE == pGroupParam->m_bInit) + { + MakeInteractionCmd(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid, commid, hREADDATAEND, ptrProHead, FALSE); + pDevParam->m_sDevParam.m_u32FuncCode = 0; + } + } +} + +void Buban103GDprocessWithPDIToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid, iItemNum; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + u_32 *puStartNo; + int iOffset, offset; + double fValue; + BOOL bFirst, bNumChanged; + PROTECTCONTENTHEAD *ptrProHead; + RTUMSG sendmsg; + PROTECTMSG msg; + VALUEDEF sValue; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + + if(pGroupParam->m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据空间为零!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + memset((void *)&msg, 0, sizeof(PROTECTMSG)); + msg.MsgType = fPFV_PROTECT_BYPASS_ACK; + msg.PortNumber = commid; + // 操作用户 + ptrProHead = (pPROTECTCONTENTHEAD)msg.MsgData; + ptrProHead->ummid = 0xFFFFFFFF; + ptrProHead->uAddr = pDevParam->m_sDevParam.m_iProvAddr; + // 定值区号(不需要时,填写0xFF) + ptrProHead->cFixNo = (char)pDevParam->m_sDevParam.m_u8FixNo; + // C P U 号(不需要时,填写0xFF) + ptrProHead->cCPUNo = (char)pDevParam->m_sDevParam.m_u8CPUNo; + + // 操作类型 + ptrProHead->uFuncCode = hPDIDATA; + // 扩展保留 + + offset = sizeof(PROTECTCONTENTHEAD); + // 实际条目类型 + msg.MsgData[offset++] = u8KOD; + + // 起始序号 + puStartNo = (u_32*)&msg.MsgData[offset]; + + offset += sizeof(u_32); + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(TRUE == bFirst) + { + if(u8ItemNo == 0) + { + pGroupParam->m_u32CurPntNo = 1; + } + else if(u8ItemNo <= pGroupParam->m_iStartItemNo) + { + pGroupParam->m_u32CurPntNo = 1; + } + + if((M_INF_WRITEITEMWITHACK == u8INF) + && (pGroupParam->m_bInit == FALSE)) + { + for(j=0; jm_iPntNum; j++) + { + if(pGroupParam->m_pu8GIN[j] == u8ItemNo) + { + break; + } + } + + if(j >= pGroupParam->m_iPntNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,不匹配的GIN=%d!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8ItemNo, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + pGroupParam->m_u32CurPntNo = j+1; + } + + *puStartNo = pGroupParam->m_u32CurPntNo; + bFirst = FALSE; + } + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + // wen 2004.02.01 如果条目号为0,则该条目为该组条目数量,不上送 + if((u8ItemNo == 0) && (j == 0)) + { + iOffset += u8DataLen; + continue; + } + + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + //pGroupParam->m_pu8DataLen[pGroupParam->m_u32CurPntNo-1] = u8DataLen; + //pGroupParam->m_pu8DataType[pGroupParam->m_u32CurPntNo-1] = u8DataType; + pGroupParam->m_pu8GIN[pGroupParam->m_u32CurPntNo-1] = u8ItemNo+j; + } + + if(GetOneValueOfASDU10(&rtumsg->MsgData[iOffset], &sValue, u8DataType, u8DataLen) == FALSE) + { + iOffset += u8DataLen; + continue; + } + iOffset += u8DataLen; + + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + fValue = sValue.m_unValue.m_uValue; + break; + case DT_INT: + fValue = sValue.m_unValue.m_iValue; + break; + case DT_FLOAT: + fValue = sValue.m_unValue.m_fValue; + break; + case DT_CONTROL: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_STRING: + fValue = -1; + break; + case DT_BINARY: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_NO:// 无数据 + default: + fValue = -1; + break; + } + + /* + if(pGroupParam->m_bInit == FALSE) + { + if((u8ItemNo == 0) && (j == 0)) + { + if((fValue > 0) && (KOD_ACTUALVALUE == u8KOD)) + { + if((int)fValue > pGroupParam->m_iPntNum) + { + //pGroupParam->m_iPntNum = (int)sValue.m_unValue.m_uValue; + bNumChanged = TRUE; + } + else + { + pGroupParam->m_iPntNum = (int)fValue; + } + } + } + } + if(TRUE == bNumChanged) + { + //freeallfixmemory + } + */ + + if(DT_BINARY == sValue.m_iDataType) + { + if(2 == sValue.m_iDataNum) + { + if((fValue < 1) || (fValue > 2)) + { + fValue = 0; + } + else + { + fValue -= 1; + } + } + } + + if(fValue > 0) + { + msg.MsgData[offset++] = TRUE; + } + else + { + msg.MsgData[offset++] = FALSE; + } + + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_u32DataID = u8DataType; + } + + pGroupParam->m_u32CurPntNo++; + } + } + + if(pGroupParam->m_iPntNum > 0) + { + if((int)pGroupParam->m_u32CurPntNo >= pGroupParam->m_iPntNum) + { + pGroupParam->m_bInit = TRUE; + pGroupParam->m_u32CurPntNo = 1; + } + } + + msg.MsgLen = offset; + + sendmsg.MsgLen = (WORD)(msg.MsgLen+sizeof(PROTECTMSGHEAD)); + sendmsg.MsgType = MSGTYPE_BAOHU_SCADADATA; + sendmsg.PortIdx = pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid; + memcpy(sendmsg.MsgData, (BYTE *)&msg, sendmsg.MsgLen); + PutBaohuDataToPort(&sendmsg); + + if(pDevParam->m_sDevParam.m_u32FuncCode == hREADPDI) + { + if(TRUE == pGroupParam->m_bInit) + { + MakeInteractionCmd(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid, commid, hREADDATAEND, ptrProHead, FALSE); + pDevParam->m_sDevParam.m_u32FuncCode = 0; + } + } +} + +void Buban103GDprocessWithPFIXToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx) +{ + int i, j, commid, iItemNum; + BYTE u8KOD, u8INF, u8DataType; + BYTE u8DataNum, u8DataLen, u8ItemNo; + u_32 *puStartNo; + int iOffset, offset; + double fValue; + float *pfValue; + BOOL bFirst, bNumChanged; + PROTECTCONTENTHEAD *ptrProHead; + RTUMSG sendmsg; + PROTECTMSG msg; + VALUEDEF sValue; + GROUPDEF *pGroupParam; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; +//#ifdef _DEBUG_MSG_ + char szbuf[256]; +//#endif + + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada"); + DebugPrint(szbuf); + commid = rtumsg->PortIdx; + if(FALSE == GetSpecialPtr(commid, psDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + bNumChanged = FALSE; + bFirst = TRUE; + iOffset = 14; + pGroupParam = &pDevParam->m_sDevParam.m_saGroupDef[iGroupIdx]; + + if(pGroupParam->m_iPntNum <= 0) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据空间为零!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + if((iOffset+3) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时, 数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + u8INF = rtumsg->MsgData[11]; + u8KOD = rtumsg->MsgData[16]; + pGroupParam->m_u8NGD = rtumsg->MsgData[13]; + + if((0xf9 == u8INF) && (rtumsg->MsgData[8] == 0x29)) + { + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada写定值确认失败"); + DebugPrint(szbuf); + } + if((0xf9 == u8INF) && (rtumsg->MsgData[8] == 0x2c)) + { + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada写定值确认成功"); + DebugPrint(szbuf); + } + if((0xfa == u8INF) && (rtumsg->MsgData[8] == 0x28)) + { + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada写定值执行成功"); + DebugPrint(szbuf); + } + if((0xfa == u8INF) && (rtumsg->MsgData[8] == 0x29)) + { + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada写定值执行失败"); + DebugPrint(szbuf); + } + if((0xfb == u8INF) && (rtumsg->MsgData[8] == 0x28)) + { + sprintf(szbuf, "Buban103GDprocessWithPFIXToScada写定值终止执行成功"); + DebugPrint(szbuf); + } + + memset((void *)&msg, 0, sizeof(PROTECTMSG)); + msg.MsgType = fPFV_PROTECT_BYPASS_ACK; + msg.PortNumber = commid; + // 操作用户 + ptrProHead = (pPROTECTCONTENTHEAD)msg.MsgData; + ptrProHead->ummid = 0xFFFFFFFF; + ptrProHead->uAddr = pDevParam->m_sDevParam.m_iProvAddr; + // 定值区号(不需要时,填写0xFF) + ptrProHead->cFixNo = (char)pDevParam->m_sDevParam.m_u8FixNo; + // C P U 号(不需要时,填写0xFF) + ptrProHead->cCPUNo = (char)pDevParam->m_sDevParam.m_u8CPUNo; + + // 操作类型 + ptrProHead->uFuncCode = hFIXDATA; + // 扩展保留 + + offset = sizeof(PROTECTCONTENTHEAD); + // 实际条目类型 + msg.MsgData[offset++] = u8KOD; + + // 起始序号 + puStartNo = (u_32*)&msg.MsgData[offset]; + + offset += sizeof(u_32); + + iItemNum = pGroupParam->m_u8NGD & 0x3F; + for(i=0; i= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 数据长度(单个数据长*数量) + u8DataNum = rtumsg->MsgData[iOffset+5]; + u8DataLen = rtumsg->MsgData[iOffset+4]; + if((iOffset+6+u8DataLen*u8DataNum) >= rtumsg->MsgLen) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)处理时,数据帧长度不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + break; + } + + // 组 号 + // 条目号 + u8ItemNo = rtumsg->MsgData[iOffset+1]; + iOffset += 2; + + if(TRUE == bFirst) + { + if(u8ItemNo == 0) + { + pGroupParam->m_u32CurPntNo = 1; + } + else if(u8ItemNo <= pGroupParam->m_iStartItemNo) + { + pGroupParam->m_u32CurPntNo = 1; + } + + if((M_INF_WRITEITEMWITHACK == u8INF) + && (pGroupParam->m_bInit == FALSE)) + { + for(j=0; jm_iPntNum; j++) + { + if(pGroupParam->m_pu8GIN[j] == u8ItemNo) + { + break; + } + } + + if(j >= pGroupParam->m_iPntNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,不匹配的GIN=%d!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, u8ItemNo, pGroupParam->m_iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + pGroupParam->m_u32CurPntNo = j+1; + } + + *puStartNo = pGroupParam->m_u32CurPntNo; + bFirst = FALSE; + } + + if(u8KOD != rtumsg->MsgData[iOffset]) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10(Group=%d)写确认处理时,数据KOD=%d与要求的KOD=%d不符!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, pGroupParam->m_iGroupNo, rtumsg->MsgData[iOffset], u8KOD); + DebugPrint(szbuf); +#endif + iOffset += u8DataLen*u8DataNum + 4; + continue; + } + else + { + iOffset++; + } + + u8DataType = rtumsg->MsgData[iOffset++]; + iOffset += 2; + for(j=0; j<(int)u8DataNum; j++) + { + // wen 2004.02.01 如果条目号为0,则该条目为该组条目数量,不上送 + if((u8ItemNo == 0) && (j == 0)) + { + iOffset += u8DataLen; + continue; + } + + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + break; + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_pu8DataLen[pGroupParam->m_u32CurPntNo-1] = u8DataLen; + pGroupParam->m_pu8DataType[pGroupParam->m_u32CurPntNo-1] = u8DataType; + pGroupParam->m_pu8GIN[pGroupParam->m_u32CurPntNo-1] = u8ItemNo+j; + } + + if(GetOneValueOfASDU10(&rtumsg->MsgData[iOffset], &sValue, u8DataType, u8DataLen) == FALSE) + { + iOffset += u8DataLen; + continue; + } + iOffset += u8DataLen; + + switch(sValue.m_iDataType) + { + case DT_UINT:// 无符号整型数 + fValue = sValue.m_unValue.m_uValue; + break; + case DT_INT: + fValue = sValue.m_unValue.m_iValue; + break; + case DT_FLOAT: + fValue = sValue.m_unValue.m_fValue; + break; + case DT_CONTROL: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_STRING: + fValue = -1; + break; + case DT_BINARY: + fValue = sValue.m_unValue.m_dwValue; + break; + case DT_NO:// 无数据 + default: + fValue = -1; + break; + } + + if(DT_STRING == sValue.m_iDataType) + { + msg.MsgData[offset++] = DATATYPE_STRING; + msg.MsgData[offset++] = (BYTE)sValue.m_iDataNum; + memcpy((void *)&msg.MsgData[offset], sValue.m_szValue, sValue.m_iDataNum); + offset += sValue.m_iDataNum; + } + else if(DT_BINARY == sValue.m_iDataType) + { + if(2 == sValue.m_iDataNum) + { + if((fValue < 1) || (fValue > 2)) + { + fValue = 0; + } + else + { + fValue -= 1; + } + } + + msg.MsgData[offset++] = DATATYPE_DI; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + //遥信量也是以float的形式上送的 + //if(fValue > 0) + //{ + // msg.MsgData[offset++] = TRUE; + //} + //else + //{ + // msg.MsgData[offset++] = FALSE; + //} + //=============================================================== + if(fValue > 0) + { + fValue = TRUE; + } + else + { + fValue = FALSE; + } + + pfValue = (float *)&msg.MsgData[offset]; + *pfValue = (float)fValue; + offset += sizeof(float); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + else + { + // 南瑞装置的开关量以无符号整数送上来 + //msg.MsgData[offset++] = DATATYPE_AI; + if(pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].iFixDataType == 2) + msg.MsgData[offset++] = DATATYPE_DI; + else + msg.MsgData[offset++] = DATATYPE_AI; + + pfValue = (float *)&msg.MsgData[offset]; + *pfValue = (float)fValue; + offset += sizeof(float); + } + + if(pGroupParam->m_bInit == FALSE) + { + pGroupParam->m_psDataInfo[pGroupParam->m_u32CurPntNo-1].m_u32DataID = u8DataType; + } + + pGroupParam->m_u32CurPntNo++; + } + } + + if(pGroupParam->m_iPntNum > 0) + { + if((int)pGroupParam->m_u32CurPntNo > pGroupParam->m_iPntNum) + { + sprintf(szbuf, "当前处理点号m_u32CurPntNo=%d, 定值总数m_iPntNum= %d", pGroupParam->m_u32CurPntNo, pGroupParam->m_iPntNum); + DebugPrint(szbuf); + pGroupParam->m_bInit = TRUE; + pGroupParam->m_u32CurPntNo = 1; + } + } + + msg.MsgLen = offset; + + sendmsg.MsgLen = (WORD)(msg.MsgLen+sizeof(PROTECTMSGHEAD)); + sendmsg.MsgType = MSGTYPE_BAOHU_SCADADATA; + sendmsg.PortIdx = pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid; + memcpy(sendmsg.MsgData, (BYTE *)&msg, sendmsg.MsgLen); + PutBaohuDataToPort(&sendmsg); + + if(pDevParam->m_sDevParam.m_u32FuncCode == hREADFIX) + { + if(TRUE == pGroupParam->m_bInit) + { + MakeInteractionCmd(pLinkParam->m_sBaoHuCmdParam.m_iBaoHuCommid, commid, hREADDATAEND, ptrProHead, FALSE); + pDevParam->m_sDevParam.m_u32FuncCode = 0; + } + } + + ptrProHead = (pPROTECTCONTENTHEAD)&sendmsg.MsgData[sizeof(PROTECTMSGHEAD)]; + // wen 2004.01.06 写定值确认 + if((M_CAUSE_WRITEACK == rtumsg->MsgData[8]) + || ( M_CAUSE_WRITECONFIRM == rtumsg->MsgData[8])) + { + ptrProHead->uFuncCode = hWRITEFIXACK; + Buban103ScadaCmdchange(commid, &sendmsg); + } + else if(M_CAUSE_WRITENAK == rtumsg->MsgData[8]) + { + ptrProHead->uFuncCode = hWRITEFIXNAK; + Buban103ScadaCmdchange(commid, &sendmsg); + } +} + +void Buban103ScadaDatachange(int commid, RTUMSG *rtumsg) +{ + // 类型标识(TYP):10 + //rtumsg->MsgData[6]; + + // 可变结构限定词(VSQ):0x81 + //rtumsg->MsgData[7]; + + // 传送原因(COT) + //rtumsg->MsgData[8]; + + // 应用服务数据单元公共地址 + //rtumsg->MsgData[9]; + + // 功能类型(FUN): 254(0xfe) + //rtumsg->MsgData[10]; + + // 信息序号(INF): + // 读组标题 : 240 + // 读一个组的全部条目的值或属性 : 241 + // 读单个条目的目录 : 243 + // 读单个条目的值或属性 : 244 + // 对通用分类数据总查询中止 : 245 + //rtumsg->MsgData[11]; + + // 返回信息标识符(RII) + //rtumsg->MsgData[12]; + + // 通用分类数据集数目 + //rtumsg->MsgData[13]; + + // 以下为多个通用分类数据 + // 通用分类标识序号(GIN):条目号和组号 + //rtumsg->MsgData[14]; + + // 描述类别(KOD) + // 无所指定的描述类别 : KOD_NOSPECIFIED(0) + // 实际值 : KOD_ACTUALVALUE(1) + // 缺省值 : KOD_DEFAULTVALUE(2) + // 量程(最大值、最小值、步长) : KOD_RANGE(3) + // 备用 : KOD_BACKUP1(4) + // 精度(n,m) : KOD_PRECISION(5) + // 因子 : KOD_FACTOR(6) + // 参比 : KOD_REFERENCE(7) + // 列表 : KOD_ENUMERATION(8) + // 量纲 : KOD_DIMENSION(9) + // 描述 : KOD_DESCRIPTION(10) + // 备用 : KOD_BACKUP2(11) + // 口令条目 : KOD_PASSWORD(12) + // 只读 : KOD_READONLY(13) + // 只写 : KOD_WRITEONLY(14) + // 备用 : KOD_BACKUP3(15) + // 备用 : KOD_BACKUP4(16) + // 备用 : KOD_BACKUP5(17) + // 备用 : KOD_BACKUP6(18) + // 相应的功能类型和信息序号 : KOD_CORFUNCANDINF(19) + // 相应的事件 : KOD_COREVENT(20) + // 列表的文本阵列 : KOD_ENUMTEXTARRAY(21) + // 列表的值阵列 : KOD_ENUMVALUEARRAY(22) + // 相关联的条目 : KOD_RELATEDENTRIES(23) + //rtumsg->MsgData[16]; + + // 数据类型描述 + //rtumsg->MsgData[17]; + //DATAID_NO : 无数据 + //DATAID_OS8ASCII : 8位ASCII + //DATAID_BSTRING : 8位2进制数 + //DATAID_UIX : 无符号整数 + //DATAID_INT : 整数 + //DATAID_UFLOAT : 无符号浮点数 + //DATAID_FLOAT : 浮点数 + //DATAID_754SHORT : R32.23 IEEE 标准754短实数 + //DATAID_754REAL : R64.53 IEEE 标准754实数 + //DATAID_DOUBLE : 双点信息 + //DATAID_SINGLE : 单点信息 + //DATAID_13BITS : 带品质描述的被测值(13BITS) + //DATAID_SORTIDNO : 通用分类标识序号 + //DATAID_WITHTIME : 带时标的报文 + //DATAID_WITHTIMESPACE : 带相对时标的报文 + //DATAID_STRUCT : 数据结构 + + // 数据尺寸 + //rtumsg->MsgData[18] + + // 数量 + //rtumsg->MsgData[19] + + // 数据值(长度根据以上描述) + + // 2 ... n 个通用分类数据 + + int i, iGroupNo, iCfgGroupIdx; + DEVDEF *pDevParam; + BUBAN103LINKDEF *pLinkParam; + BUBAN103PORTPARAM *pPortParam; + DEVADDRPARAM sDevAddrParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + sDevAddrParam.m_uchLinkAddr = rtumsg->MsgData[5]; + sDevAddrParam.m_uchCommAddr = rtumsg->MsgData[9]; + pPortParam = (BUBAN103PORTPARAM *)SioParam[commid].ExtInfo; + if(FindProtectDev(pPortParam, &sDevAddrParam, FALSE) == FALSE) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d 不在端口配置保护范围内!!!", + commid, sDevAddrParam.m_uchLinkAddr, sDevAddrParam.m_uchCommAddr); + DebugPrint(szbuf); +#endif + return; + } + + if(FALSE == GetSpecialPtr(commid, &sDevAddrParam, &pPortParam, &pLinkParam, &pDevParam)) + { + return; + } + + //组 号 + iGroupNo = rtumsg->MsgData[14]; + for(i=0; im_sDevParam.m_iCfgGroupNum; i++) + { + if(pDevParam->m_sDevParam.m_saGroupDef[i].m_iGroupNo == iGroupNo) + { + iCfgGroupIdx = i; + break; + } + } + + if(i >= pDevParam->m_sDevParam.m_iCfgGroupNum) + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10 通用分类数据处理时,Group=%d不在处理范围内!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, iGroupNo); + DebugPrint(szbuf); +#endif + return; + } + + switch(pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iDataType) + { + // 处理保护模拟量 + case PROTECT_AI_PNT_TYPE: + Buban103GDprocessWithPAIToScada(rtumsg, &sDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护开关量 + case PROTECT_DI_PNT_TYPE: + Buban103GDprocessWithPDIToScada(rtumsg, &sDevAddrParam, iCfgGroupIdx); + break; + + // 处理保护定值 + case PROTECT_FIX_PNT_TYPE: + Buban103GDprocessWithPFIXToScada(rtumsg, &sDevAddrParam, iCfgGroupIdx); + break; + + default: +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d linkaddr=%d devaddr=%d ASDU10处理时, Group=%d数据类型(=%d)不匹配!!!\n", + commid, pLinkParam->m_uchLinkAddr, pDevParam->m_sDevParam.m_u8DevAddr, + pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iGroupNo, + pDevParam->m_sDevParam.m_saGroupDef[iCfgGroupIdx].m_iDataType); + DebugPrint(szbuf); +#endif + break; + } +} + +void Buban103ScadaProtocolExchange(int commid, RTUMSG *rtumsg) +{ + if(MSGTYPE_BAOHU_SCADACMD == rtumsg->MsgType) + { + // 下行命令 + Buban103ScadaCmdchange(commid, rtumsg); + } + + if(MSGTYPE_BAOHU_SCADADATA == rtumsg->MsgType) + { + // 上行数据 + Buban103ScadaDatachange(commid, rtumsg); + } +} + +void Buban103DispConfig(int commid, BUBAN103PORTPARAM *psPortParam) +{ + int i, j; + char szDbg[256]; + + sprintf(szDbg, ">>>Disp Commid_%02d Config(PortType=%d):", commid, psPortParam->m_psBaoHu->PortType); + DebugPrint(szDbg); + + sprintf(szDbg, ">>>LinkNum=%d", psPortParam->m_iLinkNum); + DebugPrint(szDbg); + + for(i=0; im_iLinkNum; i++) + { + sprintf(szDbg, ">>>LinkIdx=%d DevNum=%d", i, psPortParam->m_psLink[i].m_iDevNum); + DebugPrint(szDbg); + + if(PROTOCOL_MASTER == psPortParam->m_psBaoHu->PortType) + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + sprintf(szDbg, "###DevNo %d", j); + DebugPrint(szDbg); + sprintf(szDbg, ">>>ProvAddr=%d CfgGroupNum=%d, DevAddr=%d", + psPortParam->m_psLink[i].m_psDev[j].m_sDevParam.m_iProvAddr, + psPortParam->m_psLink[i].m_psDev[j].m_sDevParam.m_iCfgGroupNum, + psPortParam->m_psLink[i].m_psDev[j].m_sDevParam.m_u8DevAddr); + DebugPrint(szDbg); + DebugPrint((char*)"\n"); + } + } + else + { + for(j=0; jm_psLink[i].m_iDevNum; j++) + { + sprintf(szDbg, "###DevNo %d", j); + sprintf(szDbg, ">>>ProvAddr=%d Asdu10Num=%d, RealCommid=%d", + psPortParam->m_psLink[i].m_psProvDev[j].m_iProvAddr, + psPortParam->m_psLink[i].m_psProvDev[j].m_iAsdu10Num, + psPortParam->m_psLink[i].m_psProvDev[j].m_iRealCommid); + DebugPrint(szDbg); + DebugPrint((char*)"\n"); + } + } + } +} + +void Buban103DispMalloc(int commid, int iSize) +{ + char szbuf[128]; + + return; + + sprintf(szbuf, "disp: commid=%d, malloc(%d)", commid, iSize); + DebugPrint(szbuf); +} +//===========================转发数据处理结束========================= + +//===========================数据处理函数结束========================= \ No newline at end of file diff --git a/buban103.h b/buban103.h new file mode 100644 index 0000000..79d57d9 --- /dev/null +++ b/buban103.h @@ -0,0 +1,2255 @@ +/************************************************************************************ + * + * Copyright (C) 2004-2005 SCADA Control Technology Co., Ltd. + * All rights reserved. + * + * 文件名称:buban103.h + * 文件标识:部颁103规约 + * 摘 要:103规约的处理的结构、宏还有函数定义 + * + * 当前版本:1.0 + * 作 者:aaawen + * 完成日期:2005/04/22 + * + * 取代版本:1.0 + * 原作者 : + * 完成日期: + * + * 说 明:数据定义规则 + * u8 --- BYTE(usigned char) + * ch --- char + * w --- WORD(u_short, usigned short) + * sh --- short + * b --- BOOL(bool) + * i --- int + * l --- long + * u32 --- u_32 + * ui --- unsigned int(u_int) + * ul --- unsigned long(u_long) + * f --- float + * db --- double + * c --- class + * s --- struct + * sta --- static + * g --- 全局变量 + * Array --- 数组 + * a --- 数组 + * m_ --- 数据成员 + * p --- 指针 + * str --- 字符串 + * 全部大写 --- 常量 + * 首字节必须大写--- 类名称,结构,函数 + **************************************************************************************/ +// buban103.h: interface for the buban103 class. +// +////////////////////////////////////////////////////////////////////// +#if !defined(_BUBAN103_H_200504221547__INCLUDED_) +#define _BUBAN103_H_200504221547__INCLUDED_ +#ifdef OS_LINUX +#include "baohulib/common.h" +#else +#include "common.h" +#endif + +////////////////////////////////////////////////////////////////////////// +// 宏定义 // +// WEN 2001.03.09 // +////////////////////////////////////////////////////////////////////////// +/*! + \brief 保护信息转发返回码 + */ +#define RII_PROV_ID 0xFF + +/*! + \brief 遥测量起始点号 + */ +#define INF_AI_START 92 + +/*! + \brief 遥测量数量 + */ +#define INF_AI_NUM 57 + +/*! + \brief 遥信量起始点号 + */ +#define INF_DI_START 149 + +/*! + \brief 遥信量数量 + */ +#define INF_DI_NUM 89 + +/*! + \brief 电度量起始点号 + */ +#define INF_PI_START 6 + +/*! + \brief 电度量数量 + */ +#define INF_PI_NUM 26 + +/*! + \brief 遥控点起始点号 + */ +#define INF_YK_START 48 + +/*! + \brief 遥控点数量 + */ +#define INF_YK_NUM 28 + +/*! + \brief 遥调点起始点号 + */ +#define INF_YT_START 48 + +/*! + \brief 遥调点数量 + */ +#define INF_YT_NUM 28 + +/*! + \brief 每个装置配置的最大组号 + */ +#define GROUPNUM 16 + +/*! + \brief 文件名称长度 + */ +#define FILENAME_LEN 256 + +/*! + \brief 装置模拟量最大组数 + */ +#define DEV_AI_MAXNUM 7 + +/*! + \brief 字符串最大长度 + */ +#define MAXSTRINGLEN 64 + +/*! + \brief 定时召唤命令最大数目 + */ +#define BUBAN103_TIMER_CMD_NUM 5 + +// 应用服务数据单元ASDU的常量定义 +// 监视方向的类型标识 +#define M_TM_TA_3 1 //带时标的报文 +#define M_TMR_TA_3 2 //具有相对时间的带时标的报文 +#define M_MEI_NA_3 3 //被测值I +#define M_TME_TA_3 4 //具有相对时间的带时标的被测值 +#define M_IRC_NA_3 5 //标识 +#define M_SYN_TA_3 6 //时间同步 +#define M_TGI_NA_3 8 //总查询(总召唤)终止 +#define M_MEII_NA_3 9 //被测值II +#define M_GD_NTA_3 10 //通用分类数据 +#define M_GI_NTA_3 11 //通用分类标识 +#define M_LRD_TA_3 23 //被记录的扰动表 +#define M_RTD_TA_3 26 //扰动数据传输准备就绪 +#define M_RTC_NA_3 27 //被记录的通道传输准备就绪 +#define M_RTT_NA_3 28 //带标志的状态变位传输准备就绪 +#define M_TOT_TA_3 29 //传送带标志的状态变位 +#define M_TOV_NA_3 30 //传送扰动值 +#define M_EOT_TA_3 31 //传送结束 +#define M_MEIII_TA_3 32 //带时标的被测值Ⅲ +#define M_MEIV_TA_3 33 //带时标的被测值Ⅳ +#define M_MEV_TA_3 34 //带时标的被测值Ⅴ +#define M_MEVI_TA_3 35 //带时标的被测值Ⅵ +#define M_MEVII_NA_3 50 //被测值Ⅶ +#define M_IT_NA_3 36 //电能脉冲计数值 +#define M_IT_TA_3 37 //带时标的电能脉冲计数值 +#define M_ST_NA_3 38 //步位置信息 +#define M_ST_TA_3 39 //带时标的步位置信息 +#define M_SP_NA_3 40 //单点状态信息 +#define M_SP_TA_3 41 //带时标的单点状态信息 +#define M_DP_NA_3 42 //双点状态信息 +#define M_DP_TA_3 43 //带时标的双点状态信息 +#define M_SS_NA_3 44 //单点状态和状态变位检出 +#define M_SS_TA_3 45 //带时标的单点状态和状态变位检出 +#define M_DS_NA_3 46 //双点状态和状态变位检出 +#define M_DS_TA_3 47 //带时标的双点状态和状态变位检出 +#define M_WL_TA_3 48 //水位 +#define M_DC_NA_3 64 //控制断路器命令 +#define M_RC_NA_3 65 //升降命令 +#define M_SE_NA_3 66 //设定命令 +#define M_CC_NA_3 67 //控制命令 +#define M_EX_PI_3 205 //电度命令(SIEMENS公司) + +// 控制方向的类型标识 +#define C_SYN_TA_3 6 //时间同步 +#define C_TGI_NA_3 7 //总查询(总召唤) +#define C_GD_NA_3 10 //通用分类数据 +#define C_GRC_NA_3 20 //一般命令 +#define C_GC_NA_3 21 //通用分类命令 +#define C_ODT_NA_3 24 //扰动数据传输的命令 +#define C_ADT_NA_3 25 //扰动数据传输的认可 +#define C_DC_NA_3 64 //控制断路器命令 +#define C_RC_NA_3 65 //升降命令 +#define C_SE_NA_3 66 //设定命令 +#define C_CC_NA_3 67 //控制命令 +#define C_CI_NA_3 88 //电能脉冲计数召唤命令 + +// 链路规约数据单元LDPU的常量定义 +// 监视方向的控制域功能码 +#define M_CON_NA_3 0 //确认帧 +#define M_BY_NA_3 1 //忙帧(确认帧) +#define M_DATA_NA_3 8 //以数据响应请求帧 +#define M_NV_NA_3 9 //无所要求的数据帧回答 +#define M_LKR_NA_3_1 11 //链路状态响应帧--链路工作正常 +#define M_LKR_NA_3_2 14 //链路状态响应帧--链路服务未工作 +#define M_LKR_NA_3_3 15 //链路状态响应帧--链路服务未实现 + +// 控制方向的控制功能码 +#define C_RFB_NA_3 7 //复位帧计数 +#define C_RCU_NA_3 0 //复位通讯单元 +#define C_PL1_NA_3 10 //召唤一级用户数据 +#define C_PL2_NA_3 11 //召唤二级用户数据 +#define C_RLK_NA_3 9 //请求链路状态 +#define C_SD1_NA_3 3 //传送数据(发送/确认帧) +#define C_SD2_NA_3 4 //传送数据(发送/无回答帧) + +// 功能类型 +#define FUNC_DISTANCEPROTECT 128 // 距离保护 +#define FUNC_OVERCURRENTPROTECT 160 // 过流保护 +#define FUNC_TRANSFORMERPROTECT 176 // 变压器差动保护 +#define FUNC_LINEPROTECT 192 // 线路差动保护 +#define FUNC_GENERALSORT 254 // 通用分类功能 +#define FUNC_GLOBAL 255 // 全局功能类型 + +// 命令类型 +#define ORDER_FAULTSELECT 1 // 故障的选择 +#define ORDER_REQUESTDATA 2 // 请求扰动数据 +#define ORDER_STOPDATA 3 // 终止扰动数据 +#define ORDER_REQUESTSTATUSWITHFLAG 16 // 请求带标志的状态变位 +#define ORDER_STOPSTATUSWITHFLAG 17 // 终止带标志的状态变位 +#define ORDER_REQUESTRECORDTABLE 24 // 请求被记录的扰动表 + +// 在监视方向的通用分类功能的信息序号 +#define M_INF_READGROUPTITLE 240 // 读组标题 +#define M_INF_READGROUPALLITEMS 241 // 读一个组的全部条目的值或属性 +#define M_INF_READDIROFSINGLEITEM 243 // 读单个条目的目录 +#define M_INF_READATTROFISNGLEITEM 244 // 读单个条目的值或属性 +#define M_INF_STOPQUERYGENERAL 245 // 对通用分类数据总查询中止 +#define M_INF_WRITEITEMWITHACK 249 // 带确认的写条目 +#define M_INF_WRITEITEMWITHEXEC 250 // 带执行的写条目 +#define M_INF_WRITEITEMWITHSTOP 251 // 带终止的写条目 + +// 在控制方向的通用分类功能的信息序号 +#define C_INF_READGROUPTITLE 240 // 读组标题 +#define C_INF_READGROUPALLITEMS 241 // 读一个组的全部条目的值或属性 +#define C_INF_READDIROFSINGLEITEM 243 // 读单个条目的目录 +#define C_INF_READATTROFISNGLEITEM 244 // 读单个条目的值或属性 +#define C_INF_QUERYGENERAL 245 // 对通用分类数据总查询 +#define C_INF_WRITEITEM 248 // 写条目 +#define C_INF_WRITEITEMWITHACK 249 // 带确认的写条目 +#define C_INF_WRITEITEMWITHEXEC 250 // 带执行的写条目 +#define C_INF_STOPWRITEITEM 251 // 写条目终止 + +// 信息组号 +#define GROUP_SYSTEM0 0x00 // 系统类(所有保护及自动装置的系统参数及功能、定值区切换) +#define GROUP_SYSTEM1 0x01 // 系统类 +#define GROUP_FIXVALUE0 0x02 // 定值类 +#define GROUP_FIXVALUE1 0x03 // 定值类 +#define GROUP_EVENT0 0x04 // 事件类(动作及状态事件) +#define GROUP_EVENT1 0x05 // 事件类(如告警事件) +#define GROUP_AIVALUE0 0x06 // 遥测类(保护测量值) +#define GROUP_AIVALUE1 0x07 // 遥测类(如电流、电压、功率、频率、水位、温度等) +#define GROUP_DISOE 0x08 // 遥信类(如刀闸、开关、信号、状态等) 遥信SOE +#define GROUP_DIVALUE0 0x09 // 遥信类 +#define GROUP_PIVALUE 0x0a // 电量类 +#define GROUP_YKSWITCH 0x0b // 遥控开关类(跳/合) +#define GROUP_YKDANGWEI 0x0c // 遥控分头类(升/降) +#define GROUP_YTDAOUT 0x0d // 遥调类(DA输出) +#define GROUP_YKYABAN 0x0e // 遥控压板类(保护功能投/退) +#define GROUP_DEBUGANDOPERATE 0x0f // 调试及操作信息类(用于装置的调试及操作记录) +#define GROUP_DIVALUE1 0x18 // 遥信类(如刀闸、开关、信号、状态等) 遥信状态 + +// 传送原因 +// 监视方向 +#define M_CAUSE_AUTOSEND 1 // 自发(突发) +#define M_CAUSE_CYCLE 2 // 循环 +#define M_CAUSE_RESET_FCB 3 // 复位帧计数位(FCB) +#define M_CAUSE_RESET_CU 4 // 复位通信单元(CU) +#define M_CAUSE_START 5 // 启动/重新启动 +#define M_CAUSE_POWERON 6 // 电源合上 +#define M_CAUSE_TEST 7 // 测试模式 +#define M_CAUSE_CHECKTIME 8 // 时间同步 +#define M_CAUSE_QUERY 9 // 总查询 +#define M_CAUSE_STOPQUERY 10 // 总查询停止 +#define M_CAUSE_LOCAL 11 // 当地操作 +#define M_CAUSE_REMOTE 12 // 远方操作 +#define M_CAUSE_ACK 20 // 命令的肯定认可 +#define M_CAUSE_NAK 21 // 命令的否定认可 +#define M_CAUSE_DSITURBANCEDATA 31 // 扰动数据的传送 +#define M_CAUSE_WRITEACK 40 // 通用分类写命令的肯定认可 +#define M_CAUSE_WRITENAK 41 // 通用分类写命令的否定认可 +#define M_CAUSE_READWITHVALIDDATA 42 // 对通用分类读命令有效数据响应 +#define M_CAUSE_READWITHINVALIDDATA 43 // 对通用分类读命令无效数据响应 +#define M_CAUSE_WRITECONFIRM 44 // 通用分类写确认 + +// 控制方向 +#define C_CAUSE_CYCLE 2 // 循环 +#define C_CAUSE_CHECKTIME 8 // 时间同步 +#define C_CAUSE_QUERY 9 // 总查询 +#define C_CAUSE_COMMAND 20 // 一般命令 +#define C_CAUSE_DSITURBANCEDATA 31 // 扰动数据的传送 +#define C_CAUSE_WRITEWITHVALIDDATA 40 // 通用分类写命令 +#define C_CAUSE_READWITHVALIDDATA 42 // 通用分类读命令 + +// 数据ID +#define DATAID_NO 0 // 无数据 +#define DATAID_OS8ASCII 1 // 8位ASCII +#define DATAID_BSTRING 2 // 字符串 +#define DATAID_UI 3 // 无符号整数 +#define DATAID_INT 4 // 整数 +#define DATAID_UFLOAT 5 // 无符号浮点数 +#define DATAID_FLOAT 6 // 浮点数 +#define DATAID_754SHORT 7 // R32.23 IEEE 标准754短实数 +#define DATAID_754REAL 8 // R64.53 IEEE 标准754实数 +#define DATAID_DOUBLE 9 // 双点信息 +#define DATAID_SINGLE 10 // 单点信息 +#define DATAID_13BITS 12 // 带品质描述的被测值(13BITS) +#define DATAID_SORTIDNO 15 // 通用分类标识序号 +#define DATAID_WITHTIME 18 // 带时标的报文 +#define DATAID_WITHTIMESPACE 19 // 带相对时标的报文 +#define DATAID_STRUCT 23 // 数据结构 +#define DATAID_EXDATA_0X24 0x24 // 北京四方扩展数据类型 + +// 描述类别 +#define KOD_NOSPECIFIED 0 // 无所指定的描述类别 +#define KOD_ACTUALVALUE 1 // 实际值 +#define KOD_DEFAULTVALUE 2 // 缺省值 +#define KOD_RANGE 3 // 量程(最大值、最小值、步长) +#define KOD_BACKUP1 4 // 备用 +#define KOD_PRECISION 5 // 精度(n,m) +#define KOD_FACTOR 6 // 因子 +#define KOD_REFERENCE 7 // 参比 +#define KOD_ENUMERATION 8 // 列表 +#define KOD_DIMENSION 9 // 量纲 +#define KOD_DESCRIPTION 10 // 描述 +#define KOD_BACKUP2 11 // 备用 +#define KOD_PASSWORD 12 // 口令条目 +#define KOD_READONLY 13 // 只读 +#define KOD_WRITEONLY 14 // 只写 +#define KOD_BACKUP3 15 // 备用 +#define KOD_BACKUP4 16 // 备用 +#define KOD_BACKUP5 17 // 备用 +#define KOD_BACKUP6 18 // 备用 +#define KOD_CORFUNCANDINF 19 // 相应的功能类型和信息序号 +#define KOD_COREVENT 20 // 相应的事件 +#define KOD_ENUMTEXTARRAY 21 // 列表的文本阵列 +#define KOD_ENUMVALUEARRAY 22 // 列表的值阵列 +#define KOD_RELATEDENTRIES 23 // 相关联的条目 + +/////////////////////////////结构定义///////////////////////////////// +/*! + \struct PROV_ALLITEMOFGROUPPARAM + \brief 转发条目参数定义 + + \par 快速参考 + buban103.h + */ +typedef struct{ + /*! + \var PROV_ALLITEMOFGROUPPARAM::m_u8RII + \brief 主站信息返回值 + + \note + 取值范围:[0---255]\n + */ + unsigned char m_u8RII; + /*! + \var PROV_ALLITEMOFGROUPPARAM::m_u8Group + \brief 信息组号 + + \note + 取值范围:[0---255]\n + */ + unsigned char m_u8Group; + /*! + \var PROV_ALLITEMOFGROUPPARAM::m_u8ItemNo + \brief 信息条目号 + + \note + 取值范围:[0---255]\n + */ + unsigned char m_u8ItemNo; + /*! + \var PROV_ALLITEMOFGROUPPARAM::m_u8ItemAttr + \brief 条目属性 + \note + (实际值、缺省值、量程... ...) + \note + 取值范围:[1、3、9、10]\n + */ + unsigned char m_u8ItemAttr; + /*! + \var PROV_ALLITEMOFGROUPPARAM::m_bFinished + \brief 数据读取完成标识 + + \note + 取值范围:[TRUE/FALSE]\n + */ + BOOL m_bFinished; +}PROV_ALLITEMOFGROUPPARAM; + +/*! + \struct DEVPARAMDEF + \brief 设备结构 + + \par 快速参考 + buban103.h + */ +typedef struct{ + /*! + \var DEVPARAMDEF::m_szDevName + \brief 装置名称 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为64]\n + */ + char m_szDevName[66]; + /*! + \var DEVPARAMDEF::m_u8DevAddr + \brief 保护装置地址 + + \note + 取值范围:[1-254,255为广播地址]\n + */ + u_char m_u8DevAddr; + + /*! + \var DEVPARAMDEF::m_iCfgGroupNum + \brief 保护装置组配置数量 + + \note + 取值范围: [0--GROUPNUM]\n + */ + i_32 m_iCfgGroupNum; + + /*! + \var DEVPARAMDEF::m_saGroupDef[] + \brief 保护装置类型 + + \par 快速参考 + GROUPDEF结构 + + \note + 取值范围: 无\n + */ + GROUPDEF m_saGroupDef[GROUPNUM]; + + /*! + \var DEVPARAMDEF::m_szType[] + \brief 间隔(保护装置)类型 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为64]\n + "LFP984B", "RCS921A", "RCS931A", "LFP965B"等\n + */ + char m_szType[64]; + + /*! + \var DEVPARAMDEF::m_szDatFileName[] + \brief 间隔(保护装置)数据信息配置文件名称 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为256]\n + */ + //char m_szDatFileName[FILENAME_LEN]; + + /*! + \var DEVPARAMDEF::m_sAiDBOrientation + \brief 基本模拟测量量在数据库中定位 + \note + 数据包括七组测量值 + */ + DBORIENTATION m_sAiDBOrientation[DEV_AI_MAXNUM]; + + /*! + \var DEVPARAMDEF::m_sDiDBOrientation + \brief 基本模拟测量量在数据库中定位 + \note + 数据包括单点和双点遥信量 + */ + DBORIENTATION m_sDiDBOrientation; + + /*! + \var DEVPARAMDEF::m_sPiDBOrientation + \brief 基本模拟测量量在数据库中定位 + */ + DBORIENTATION m_sPiDBOrientation; + + /*! + \var DEVPARAMDEF::m_sStepDBOrientation + \brief 步位置信息测量量在数据库中定位 + \note + 数据写入模拟量数据库 + */ + DBORIENTATION m_sStepDBOrientation; + + /*! + \var DEVPARAMDEF::m_sYkDBOrientation + \brief 遥控信息量在数据库中定位 + \note + 数据不写入数据库 + */ + DBORIENTATION m_sYkDBOrientation; + + /*! + \var DEVPARAMDEF::m_sSyncTimeInfo + \brief 时间同步信息 + */ + DBINFO m_sSyncTimeInfo; + + /*! + \var DEVPARAMDEF::m_iProvAddr + \brief 转发保护地址 + + \note + 用于端口与单个装置的通讯 + \note + 取值范围:[-1, 非负整数]\n + */ + i_32 m_iProvAddr; + + /*! + \var DEVPARAMDEF::m_u32FuncCode + \brief 保护命令功能码生成记忆 + + \note + 用于数据返回时,生成交互指令 + \note + 取值范围:hREADFIX : 读取定值\n + hREADFIXNO : 读取定值区号\n + hREADPAI : 读取保护模拟量\n + hREADPDI : 读取保护开关量\n + hREADPWAVE : 读取保护波形数据\n + hQUERYFAULT : 读取指定故障报告\n + hQUERYSELFCHECK : 读取指定的自检报告\n + hWRITEALLFIX : 修改保护定值\n + hWRITESPECIALFIX : 修改指定的保护定值\n + hWRITEFIXNO : 修改保护定值区\n + hRESETPROTECT : 保护信号复归\n + hCHECKTIME : 单个装置对时\n + hBROADCASTCHECKTIME : 保护装置广播对时\n + hCANCEL : 保护操作取消\n + */ + u_32 m_u32FuncCode; + + /*! + \var DEVPARAMDEF::m_iYkStartPnt + \brief 遥控起始点号 + + \note + 用于端口与单个装置的通讯 + \note + 取值范围:[-1, 非负整数]\n + */ + i_32 m_iYkStartPnt; + + /*! + \var DEVPARAMDEF::m_iYtStartPnt + \brief 遥调起始点号 + + \note + 用于端口与单个装置的通讯 + \note + 取值范围:[-1, 非负整数]\n + */ + i_32 m_iYtStartPnt; + + BYTE m_u8SCN; + /*! + \var DEVPARAMDEF::m_u8CPUNo + \brief 当前CPU号 + + \note + 用于端口与单个装置的通讯 + \note + 取值范围:[1, ... ,255]\n + \note + 其中255为当前CPU号,对于多组定值来说,cpu号和组号一一对应\n + */ + BYTE m_u8CPUNo; + + /*! + \var DEVPARAMDEF::m_u8FixNo + \brief 定值区号 + + \note + 用于端口与单个装置的通讯 + \note + 取值范围:[1, ... ,255]\n + \note + 其中255为当前定值区号 + */ + BYTE m_u8FixNo; + + /*! + \var DEVPARAMDEF::m_iFaultNo + \brief 故障序号 + + \note + 仅用于扰动数据上送时 + */ + i_32 m_iFaultNo; +}DEVPARAMDEF; + +/*! + \struct PROVDEVPARAMDEF + \brief 设备结构 + + \par 快速参考 + buban103.h + */ +typedef struct +{ + /*! + \var DEVPARAMDEF::m_sProvGroupParam + \brief 转发组数据参数 + + \note + 仅用于转发组所有数据时,一帧无法完成的情况 + */ + PROV_ALLITEMOFGROUPPARAM m_sProvGroupParam; + + /*! + \var PROVDEVPARAMDEF::m_sProvSoe + \brief 转发SOE数据参数 + + \note + 用于历史记录的转发事件 + */ + DEVPROVSOE m_sProvSoe; +}PROVDEVPARAMDEF; + +typedef struct +{ + i_32 m_iCmdTimerCnt; //命令时间计数 + i_32 m_iCmdTimerConst; //命令时间常量 +} BUBAN103CMDDEF; + +// wen 2003.10.27 保存扰动数据故障序号等参数 +typedef struct +{ + BYTE m_u8FUN; //功能类型(FUN) + BYTE m_u8Res1; //未用 + BYTE m_u8Res2; //未用 + BYTE m_u8TOV; //扰动值类型(TOV) + WORD m_wFAN; //故障序号(FAN) + WORD m_wNOF; //电网故障序号(NOF) + BYTE m_u8NOC; //通道数目 + WORD m_wNOE; //一个通道信息元素的数目 + WORD m_wINT; //信息元素间的间隔 + WORD m_wHour; //时 + WORD m_wMinute; //分 + WORD m_wSecond; //秒 + WORD m_wMilliseconds; //毫秒 + WORD m_wYear; //年 + WORD m_wMonth; //月 + WORD m_wDay; //日 + + BOOL m_bRecvRight; //接收是否正确 + + BYTE m_u8ACC; //通道号 + int m_iNum; //缓冲区psValue 数量 + int m_iDataNum; //缓冲区psValue 扰动值的数量 + short *m_pshValue; //扰动值 +} BUBAN103DISTURBANCEDEF; + +typedef struct tagDISTURBANCEDIDATA +{ + int m_iNo; // 序号 + int m_iNum; // 数量 + + int m_iTap; // 偏移 + BYTE m_u8Fun; // 功能类型 + BYTE m_u8Inf; // 信息序号 + short m_shValue; // 数值 + + struct tagDISTURBANCEDIDATA *m_psCurUse; // 正在使用的指针 + struct tagDISTURBANCEDIDATA *m_psRight; // 右指针 + struct tagDISTURBANCEDIDATA *m_psBottom; // 下指针 +}DISTURBANCEDIDATA, *pDISTURBANCEDIDATA; + +typedef struct tagDISTURBANCEAIDATA +{ + int m_iACCNo; // 通道号 + int m_iTOV; // 扰动值类型 + double m_dbRPV; // 额定一次值 + double m_dbRSV; // 额定二次值 + double m_dbfRFA; // 参比因子 + int m_iNOE; // 采样值数量 + int m_iNOC; // 模拟量数量 + + short *m_pshValue; // 模拟量值 +}DISTURBANCEAIDATA, *pDISTURBANCEAIDATA; + +/*应用服务数据单元的报文结构定义*/ + +typedef struct +{ + //WORD m_wGIN; //通用分类标识序号 + BYTE m_u8Grp; //组号 + BYTE m_u8Itm; //条目号 + BYTE m_u8KOD; //类型描述 +}GEN_DATAGROUP; //通用分类数据组 + +//监视方向的应用服务数据单元结构 +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nDPI; //双点信息 + unsigned char nTIME[4]; //四个八位位组二进制时间 + unsigned char nSIN; //附加信息 +}MASDU1;//带时标的报文,nTYP=M_TM_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nDPI; //双点信息 + unsigned short nRET; //相对时间 + unsigned short nFAN; //故障序号 + unsigned char nTIME[4]; //四个八位位组二进制时间 + unsigned char nSIN; //附加信息 +}MASDU2;//带相对时间的时标报文,nTYP=M_TMR_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned short nMEA1; //B相电流 + unsigned short nMEA2; //AB相电压 + unsigned short nMEA3; //有功功率 + unsigned short nMEA4; //无功功率 +}MASDU3;//被测值I报文,nTYP=M_MEI_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + u_32 nSCL; //短路位置 + unsigned short nRET; //相对时间 + unsigned short nFAN; //故障序号 + unsigned char nTIME[4]; //四个八位位组二进制时间 +}MASDU4;//带相对时间的有时标被测值报文,nTYP=M_TME_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nCOL; //兼容级别 + unsigned char nASC[8]; //ASCII字符 + unsigned char nREV; //制造厂内部软件标识符,自由赋值 +}MASDU5;//标识报文,nTYP=M_IRC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned short nFAN; //故障序号 + unsigned char nTIME[7]; //七个八位位组二进制时间 +}MASDU6;//时间同步报文,nTYP=M_SYN_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nSCN; //扫描序号 +}MASDU8;//总查询(总召唤)终止报文,nTYP=M_TGI_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned short nMEA1; //A相电流Il1 + unsigned short nMEA2; //B相电流Il2 + unsigned short nMEA3; //C相电流Il3 + unsigned short nMEA4; //A相电压Ul1e + unsigned short nMEA5; //B相电压Ul2e + unsigned short nMEA6; //C相电压Ul3e + unsigned short nMEA7; //有功功率P + unsigned short nMEA8; //无功功率Q + unsigned short nMEA9; //频率f +}MASDU9;//被测值II报文,nTYP=M_MEII_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nRII; //返回标识符 + unsigned char nNGD; //通用分类数据集数目 + unsigned char* nDATASET;//数据集 + //GEN_DATASET nDATASET[]; 数据集 +}MASDU10;//通用分类数据报文,nTYP=M_GD_N(T)A_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nRII; //返回标识符 + unsigned char nGIN; //通用分类标识序号 + unsigned short nNDE; //描述元素的数目 + unsigned char* nDEL; //描述元素 + //GEN_DEL nDEL; //描述元素 +}MASDU11;//通用分类标识报文,nTYP=M_GI_N(T)A_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用其值应为0 + unsigned char* nDATASET;//数据集 + //DIS_DATASET nDATASET[]; //数据集 +}MASDU23;//被记录扰动表报文,nTYP=M_LRD_TA_3 + + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nRES; //保留值,未用 + unsigned char nTOV; //扰动值的类型 + unsigned short nFAN; //故障序号 + unsigned short nNOF; //电网故障序号 + unsigned char nNOC; //通道数目 + unsigned short nNOE; //一个通道信息元素的数目 + unsigned short nINT; //信息元素间的间隔 + unsigned char nTIME[4]; //四个八位位组二进制时间 +}MASDU26;//扰动数据传输准备就绪报文,nTYP=M_RTD_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nRES; //保留值,未用 + unsigned char nTOV; //扰动值类型 + unsigned short nFAN; //故障序号 + unsigned char nACC; //实际通道号 + u_32 nRPV; //一次额定值 + u_32 nRSV; //二次额定值 + u_32 nRFA; //参比因子 +}MASDU27;//被记录的通道传输就序报文,nTYP=M_RTC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nRES1; //保留值1,未用 + unsigned char nRES2; //保留值2,未用 + unsigned char nRES3; //保留值3,未用 + unsigned short nFAN; //故障序号 +}MASDU28;//带标志的状态变位的传输准备就绪报文,nTYP=M_RTT_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned short nFAN; //故障序号 + unsigned char nNOT; //带标志的状态位的数目 + unsigned short nTAP; //标志的位置 + struct{ + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nDPI; //双点信息 + } nSTATUS; //状态变位 +}MASDU29;//带标志的状态变位传输报文,nTYP=M_TOT_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nRES; //保留值,未用 + unsigned char nTOV; //扰动值类型 + unsigned short nFAN; //故障序号 + unsigned char nACC; //实际通道序号 + unsigned short nNDV; //每个应用服务数据单元有关扰动值的数目 + unsigned short nNFE; //每个应用服务数据单元的第一个信息元素的序号 + unsigned short* nSDV; //单个扰动值 +}MASDU30;//传输扰动值报文,nTYP=M_TOV_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nTOO; //命令类型 + unsigned char nTOV; //扰动值类型 + unsigned short nFAN; //故障序号 + unsigned char nACC; //实际通道 +}MASDU31;//传输结束报文,nTYP=M_EOT_TA_3 + +//控制方向上的应用服务数据单元结构 +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nTIME[7]; //七个八位位组二进制时间 +}CASDU6;//时间同步报文,nTYP=C_SYN_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nSCN; //扫描序号 +}CASDU7;//总查询(总召唤)启动报文,nTYP=C_IGI_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nRII; //返回信息标识符 + unsigned char nNGD; //通用分类数据数目 + unsigned char* nDATASET; //通用分类数据集 + //GEN_DATASET nDATASET[]; //通用分类数据集 +}CASDU10;//通用分类数据报文,nTYP=C_GD_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nDCO; //双命令 + unsigned char nRII; //返回信息标识符 +}CASDU20;//一般命令报文,nTYP=C_GRC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nRII; //返回信息标识符 + unsigned char nNOG; //通用分类标识数目 + GEN_DATAGROUP* nDATAGROUP; //数据集 +}CASDU21;//通用分类命令报文,nTYP=C_GC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nTOO; //命令类型 + unsigned char nTOV; //扰动值的类型 + unsigned short nFAN; //故障序号 + unsigned char nACC; //实际通道序号 +}CASDU24;//扰动数据传输的命令报文,nTYP=C_SYN_TA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号,未用 + unsigned char nTOO; //命令类型 + unsigned char nTOV; //扰动值的类型 + unsigned short nFAN; //故障序号 + unsigned char nACC; //实际通道号 +}CASDU25;//扰动数据传输的认可报文,nTYP=C_ADT_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nQCC; //电能脉冲计数量召唤命令的限定词 + unsigned char nRII; //返回信息标识符 +}CASDU88;//电能脉冲计数量的召唤命令,nTYP=C_CI_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nDCC; //控制断路器 + unsigned char nRII; //返回信息标识符 +}CASDU64;//控制断路器命令,nTYP=C_DC_NA_3 / C_EXDC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nRCC; //升降命令 + unsigned char nRII; //返回信息标识符 +}CASDU65;//控制断路器命令,nTYP=C_RC_NA_3 / C_EXRC_NA_3 + +typedef struct +{ + unsigned char nTYP; //类型标识 + unsigned char nVSQ; //可变结构限定词 + unsigned char nCOT; //传送原因 + unsigned char nADDR; //应用服务数据单元公共地址 + unsigned char nFUN; //功能类型 + unsigned char nINF; //信息序号 + unsigned char nCCC; //控制命令 + unsigned char nRII; //返回信息标识符 +}CASDU67;//控制断路器命令,nTYP=C_DC_NA_3 / C_EXDC_NA_3 + +/*链路层传输帧格式结构*/ +//控制方向 +typedef struct +{ + unsigned char nSTART1;//启动字符=68H + unsigned char nLEN1;//帧长=控制域+地址域+用户数据区 + unsigned char nLEN2;//帧长=控制域+地址域+用户数据区 + unsigned char nSTART2;//启动字符=68H + unsigned char nCONTROL;//控制域 + unsigned char nADDR;//地址域 +}CLPDU_VARR;//控制方向上的链路规约数据单元结构,可变帧长 + +typedef struct{ + unsigned char nSTART;//启动字符=10H + unsigned char nCONTROL;//控制域 + unsigned char nADDR;//地址域 + unsigned char nCS;//帧效验和 + unsigned char nEnd;//结束字符=16H +}CLPDU_FIX;//控制方向上的链路规约数据单元结构,固定帧长 + +typedef struct +{ + /*! + \brief 初始化标志 + \note + =TRUE 收到结束帧 + =FALSE 未收到结束帧 + 第一次总查询结束后置位,以后保持不变 + */ + BOOL m_bInitdata; + /*! + \brief 总召唤数据标识 + \note + =TRUE 总召唤数据结束,收到总召唤结束帧或者超时 + =FALSE 总召唤数据未结束 + */ + BOOL m_bAllQueryOk; + + /*! + \brief 召唤计数,用于控制召唤不到期望的值时跳出死循环 + */ + u_32 m_u32CallCnt; + /*! + \brief 返回码 + */ + u_char m_u8RII; + /*! + \brief 保存扰动数据故障序号等参数 + */ + BUBAN103DISTURBANCEDEF m_sDisturbanceParam; + /*! + \brief 中间信息存储的临时文件名称 + */ + char m_chArrayTmpFileName[FILENAME_LEN]; + /*! + \brief 设备定义,包括名称和地址 + */ + DEVPARAMDEF m_sDevParam; +}DEVDEF; + +typedef struct tagPROVDEVDEF +{ + /*! + \brief 设备定义,包括名称和地址 + */ + //PROVDEVPARAMDEF m_sDevParam; + + /*! + \brief 总查询进行中(=TRUE) + */ + BOOL m_bProvQuery; + i_32 m_iQueryPntNo; + /*! + \brief 总查询进行步骤中 + */ + i_32 m_iProvQueryStepWithASDU; + /*! + \brief 产生Asdu5的原因 + */ + i_32 m_iProvAsdu5Cause; + /*! + \brief 装置的实际端口号 + */ + i_32 m_iRealCommid; + /*! + \brief 装置的转发地址(唯一确定一个装置) + */ + i_32 m_iProvAddr; + /*! + \brief 转发SOE数据参数 + \note + 用于历史记录的转发事件(应该是没有作用,已经遗弃) + */ + DEVPROVSOE m_sProvSoe; + + /*! + \var PROVDEVDEF::m_sProvGroupParam + \brief 转发组数据参数 + + \note + 仅用于转发组所有数据时,一帧无法完成的情况 + */ + PROV_ALLITEMOFGROUPPARAM m_sProvGroupParam; + + i_32 m_iStatusStn; + i_32 m_iStatusPnt; + + DBORIENTATION m_sYxInfo; + DBORIENTATION m_sYcInfo; + DBORIENTATION m_sYmInfo; + i_32 m_iAsdu10Num; + + SINGLELIST m_sBaoHuData; +}PROVDEVDEF; + +#define MAX_PROV_DEVICE_NUM 64 // 转发保护装置最大数量 + +// wen 2005.10.08 修改控制字结构 +typedef struct tagBUBAN103LINKCTRL +{ + /*! + \brief 从站初始化标志 + \note + =1 ok + =0 no + */ + BOOL m_bLinkOk; + /*! + \brief 链接正常计数 + */ + u_32 m_u32LinkOkCnt; + /*! + \brief 控制信息 + */ + u_char m_u8CtlByte; + +}BUBAN103LINKCTRL, *pBUBAN103LINKCTRL; + +// wen 2003.10.27 增加全局参数定义 +typedef struct tagBUBAN103LINKDEF +{ + /*! + \var BUBAN103LINKDEF::m_szLinkName + \brief 链路名称 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为64]\n + */ + char m_szLinkName[66]; + /*! + \brief 主站发送总召唤、通用分类总召唤标志 + \note + 初始化时=FALSE,已发送命令后OK + */ + BOOL m_bRstLinkOk; + + /*! + \brief 是否转换到下一个装置 + \note + 在装置总召唤完成后,是否指向下一个装置 + */ + BOOL m_bGotoNext; + + /*! + \brief 从站初始化标志 + \note + =1 ok + =0 no + */ + BOOL *m_pbLinkOk; + /*! + \brief 链接正常计数 + */ + u_32 *m_pu32LinkOkCnt; + /*! + \brief 控制信息 + */ + u_char *m_pu8CtlByte; + // wen 2005.10.08 将以上3个动态分配成员指针修改为结构统一分配 + //BUBAN103LINKCTRL *m_pLinkCtrl; + + /*! + \brief 超时时间间隔 + */ + u_32 m_u32TimeOutConst; + /*! + \brief 当前指令索引 + */ + short m_shCurCmdIdx; + /*! + \brief 轮询指令生成时间 + */ + BUBAN103CMDDEF m_sArrayCmdTime[BUBAN103_TIMER_CMD_NUM]; + + /*! + 链路间隔装置数量 + */ + i_32 m_iDevNum; + /*! + 设备地址索引 + */ + i_32 m_iDevIdx; + + /*! + 一类数据的问询次数计算 + */ + i_32 m_iQueryNum_CLASS1_Const; + i_32 m_iQueryNum_CLASS1_Count; + + /*! + 一类数据已经查询地址,分时给别的装置查询数据 + */ + i_32 m_iQueryedAddr_CLASS1; + + /*! + \var BUBAN103LINKDEF::m_iProvAddrOffset + \brief 转发保护地址 + + \note + 用于端口与多个装置的通讯,总线方式 + \note + 取值范围:[非负整数]\n + */ + i_32 m_iProvAddrOffset; + + /*! + \var BUBAN103LINKDEF::m_iInputPort + \brief 输入厂站端口号 + + \note + 用于确定该厂站的通讯厂站端口 + \note + 取值范围:[非负整数]\n + \note + 0为本厂站端口,其它数值为通讯厂站端口 + */ + i_32 m_iInputPort; + + /*! + \var BUBAN103LINKDEF::m_chArrayTempletFileName[] + \brief 模板文件名称 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为256]\n + */ + char m_chArrayTempletFileName[FILENAME_LEN]; + + // wen 2004.01.15 增加链路地址以适用于ASDU与链路地址不同的情况 + /*! + \var BUBAN103LINKDEF::m_uchLinkAddr + \brief 链路地址 + + \note + 用于银山科技103子站 + \note + 取值范围:[非负整数]\n + */ + BYTE m_uchLinkAddr; + + /*! + \var BUBAN103LINKDEF::m_iMaskNoMatchString + \brief 屏蔽未配置事件点信息 + \note + 取值范围:[0---255]\n + */ + i_32 m_iMaskNoMatchString; + + // wen 2004.07.26 增加保护装置的状态处理 + /*! + \var BUBAN103LINKDEF::m_iInputStationOfDevStatus + \brief 保护装置状态输入厂站端口号 + \note + 取值范围:[ >= 0 ]\n + */ + i_32 m_iInputStationOfDevStatus; + + /*! + \var BUBAN103LINKDEF::m_iInputStartPntOfDevStatus + \brief 保护装置状态输入厂站起始点号 + \note + 取值范围:[ >= 0 ]\n + */ + i_32 m_iInputStartPntOfDevStatus; + + /*! + \var BUBAN103LINKDEF::m_iJudgeAsduNo + \brief 是否判断asdu号 + \note + 取值范围:[0---255]\n + */ + i_32 m_iJudgeAsduNo; + + /*! + \var BUBAN103LINKDEF::m_iDisTransDataProcess + \brief 是否处理扰动数据 + \note + 取值范围:[0---255]\n + */ + i_32 m_iDisTransDataProcess; + + /*! + \var BUBAN103LINKDEF::m_psDev + \brief 该链路支持的装置指针 + \note 该成员动态分配,数量=m_iDevNum + */ + DEVDEF *m_psDev; + + // 以下为转发时用参数 + /*! + \var BUBAN103LINKDEF::m_psProvDev + \brief 该链路支持的转发装置指针 + \note 该成员动态分配,数量=m_iDevNum + */ + PROVDEVDEF *m_psProvDev; + + /*! + \var BUBAN103LINKDEF::m_sBaoHuCmdParam + \brief 调度命令参数 + \note 用作数据的回馈时的处理 + */ + BAOHUPROVPARAM m_sBaoHuCmdParam; +} BUBAN103LINKDEF, *pBUBAN103LINKDEF; + +typedef struct tagBUBAN103PORTPARAM +{ + /*! + \var BUBAN103PORTDEF::m_iLinkNum + \brief 链路数量 + */ + i_32 m_iLinkNum; + + /*! + \var BUBAN103PORTDEF::m_achRecvBuf + \brief 接收数据缓冲区 + \note + 缓冲区最大不超过 300 bytes\n + */ + char m_achRecvBuf[300]; + + /*! + \var BUBAN103PORTDEF::m_iRecvLen + \brief 接收数据长度 + */ + int m_iRecvLen; + + /*! + \var BUBAN103PORTDEF::m_iLinkIdx + \brief 链路索引 + */ + int m_iLinkIdx; + + /*! + \var BUBAN103PORTDEF::m_iPortOk + \brief 端口ok + */ + int m_iPortOk; + + /*! + \var BUBAN103PORTDEF::m_bSendChangeDi + \brief 是否上送变化遥信 + */ + BOOL m_bSendChangeDi; + + /*! + \var BUBAN103PORTDEF::m_psLink + \brief 端口支持的链路指针 + \note 该成员动态分配,数量=m_iLinkNum + */ + BUBAN103LINKDEF *m_psLink; + + /*! + \brief 该规约的端口数据指针 + */ + SIO_PARAM_BAOHU_DEF *m_psBaoHu; +}BUBAN103PORTPARAM, *pBUBAN103PORTPARAM; + +typedef struct tagVALUEDEF +{ + union VALUE + { + /*! + \var VALUE::m_uValue + \brief 无符号长整型 + */ + u_32 m_uValue; + /*! + \var VALUE::m_iValue + \brief 整型 + */ + i_32 m_iValue; + /*! + \var VALUE::m_fValue + \brief 浮点数 + */ + double m_fValue; + /*! + \var VALUE::m_dwValue + \brief 双字 + */ + DWORD m_dwValue; + + }m_unValue; + + /*! + \var VALUEDEF::m_szValue + \brief 字符串 + */ + char m_szValue[MAXSTRINGLEN]; + /*! + \var VALUEDEF::m_iDataType + \brief 数据类型 + \note 取值范围如下\ + =0, 全无效\ + =1, 无符号整型\ + =2, 整型数\ + =3, 浮点数\ + =4, 字符串\ + =5, 数字量\ + =6, 控制字 + */ + i_32 m_iDataType; + /*! + \var VALUEDEF::m_iDataNum + \brief 数字量占用位数 + \note 仅对数字量和控制字和字符串有效 + */ + i_32 m_iDataNum; +}VALUEDEF, *pVALUEDEF; +/////////////////////////以下为通用函数接口/////////////////////////// +/*! + \brief 读取配置函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban103ReadConfig(int commid); // 初始化处理 +/*! + \brief 读取端口数据函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void Buban103RecvData(int commid, u_char *buf, int len);// 规约读数据处理 +/*! + \brief 规约数据处理定时器函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban103Timer(int commid); // 定时器处理 +/*! + \brief 遥控遥调数据处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void Buban103YkYtProcess(int commid, u_char *buf, int len); // 遥控遥调处理 +/*! + \brief 系统下发对时函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban103SendSystemTime(int commid); // 系统对时 +/*! + \brief 系统退出时规约处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban103Exit(int commid); // 规约退出 +/*! + \brief 保护命令处理函数 + \param commid -- 端口号 + \param rtumsg -- 下发的保护命令指针 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban103BaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData); +/*! + \brief 取保护数据库指针函数 + \param commid -- 端口号 + \param iProvAddr -- 统一编排的保护转发地址 + \param ppBaoHuDB -- 存放保护数据指针的指针 + \retval -- 返回该装置保护数据组数 + */ +int Buban103GetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB); +/////////////////////////通用函数接口结束/////////////////////////////// + +/////////////////////////以下为通用函数支持接口///////////////////////// +void Buban103ProvMakeYkYtCommand(int commid, u_char *buf, int len); +/////////////////////////通用函数支持接口结束/////////////////////////// + + +///////////////////////////以下为配置函数接口/////////////////////////// +BOOL InitBuban103InfoFromTempletFile(int commid,\ + char *ptrTemplate,\ + BUBAN103LINKDEF *psLink); +BOOL InitBuban103InfoFromTempletFileEx(int commid,\ + char *ptrTemplate,\ + BUBAN103LINKDEF *psLink,\ + BOOL bMaster); +BOOL GetParamItem(char *pSour, char **ppDest); +BOOL GetParamItemEx(char *pSour, char **ppDest, const char *pSplit); +BOOL GetLinkParamFromTemplateFile(int commid, HDSFILE hFile,\ + BUBAN103LINKDEF *psLink); +BOOL GetDevParamFromTemplateFile(int commid, HDSFILE hFile,\ + BUBAN103LINKDEF *psLink); +BOOL GetProvDevParamFromTemplateFile(int commid, HDSFILE hFile,\ + BUBAN103LINKDEF *psLink); +BOOL GetInfoData(char *pInfo, int iPntNo, DBORIENTATION *psDB); +BOOL GetSyncTimeInfoData(char *pInfo, DBINFO *psSyncInfo); +BOOL GetGroupInfoData(char *pInfo, int iPntNo, DEVPARAMDEF *psDevParam); + +void SetProtectDevStatus(BUBAN103LINKDEF *psLinkParam, int iDevNo, BOOL bStatus); + +void InitDevParam(DEVPARAMDEF *psDevParam); + +BOOL InitBuban103InfoFromDat(int commid, BUBAN103LINKDEF *psLink); +void InitGroupParam(GROUPDEF *psGroupParam, char *szDatFileName); +void InitBuban103CmdBuf(int commid, BUBAN103PORTPARAM *psPortParam); +void InitBuban103LinkCmdBuf(BUBAN103LINKDEF *psLinkParam); +void InitBuban103DevCmdBuf(BUBAN103LINKDEF *psLinkParam, int iDevNo); + +void ReCalcDevPntStart(int commid, BUBAN103PORTPARAM *psPortParam); +/////////////////////////////配置函数接口结束/////////////////////////// + + +/////////////////////以下为POLLING规约常规函数接口////////////////////// +void Buban103FindNextCmd(int commid); +BOOL Buban103FindNextCmdEx(int commid); +void Buban103CalcNextDev(int commid, BOOL bFlag); +void Buban103SendCmdFormPollCmdBuf(int commid); +//////////////////////POLLING规约常规函数接口结束/////////////////////// + +/////////////////////////buban103公共函数接口/////////////////////////// +BOOL IsDevLinkOk(BUBAN103LINKDEF *psLinkParam, int iDevNo); +void ClearLinkCnt(BUBAN103LINKDEF *psLinkParam, int iDevNo); +void SetDevLinkOk(BUBAN103LINKDEF *psLinkParam, int iDevNo, BOOL bFlagOk); +BYTE GetLinkAddr(BUBAN103LINKDEF *psLinkParam, int iDevNo); +BYTE *GetLinkCtrl(BUBAN103LINKDEF *psLinkParam, int iDevNo); +BOOL IsLinkTimeOut(BUBAN103LINKDEF *psLinkParam, int iDevNo); + +BYTE CalBuban103Lpc(BYTE *msg, u_32 len); +BOOL Buban103Check(char *pData, int iDataLen); +BOOL FindProtectDev(BUBAN103PORTPARAM *psPortParam, DEVADDRPARAM *psAddrParam, BOOL bJudgeLinkOnly); +BOOL FindProtectDevFromProvAddr(BUBAN103PORTPARAM *psPortParam, DEVADDRPARAM *psAddrParam, int iProvAddr); +BOOL FindProtectDevFromPntNo(BUBAN103PORTPARAM *psPortParam, DEVADDRPARAM *psAddrParam, DBINFO *psDBInfo, int iPntNo, int itype); + +BOOL FindProtectDevFromYkYtPnt(BUBAN103PORTPARAM *psPortParam, DEVADDRPARAM *psAddrParam, int iYkYtPnt); +int FindYkPointFromDev(DBORIENTATION *psYkYtDBUnit, BYTE u8Fun, BYTE u8Inf); +BOOL GetSpecialPtr(int commid, DEVADDRPARAM *psDevAddrParam,\ + BUBAN103PORTPARAM **ppsPortParam,\ + BUBAN103LINKDEF **ppsLinkParam, DEVDEF **ppsDevParam); +BOOL GetSpecialProvPtr(int commid, DEVADDRPARAM *psDevAddrParam,\ + BUBAN103PORTPARAM **ppsPortParam,\ + BUBAN103LINKDEF **ppsLinkParam, PROVDEVDEF **ppsProvDevParam); +BOOL GetPortParamPtr(int commid, BUBAN103PORTPARAM **ppsPortParam); +BOOL GetOneValueOfASDU10(BYTE *pu8SourData, VALUEDEF *psValue, BYTE u8DataType, BYTE u8DataLen); + +int FindAiGroupIdx(DBORIENTATION *pAiDB, int iMaxNum, BYTE u8Asdu, BYTE u8Fun, BYTE u8Inf); +/////////////////////////buban103公共函数接口结束/////////////////////// + +//===========================以下为指令生成函数======================= +//生成 Buban103 命令? +void MakeBuban103LinkCommand(u_32 commid, BYTE bLinkAddr, u_char link_cmd_idx, u_char* msg, u_32 len, u_32 cmdtype); +//生成时间同步命令 +void MakeTimeSyn_CAsdu6(u_32 commid, CMDPARAM *psCmdParam); +//生成总查询启动命令 +void MakeAllQuery_CAsdu7(u_32 commid, CMDPARAM *psCmdParam); +//生成通用分类数据命令 +void MakeGenIdentData_CAsdu10(u_32 commid, CMDPARAM *psCmdParam, u_char *dataset, u_char ngd); +void MakeGenIdentData_CAsdu10Ex(u_32 commid, CMDPARAM *psCmdParam, u_char *dataset, u_char ngd, u_32 cmdtype); +//生成一般命令 +void MakeGenCommand_CAsdu20(u_32 commid, CMDPARAM *psCmdParam, bool cmd); +//生成通用分类命令 +void MakeGenIdentCommand_CAsdu21(u_32 commid, CMDPARAM *psCmdParam, GEN_DATAGROUP* datagroup, u_char nog); +//生成扰动数据传输命令 +void MakeDisTrans_CAsdu24(u_32 commid, CMDPARAM *psCmdParam, u_char too, u_char tov, u_short fan, u_char acc); +//生成扰动数据传输的认可命令 +void MakeDisTrans_CAsdu25(u_32 commid, CMDPARAM *psCmdParam, u_char too, u_char tov, u_short fan, u_char acc); +//生成脉冲电度的查询命令 +void MakeQCC_CAsdu88(u_32 commid, CMDPARAM *psCmdParam); +//Buban103 生成一类数据问询指令 +void MakeBuban103_PL1_NA_3_Cmd(int commid, DEVADDRPARAM *psAddrParam); +/*! + \brief 生成标准的103定时轮询指令 + \param commid -- 厂站端口号 + \param iBuIdx -- 保护装置(间隔)索引 + \param CmdIdx -- 指令索引号 + \sa + \ref 0 时间同步过程 + \ref 1 模拟量查询 + \ref 2 状态量查询 + + \retval 指令生成成功标识 + \note + 无\n + */ +void MakeBuban103PollingCmd(int commid, BUBAN103LINKDEF *psLinkParam, i_32 CmdIdx); +//===========================指令生成函数结束========================= + +///////////////////////以下为规约处理函数接口/////////////////////////// +void Buban103ProcessData(int commid, BUBAN103PORTPARAM *psPortParam, BOOL bProcess); +void Buban103shortprocess(RTUMSG *rtumsg); +void Buban103longprocess(RTUMSG *rtumsg); + +// wen 2003.10.27 增加函数 +// 其他报文数据处理开始 +// 带时标的报文 +void Buban103TMprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标的报文 +void Buban103TMprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标的报文 +//void Buban103TMprocessOfPEvent(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带相对时间的时标报文 +void Buban103TMRprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带相对时间的时标报文 +void Buban103TMRprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带相对时间的时标报文 +//void Buban103TMRprocessOfPEvent(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值I报文 +void Buban103MEIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带相对时间的有时标的被测值报文 +void Buban103TMEprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 标识报文 +void Buban103IRCprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值II报文 +void Buban103MEIINAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值III报文 +void Buban103MEIIITAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值IV报文 +void Buban103MEIVTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值V报文 +void Buban103MEVTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值VI报文 +void Buban103MEVITAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 被测值VII报文 +void Buban103MEVIINAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 步位置信息报文 +void Buban103STNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 单点信息状态帧 +void Buban103SPNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标单点信息状态帧 +void Buban103SPTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标单点信息状态帧 +void Buban103SPTAprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标单点信息状态帧 +//void Buban103SPTAprocessOfPEvent(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 双点信息状态帧 +void Buban103DPNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标双点信息状态帧 +void Buban103DPTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标双点信息状态帧 +void Buban103DPTAprocessOfSoe(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标双点信息状态帧 +//void Buban103DPTAprocessOfPEvent(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 单点状态和状态变化信息状态帧 +void Buban103SSNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标单点状态和状态变化信息状态帧 +void Buban103SSTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 双点状态和状态变化信息状态帧 +void Buban103DSNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 带时标双点状态和状态变化信息状态帧 +void Buban103DSTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 水位 +void Buban103WLTAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 电能脉冲计数值 +void Buban103ITNAprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 通用分类数据报文 +void Buban103GDprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 遥控命令应答 +void Buban103YkAck(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 遥调命令应答 +void Buban103YtAck(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); + +/*! + \brief 通用分类数据报文模拟量处理 + \param rtumsg -- 数据源缓冲区 + \param psDevAddrParam -- 保护装置地址参数指针 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithAI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文开关量处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithDI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文电度量处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithPI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文保护模拟量处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithPAI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文保护开关量处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithPDI(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文保护定值处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithPFIX(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); +//void Buban103GDprocessWithPFIXNew(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); +//void Buban103GDprocessWithPFIXNewEx(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +/*! + \brief 通用分类数据报文保护事件处理 + \param rtumsg -- 数据源缓冲区 + \param iBuIdx -- 保护装置(间隔)索引 + \note + 取值范围:0 -- MAX_POLL_ADDRESS_NUM-1\n + \param iGroupIdx -- 通用分类数据组索引 + \note + 取值范围:0 -- GROUPNUM-1\n +*/ +void Buban103GDprocessWithPEVENT(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +// 通用分类标识报文 +void Buban103GIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); + +// 对时程序 +void Buban103SynTime(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); + +// 电度数据处理(SIEMENS 公司保护专用) +void Buban103EXPIprocess(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +// 其他报文数据处理结束 + +// 扰动数据处理开始 +// 扰动数据表处理 +void Buban103LRDprocess(RTUMSG *rtumsg); +// 扰动数据传输准备就绪 +void Buban103RTDprocess(RTUMSG *rtumsg); +// 带标志的状态变位传输准备就绪 +void Buban103RTTprocess(RTUMSG *rtumsg); +// 带标志的状态变位传输 +void Buban103TOTprocess(RTUMSG *rtumsg); +// 被记录的通道传输准备就绪 +void Buban103RTCprocess(RTUMSG *rtumsg); +// 传送扰动值 +void Buban103TOVprocess(RTUMSG *rtumsg); +// 带标志的状态变位、通道、扰动数据传输结束 +void Buban103EOTprocess(RTUMSG *rtumsg); +// 扰动数据处理结束 + +// 写通道扰动数据到文件中 +BOOL Buban103WriteACCDatatoFile(RTUMSG *rtumsg); +// 读录波数据文件头 +void Buban103GetFileHead(char *ptrDataHead, size_t *piNOF, size_t *piNOC, size_t *piNOE, size_t *piINT); +// 读录波数据记录时间 +//void Buban103GetTime(char *ptrDataHead, SYSTEMTIME *ptrtm); +// 读录波数据模拟量头 +void Buban103ProcessAiHead(char *ptrDataHead, DISTURBANCEAIDATA *pAiData); +// 转换临时文件为可用文件 +void Buban103tmpFileChangetodatFile(char *sztmpFileName); +// 生成CFG文件 +//void Buban103MakeCFGFile(int iStationNo, pDISTURBANCEDIDATA ptrDi, pDISTURBANCEAIDATA ptrAi, FILE *fp, char *szInfFile, SYSTEMTIME *tm); +// 生成DAT文件 +void Buban103MakeDATFile(pDISTURBANCEDIDATA ptrDi, pDISTURBANCEAIDATA ptrAi, FILE *fp); + +// 转发函数处理 +/*! + \brief 插入SOE数据 + \param commid -- 厂站端口号 + \param selidx -- 端口索引号 + \param iBuIdx -- 保护装置(间隔)索引 + \param pSoeMsg -- SOE数据指针 + \retval 插入SOE数据时是否覆盖(缓冲区是否已满) + \note + 无\n + */ +BOOL ProvInsertSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, SOE_DEF *pSoeMsg); + +/*! + \brief 从缓冲区取并且删除SOE数据 + \param commid -- 厂站端口号 + \param selidx -- 端口索引号 + \param iBuIdx -- 保护装置(间隔)索引 + \param pSoeMsg -- SOE数据指针 + \retval 获取SOE数据是否成功 + \note + 无\n +*/ +BOOL ProvGetAndDelSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, SOE_DEF *pSoeMsg); + +/*! + \brief 从缓冲区取第X项SOE数据 + \param commid -- 厂站端口号 + \param psDevAddrParam -- 端口索引号 + \param iNo -- 第i个soe记录 + \note + iNo=0为最新的事件记录,1为次之,以此类推 + \param pSoeMsg -- SOE数据指针 + \retval 获取SOE数据是否成功 + \note + 无\n +*/ +BOOL ProvGetNoXSoe(u_32 commid, DEVADDRPARAM *psDevAddrParam, int iNo, SOE_DEF *pSoeMsg); + +/*! + \brief 是否有一类数据存在 + \param commid -- 厂站端口号 + \param iBuIdx -- 保护装置(间隔)索引 + \param bCheckDiChange -- 检测遥信变位标识 + \retval 一类数据存在标识 + \note + 无\n +*/ +BOOL ProvHaveClassOne(u_32 commid, DEVADDRPARAM *psDevAddrParam, BOOL bCheckDiChange); + +/*! + \brief 转发初始化 + \param commid -- 厂站端口号 + \retval 无 + \note + 无\n +*/ +void ProvInit(u_32 commid); +/*! + \brief 转发链路指令的生成 + \param commid -- 厂站端口号 + \param addr -- 间隔设备地址 + \param cmdidx -- 指令索引号 + \param bACD -- 一类数据存在标识 + \retval 无 + \note + 无\n +*/ +void ProvMakeLinkCommand(u_32 commid, u_char addr, u_char cmdidx, BOOL bACD); +/*! + \brief 转发链路指令的生成 + \param commid -- 厂站端口号 + \param addr -- 间隔设备地址 + \param cmdidx -- 指令索引号 + \param bACD -- 一类数据存在标识 + \param bClearRecvBuf -- 是否清除接收缓冲区 + \param cmdtype-- 指令缓冲区类型 + \retval 无 + \note + 无\n +*/ +void ProvMakeLinkCommandEx(u_32 commid, u_char addr, u_char cmdidx, BOOL bACD, BOOL bClearRecvBuf, u_32 cmdtype); +/*! + \brief 转发数据指令的生成 + \param commid -- 厂站端口号 + \param addr -- 间隔设备地址 + \param cmdidx -- 指令索引号 + \param bACD -- 一类数据存在标识 + \param bCause -- 传送原因 + \param cmdtype-- 指令缓冲区类型 + \retval 无 + \note + 无\n +*/ +void ProvMakeVarCommand(u_32 commid, u_char linkaddr, u_char addr, u_char cmdidx, BOOL bACD, BYTE bCause, u_32 cmdtype); +/*! + \brief 转发命令处理 + \param portidx -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \retval 无 + \note + 无\n +*/ +void ProvRtuProtocolDataProcess(int commid, RTUMSG *rtumsg); +/*! + \brief 保护命令数据处理函数 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvSendCmdToPort(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 短帧数据转发处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \retval 无 + \note + 无\n +*/ +void Provshortprocess(u_32 commid, RTUMSG *rtumsg); +/*! + \brief 转发一类数据处理 + \param commid -- 厂站端口号 + \param addr -- 间隔设备地址 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvPL1process(u_32 commid, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发二类数据处理 + \param commid -- 厂站端口号 + \param addr -- 间隔设备地址 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvPL2process(u_32 commid, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 长帧数据转发处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \retval 无 + \note + 无\n +*/ +void Provlongprocess(u_32 commid, RTUMSG *rtumsg); +/*! + \brief 转发时间同步处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \retval 无 + \note + 无\n +*/ +void ProvSYNprocess(u_32 commid, RTUMSG *rtumsg); +/*! + \brief 转发总查询(总召唤)处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvTGIprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发通用分类数据处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvGDprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发一般命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvGRCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发通用分类命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvGCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发扰动数据传输的命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvODTprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发扰动数据传输的认可处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvADTprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发控制断路器命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvDCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发升降命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvRCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发设定命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvSEprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发控制命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvCCprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发电能脉冲计数召唤命令处理 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +void ProvCIprocess(u_32 commid, RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam); +/*! + \brief 转发全部组标题 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +BOOL ProvMakeTitleOfGroups(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum); +/*! + \brief 转发一个组的全部条目的值或属性 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \param bContinue- 未传送的保护数据继续 + \retval 无 + \note + 无\n +*/ +BOOL ProvMakeAttrOfAllItemInGroup(u_32 commid, RTUMSG *rtumsg,\ + PROVDEVDEF *pProvDevParam,\ + GROUPDEF *pBaoHuDB, int iNum); +/*! + \brief 转发一个条目的目录 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +BOOL ProvMakeDirOfItem(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum); +/*! + \brief 转发一个条目的值或属性 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +BOOL ProvMakeAttrOfItem(u_32 commid, RTUMSG *rtumsg, PROVDEVDEF *pProvDevParam, GROUPDEF *pBaoHuDB, int iNum); + +/*! + \brief 转发遥信变位 + \param commid -- 厂站端口号 + \param rtumsg -- 接收到的数据信息 + \param iBuIdx -- 保护装置(间隔)索引 + \retval 无 + \note + 无\n +*/ +BOOL ProvSendChangedDi(u_32 commid, DEVADDRPARAM *psDevAddrParam); + +/*! + \brief 单个定值的打包 + \param pbDestBuf -- 目的缓冲区指针 + \param uMaxBufLen -- 目的缓冲区最大长度 + \param bDataFormat -- 数据格式 + \param uDataType -- 数据类型 + \param uDataLen -- 源数据长度 + \param pbSourData -- 源数据缓冲区指针 + \retval 无 + \note + 无\n +*/ +i_32 PackOneValueIntoPackage(BYTE *pbDestBuf, u_32 uMaxBufLen, BYTE bDataFormat, + u_32 uDataType, u_32 uDataLen, BYTE *pbSourData); + +// 部颁103和斯凯达内部规约间的格式转换 +void Buban103ScadaCmdchange(int commid, RTUMSG *rtumsg); +void Buban103ScadaDatachange(int commid, RTUMSG *rtumsg); +void Buban103ScadaProtocolExchange(int commid, RTUMSG *rtumsg); + +void Buban103GDprocessWithPAIToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); +void Buban103GDprocessWithPDIToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); +void Buban103GDprocessWithPFIXToScada(RTUMSG *rtumsg, DEVADDRPARAM *psDevAddrParam, i_32 iGroupIdx); + +// 调试信息显示 +void Buban103DispConfig(int commid, BUBAN103PORTPARAM *psPortParam); +void Buban103DispMalloc(int commid, int iSize); +/////////////////////////规约处理函数接口结束/////////////////////////// + +#endif // !defined(_BUBAN103_H_200504221547__INCLUDED_) diff --git a/buban104.cpp b/buban104.cpp new file mode 100644 index 0000000..cf067b7 --- /dev/null +++ b/buban104.cpp @@ -0,0 +1,4881 @@ +//*************************************************************** +//* buban104.cpp * +//* aaawen 2005.09.14 * +//*************************************************************** +//_DEBUG_MSG_,_OS_WINDOWS_DEBUG_ +#ifdef OS_LINUX +#include "baohulib/commport.h" +#include "baohulib/serialport.h" +#else +#include "commport.h" +#include "udpcomm.h" +#include "display.h" +#endif +#include +#include +#include "buban101.h" +#include "buban104.h" +#include "scadaprotect.h" + +extern SIO_PARAM_DEF SioParam[]; +extern FUNCTION_CALL *FunCallPtr; +extern void *pvconf_handle; +extern void *pvportconf_handle; +extern void *pvdataconf_handle; +extern char pvDataFileName[256]; +extern char IniFilePath[256]; + +const char *gpStrBuban104Cmd[BUBAN104_TIMER_CMD_NUM] = +{ + "总召唤电度数据", + "召唤初始化数据", + "帧序应答" +}; + +/*! + 组织结构:链路(间隔)+装置 +*/ +const char *gpStrBuban104ConfigInfo[] = +{ + " ; ***** 部颁104规约参数定义 *****", + " ", + " ; 所有命令召唤周期均以秒为单位,可以为xx.xxx秒。", + " ; 注意:104规约只支持网络通讯,作为主站时是客户方式,作为子站时是服务器方式。", + " ; 网络端口 = 2404。", + " 站地址 = 1 ; 缺省= 0 。", + " 总召唤电度数据 = 120", + " 召唤初始化数据 = 300", + " 帧序应答 = 20", + " ; 在对方超时时间之内发送帧序应答帧。", + " 超时时间 = 3.0", + //" 转发返校超时时间 = 10.0", + " 转发是否要求应答 = 0", + " 超时发送测试帧 = 0", + " ; =0:超时不发送测试报文而是帧序应答报文(缺省值),=1:发送测试报文", + " 遥控方式=0", + " ; =0:双点遥控(缺省),=1:单点遥控。", + " ", + " 遥测信息体起始地址=0x701", + " 遥信信息体起始地址=0x001", + " 遥脉信息体起始地址=0xC01", + " 遥控信息体起始地址=0xB01", + " ;以上信息体地址可以配置,缺省值为97版部颁104所规定值", + " ", + " 帧序应答尺寸=2", + " ", + " 版本号 = 1", + " ;=0 是buban104(缺省值); =1 是IEC_870_5_104规约", + " 发布时间=2000", + " ;=1997; =2000(缺省值)", + " 转发遥测类型标识 = 21", + " ", + "*******部颁104规约结束*******", + "", // 结束标志(中间不能含有该空字符串) +}; + +//******************************************************************** +//* 读取配置函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban104ReadConfig(int commid) +{ + int i; + char szSection[128], szbuf[128]; + char szPortConfig[256]; + pBUBAN104PORTPARAM pPortParam; + +#ifdef OS_LINUX + strcpy(szPortConfig, "portconfig.ini"); +#else + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); +#endif + + SioParam[commid].ExtInfo = HEAP_MALLOC(sizeof(BUBAN104PORTPARAM)); + + if(!SioParam[commid].ExtInfo) + { + sprintf(szbuf, "WARN(%04d): commid_%02d ExtInfo=malloc(%d) failed.\n", + _getpid(), commid, sizeof(BUBAN104PORTPARAM)); + DebugPrint(szbuf); + return; + } + + memset(SioParam[commid].ExtInfo, 0, sizeof(BUBAN104PORTPARAM)); + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + /* 只有在SioParam[commid].m_psBaoHu非空时,才会运行到这里 */ + pPortParam->m_psBaoHu = SioParam[commid].m_psBaoHu; + + sprintf(szSection, "Port%d", commid+1); + + if(GetPrivateProString(szSection, "站地址", "0", szbuf, 120, szPortConfig) > 0) + { + pPortParam->wLinkAddr = atoi(szbuf); + } + // 轮询指令配置 + for(i=0; iCmdTime[i].CmdTimerConst = (long)(atof(szbuf)*1000/TIMER_CNT); + if(pPortParam->CmdTime[i].CmdTimerConst > 5) + { + pPortParam->CmdTime[i].CmdTimerCnt = pPortParam->CmdTime[i].CmdTimerConst - 5; + } + } + + if(GetPrivateProString(szSection, "超时时间", "20.0", szbuf, 120, szPortConfig) > 0) + { + pPortParam->lTimeOutConst = (long)(atof(szbuf)*1000/TIMER_CNT); + } + + pPortParam->ProvAckOrNot = GetPrivateProInt(szSection, "转发是否要求应答", 0, szPortConfig); + if(pPortParam->ProvAckOrNot > 0) + { + pPortParam->ProvAckOrNot = 1; + } + else + { + pPortParam->ProvAckOrNot = 0; + } + + // wen 2005.10.28 修改超时时是否发送测试报文 + pPortParam->lTimeOutSendTest = GetPrivateProInt(szSection, "超时发送测试帧", 0, szPortConfig); + + if(GetPrivateProString(szSection, "遥控方式", "0", szbuf, 120, szPortConfig) > 0) + { + pPortParam->YkMode = atoi(szbuf); + } + + pPortParam->iAiBaseAddr = GetPrivateProInt(szSection, "遥测信息体起始地址", INFO_AI_BASEADDR, szPortConfig); + pPortParam->iDiBaseAddr = GetPrivateProInt(szSection, "遥信信息体起始地址", INFO_DI_BASEADDR, szPortConfig); + pPortParam->iPiBaseAddr = GetPrivateProInt(szSection, "遥脉信息体起始地址", INFO_PI_BASEADDR, szPortConfig); + pPortParam->iYkBaseAddr = GetPrivateProInt(szSection, "遥控信息体起始地址", INFO_YKYT_BASEADDR, szPortConfig); + + pPortParam->m_iFrameSize = GetPrivateProInt(szSection, "帧序应答尺寸", MAX_FRAMEMATCHING_SIZE, szPortConfig); + + pPortParam->RtuVersion = GetPrivateProInt(szSection, "版本号", 0, szPortConfig); + pPortParam->m_iPublishYear = GetPrivateProInt(szSection, "发布时间", 2000, szPortConfig); + + pPortParam->m_bProvAiType = GetPrivateProInt(szSection, "转发遥测类型标识", 13, szPortConfig); + + InitBuban104CommandBuffer(commid); +} +// +// +//******************************************************************** +//* 读取端口数据函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void Buban104RecvData(int commid, u_char *buf, int len)// 规约读数据处理 +{ + int i; + pBUBAN104PORTPARAM pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + if(!IsExtInfoPtr(commid)) + return; + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + for(i=0; im_psBaoHu->m_iRevStatus) + { + case 0:// 0x10 / 0x68 + pPortParam->m_iRecvLen = 0; + if(buf[i] == 0x68) + { + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + } + else + { + pPortParam->m_psBaoHu->m_iRevStatus = 100; + pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + } + break; + case 1:// length + pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + pPortParam->m_psBaoHu->m_iNeedRevLength = buf[i]; + if(pPortParam->m_psBaoHu->m_iNeedRevLength <= 0) + { + pPortParam->m_psBaoHu->m_iRevStatus = 100; + } + else + { + pPortParam->m_psBaoHu->m_iRevStatus++; + } + break; + case 2:// 正确接收数据 + pPortParam->m_psBaoHu->m_iNeedRevLength--; + pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(pPortParam->m_psBaoHu->m_iNeedRevLength > 0) + break; + + Buban104ProcessData(commid, pPortParam, TRUE); + pPortParam->m_psBaoHu->m_iRevStatus = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 1; +#ifndef OS_LINUX + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen); + } +#endif + //pPortParam->LinkOkCnt = 0; + break; + case 100:// 错误接收数据 + default: + if(buf[i] == 0x68) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen); + } +#endif + Buban104ProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + pPortParam->m_psBaoHu->m_iRevStatus = 1; + pPortParam->m_iRecvLen = 1; + pPortParam->m_au8RecvBuf[0] = buf[i]; + } + else + { + pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(pPortParam->m_iRecvLen > 200) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_au8RecvBuf, pPortParam->m_iRecvLen); + } +#endif + Buban104ProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + pPortParam->m_iRecvLen = 0; + } + } + break; + } + } + +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "wen: commid = %d, send=%d, recv=%d, error=%d, lost=%d\n", commid, + SioParam[commid].SendCharNum, SioParam[commid].RecvCharNum, + SioParam[commid].ErrMsgNum, SioParam[commid].LostSyncCnt); + DebugPrint(szbuf); +#endif +} + +//******************************************************************** +//* 定时器处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban104Timer(int commid) +{ + BUBAN104PORTPARAM *pPortParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + if(pPortParam->LinkOk) + { + // 超时计数 + pPortParam->lTimeOutCnt++; + } + // 如果为转发端口,则不进行轮询指令的生成。 + if(PROTOCOL_SLAVE != pPortParam->m_psBaoHu->PortType) + { + Buban104FindNextCmd(commid); + } + else + { + Buban104FindNextProvCmd(commid); + } + + Buban104SendCmdFormPollCmdBuf(commid); +} + +//******************************************************************** +//* 遥控遥调数据处理函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void Buban104YkYtProcess(int commid, u_char *buf, int len) // 遥控遥调处理 +{ + int portno, ykytpnt; + int iDirect; + + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + iDirect = buf[9] & 0x80; + portno = buf[0]+buf[1]*256+buf[2]*65536+buf[3]*16777216; + ykytpnt = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; + + // 返校信息(反馈信号) + if(iDirect) + { + Buban104ProvMakeYkYtCommand(commid, buf, len); + } + else + { + MakeBuBan104YkYtCommand(commid, buf, len); + } +} + +//******************************************************************** +//* 系统下发对时函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban104SendSystemTime(int commid) // 系统对时 +{ + BUBAN104PORTPARAM *pPortParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(2 != pPortParam->m_psBaoHu->CheckTime) + { + return; + } + + if(pPortParam->Initdata) + { + if(PROTOCOL_SLAVE != pPortParam->m_psBaoHu->PortType) + { + MakeBuban104Command(commid, RTU_TIME); + } + } +} + +//******************************************************************** +//* 系统退出时规约处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void Buban104Exit(int commid) +{ + // 释放所有分配的内存 +} + +// 该函数用来驱动由转发端口下发到实际装置的保护命令 +void Buban104BaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData) +{ +} + +int Buban104GetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB) +{ + return 0; +} +/////////////////////////通用函数接口结束/////////////////////////////// + +/////////////////////////buban104公共函数接口/////////////////////////// +//指令缓冲区初始化 +void InitBuban104CommandBuffer(int commid) +{ + pBUBAN104PORTPARAM pPortParam; + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + pPortParam->LinkOk = false; + + // wen 2005.09.15 将该标识修改为true后, + // 在主站下发总召命令和总召电度后,会将其标识置为false; + // 而子站端不会受此标识的影响,标识为false,不下发数据。 + //pPortParam->Initdata = false; + pPortParam->Initdata = true; + + pPortParam->bAckRight = true; + pPortParam->bStopComm = false; + pPortParam->bCloseSocket = false; + pPortParam->CurCmdIdx = 0; + pPortParam->wRecvSequence = 0; + pPortParam->wSendSequence = 0; + pPortParam->wAckSequence = 0; + pPortParam->lTimeOutCnt = 0; + ClearAllCmdFromPollCmdBuf(commid); +} + +//关闭socket通讯 +void Buban104CloseSocket(u_32 commid) +{ +#ifdef OS_LINUX + CloseNetPort(commid); +#endif +} +/////////////////////////buban104公共函数接口结束/////////////////////// + +void Buban104ProvMakeYkYtCommand(int commid, u_char *buf, int len) +{ + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + int ykpoint, iLen; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + BOOL bHaveOrder = FALSE; + BUBAN104PORTPARAM *pPortParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + if((buf[9] & 0x80) == 0) + { + return; + } + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + memset( (char*)commandbuf, 0x00, MAX_POLLCMD_BUF_LEN ); + + ykpoint = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; + ykpoint += pPortParam->iYkBaseAddr - 1; + + commandbuf[0] = 0x68; + commandbuf[1] = 14; + switch(pPortParam->YkMode) + { + case CONTROL_SINGAL: // 单点控制 + commandbuf[6] = 45; + break; + case CONTROL_DOUBLE: // 双点控制 + case CONTROL_DIRECT: // 直接控制 + commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47; + break; + } + commandbuf[7] = 1; + //commandbuf[8] 传送原因 + iLen = 9; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = LOBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = HIBYTE(LOWORD(ykpoint)); + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = LOBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = HIBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = LOBYTE(HIWORD(ykpoint)); + } + + switch(buf[8]) + { + case 1: + case 4: // 选择 + bHaveOrder = TRUE; + commandbuf[8] = 7; + commandbuf[iLen] = 0xfc; + break; + + case 2: + case 5: // 执行 + bHaveOrder = TRUE; + commandbuf[8] = 7; + commandbuf[iLen] = 0x7c; + break; + + case 3: + case 6: + bHaveOrder = TRUE; + commandbuf[8] = 9; + commandbuf[iLen] = 0xfc; + break; + } + + if( bHaveOrder ) + { + if((buf[9] & 0x03) == 0x03) + { + commandbuf[8] |= 0x40; + } + else + { + // 控分还是控合 + if((buf[9] & 0x03) == 0x01)// 控合 + { + if(CONTROL_SINGAL == pPortParam->YkMode) + { + commandbuf[iLen++] |= 1; + } + else + { + commandbuf[iLen++] |= 2; + } + } + else// 控分 + { + if(CONTROL_SINGAL != pPortParam->YkMode) + { + commandbuf[iLen++] |= 1; + } + } + } + + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, iLen); + } + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n", + _getpid(), commid, ykpoint, (buf[9] & 0x7F)); + } +} + +//===========================以下为指令生成函数======================= +/*! + \brief 寻找并生成下一条命令 + \param u_32 portno : RTU端口号 + \param i_32 iBuIdx : 间隔装置索引 +*/ +void MakeBuban104Command(u_32 commid, u_char cmdidx) +{ + int i, iLen; + DAY_TIME sCurTime; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + BUBAN104PORTPARAM *pPortParam; + + memset( commandbuf, 0, sizeof( commandbuf ) ); + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + iLen = 0; + switch ( cmdidx ) + { + // format-i + case RTU_TIME: // 时间同步 + GetLocalTimeEx(&sCurTime); + commandbuf[0] = 0x68; + iLen = 6; + commandbuf[iLen++] = 103; + commandbuf[iLen++] = 1; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + sCurTime.mSec = sCurTime.Sec * 1000 + sCurTime.mSec; + commandbuf[iLen++] = sCurTime.mSec % 256; + commandbuf[iLen++] = sCurTime.mSec / 256; + commandbuf[iLen++] = (u_char)sCurTime.Min; + commandbuf[iLen++] = (u_char)sCurTime.Hour; + commandbuf[iLen++] = (u_char)sCurTime.Day; + commandbuf[iLen++] = (u_char)sCurTime.Month; + commandbuf[iLen++] = (u_char)(sCurTime.Year%100); + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, iLen); + break; + + case ASK_DI_DATA: // 召唤2级数据YX + for ( i = 0; i < (pPortParam->m_psBaoHu->DiNum+MAX_GROUP_DINUM-1)/MAX_GROUP_DINUM; i++) + { + commandbuf[0] = 0x68; + //commandbuf[1] = 14; + iLen = 6; + commandbuf[iLen++] = 100; + commandbuf[iLen++] = 0; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 5; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + + } + else + { + commandbuf[iLen++] = 5; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 21 + i; + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, iLen); + } + break; + + case ASK_AI_DATA: // 召唤2级数据YC + for ( i = 0; i < (pPortParam->m_psBaoHu->AiNum+MAX_GROUP_AINUM-1)/MAX_GROUP_AINUM; i++) + { + commandbuf[0] = 0x68; + //commandbuf[1] = 14; + iLen = 6; + commandbuf[iLen++] = 100; + commandbuf[iLen++] = 0; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 5; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 5; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 29 + i; + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, iLen); + } + break; + + case ASK_PI_DATA: // 召唤2级数据YM + for ( i = 0; i < (pPortParam->m_psBaoHu->PiNum+MAX_GROUP_PINUM-1)/MAX_GROUP_PINUM; i++) + { + commandbuf[0] = 0x68; + //commandbuf[1] = 14; + iLen = 6; + commandbuf[iLen++] = 101; + commandbuf[iLen++] = 0; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 2 + i; + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, iLen); + } + break; + + case ASK_PI: //召唤电度量 + commandbuf[0] = 0x68; + //commandbuf[1] = 14; + iLen = 6; + commandbuf[iLen++] = 101; + commandbuf[iLen++] = 1; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + + } + else + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + // wen 2006.04.03 发布时间97版和2000版组分配不同 + if(pPortParam->m_iPublishYear == 1997) + { + commandbuf[iLen++] = 0x41; + } + else + { + commandbuf[iLen++] = 0x45; + } + + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, iLen); + pPortParam->Initdata = false; + break; + + case ASK_ALL_DATA:// 召唤初始化数据 + commandbuf[0] = 0x68; + //commandbuf[1] = 14; + iLen = 6; + commandbuf[iLen++] = 100; + commandbuf[iLen++] = 1; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 6; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 20; + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, commandbuf, iLen); + pPortParam->Initdata = false; + break; + + // format-s + case FORMAT_S: // S-格式 + // wen 2005.09.21 如果缓冲区内有数据,则不生成S帧 + if(CheckPollCmdBufEmpty(commid) <= 0) + { + break; + } + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x01; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, commandbuf, iLen); + break; + + // format-u + case FORMAT_U_START_ACT: // U-格式启动 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x07; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, iLen); + break; + + case FORMAT_U_START_CON: // U-格式启动应答 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x0b; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, commandbuf, iLen); + break; + + case FORMAT_U_STOP_ACT: // U-格式停止 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x13; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, iLen); + break; + + case FORMAT_U_STOP_CON: // U-格式停止应答 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x23; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, commandbuf, iLen); + break; + + case FORMAT_U_TEST_ACT: // U-格式测试 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = 0x43; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, commandbuf, iLen); + break; + + case FORMAT_U_TEST_CON: // U-格式测试应答 + commandbuf[iLen++] = 0x68; + commandbuf[iLen++] = 4; + commandbuf[iLen++] = (char)0x83; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + commandbuf[iLen++] = 0x00; + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, commandbuf, iLen); + break; + + default: + break; + } +} + +//生成遥控遥调指令 +void MakeBuBan104YkYtCommand( u_32 commid, u_char *buf, int len ) +{ + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=成功, 0=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + int ykpoint, iLen; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + static int iYkStatus = 0; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (pBUBAN104PORTPARAM)SioParam[commid].ExtInfo; + + memset( (char*)commandbuf, 0x00, MAX_POLLCMD_BUF_LEN ); + + ykpoint = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; + ykpoint += pPortParam->iYkBaseAddr - 1; + + iLen = 9; + switch(buf[8]) + { + case 1: + case 4: // 选择 + commandbuf[0] = 0x68; + commandbuf[1] = 14; + switch(pPortParam->YkMode) + { + case CONTROL_SINGAL: // 单点控制 + commandbuf[6] = 45; + break; + case CONTROL_DOUBLE: // 双点控制 + case CONTROL_DIRECT: // 直接控制 + commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47; + break; + } + commandbuf[7] = 1; + commandbuf[8] = 6; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + + // wen 2002.11.18 字节顺序修改 + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + commandbuf[iLen++] = 0; + } + + if(buf[9] == 1) + { + if(CONTROL_SINGAL == pPortParam->YkMode) + { + iYkStatus = 1; + } + else + { + iYkStatus = 2; + } + } + else + { + if(CONTROL_SINGAL == pPortParam->YkMode) + { + iYkStatus = 0; + } + else + { + iYkStatus = 1; + } + } + commandbuf[iLen++] = (BYTE)(0xfc + iYkStatus); + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, iLen); + break; + + case 2: + case 5: // 执行 + commandbuf[0] = 0x68; + commandbuf[1] = 14; + switch(pPortParam->YkMode) + { + case CONTROL_SINGAL: // 单点控制 + commandbuf[6] = 45; + break; + case CONTROL_DOUBLE: // 双点控制 + case CONTROL_DIRECT: // 直接控制 + commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47; + break; + } + commandbuf[7] = 1; + commandbuf[8] = 6; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + // wen 2002.11.18 字节顺序修改 + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + + // wen 2002.11.18 字节顺序修改 + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + commandbuf[iLen++] = 0; + } + + commandbuf[iLen++] = 0x7c + iYkStatus; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, iLen); + break; + + case 3: + case 6: + commandbuf[0] = 0x68; + commandbuf[1] = 14; + switch(pPortParam->YkMode) + { + case CONTROL_SINGAL: // 单点控制 + commandbuf[6] = 45; + break; + case CONTROL_DOUBLE: // 双点控制 + case CONTROL_DIRECT: // 直接控制 + commandbuf[6] = 46;//(rtumsg->MsgData[3] == 1) ? 46 : 47; + break; + } + commandbuf[7] = 1; + commandbuf[8] = 8; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + + // wen 2002.11.18 字节顺序修改 + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + + // wen 2002.11.18 字节顺序修改 + commandbuf[iLen++] = (char)(ykpoint & 0x00ff); + commandbuf[iLen++] = (char)((ykpoint & 0xff00)>>8); + commandbuf[iLen++] = 0; + } + + commandbuf[iLen++] = 0xfc + iYkStatus; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, iLen); + break; + } + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n", + _getpid(), commid, ykpoint, (buf[9] & 0x7F)); + } +} + +//===================以下为POLLING规约常规函数接口====================== +/*! + \brief 寻找并生成下一条命令 + \param u_32 portno : RTU端口号 + \param i_32 iBuIdx : 间隔装置索引 +*/ +void Buban104FindNextCmd(int commid) +{ + int i, iCurCmdIdx; + BUBAN104PORTPARAM *pPortParam; + int framename[BUBAN104_TIMER_CMD_NUM] = + { + ASK_PI, + ASK_ALL_DATA, + FORMAT_S + }; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(!pPortParam->LinkOk) + { + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + MakeBuban104Command(commid, FORMAT_U_START_ACT); + return; + } + + for(i=0; iCmdTime[i].CmdTimerConst ) + pPortParam->CmdTime[i].CmdTimerCnt++; + } + + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + iCurCmdIdx = pPortParam->CurCmdIdx; + for ( i = 0; i < BUBAN104_TIMER_CMD_NUM; i++ ) + { + if(!pPortParam->bAckRight) + { + break; + } + + // wen 2005.09.16 在初始化不成功时,不生成轮询指令 + if(!pPortParam->Initdata) + { + break; + } + + iCurCmdIdx = (iCurCmdIdx+1) % BUBAN104_TIMER_CMD_NUM; + if ( (pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt + >= pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst) + && ( pPortParam->CmdTime[iCurCmdIdx].CmdTimerConst > 0 )) + { + pPortParam->CurCmdIdx = iCurCmdIdx; + MakeBuban104Command(commid, framename[iCurCmdIdx]); + pPortParam->CmdTime[iCurCmdIdx].CmdTimerCnt = 0; + return; + } + } + + // wen (超时情况下) + if(CheckPollCmdBufEmpty(commid) > 0) + { + if(pPortParam->lTimeOutCnt >= pPortParam->lTimeOutConst) + { + if(!pPortParam->bCloseSocket) + { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.10.28 修改超时时是否发送测试报文 + //MakeBuban104Command(commid, FORMAT_S); + //====================================================== + if(pPortParam->lTimeOutSendTest) + { + MakeBuban104Command(commid, FORMAT_U_TEST_ACT); + } + else + { + MakeBuban104Command(commid, FORMAT_S); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = TRUE; + } + else + { + InitBuban104CommandBuffer(commid); + // 关闭网络端口 + Buban104CloseSocket(commid); + } + } + } +} + +void Buban104FindNextProvCmd(int commid) +{ + BUBAN104PORTPARAM *pPortParam; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(!pPortParam->LinkOk) + { + return; + } + + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + // wen (超时情况下) + if(pPortParam->lTimeOutCnt >= pPortParam->lTimeOutConst) + { + if(!pPortParam->bCloseSocket) + { + if(pPortParam->bAckRight) + { + if(pPortParam->Initdata) + { + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 修改超时时是否发送测试报文 + //MakeBuban104Command(commid, FORMAT_U_TEST_ACT); + //====================================================== + if(pPortParam->lTimeOutSendTest) + { + MakeBuban104Command(commid, FORMAT_U_TEST_ACT); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = TRUE; + } + } + else + { + InitBuban104CommandBuffer(commid); + // 关闭网络端口 + Buban104CloseSocket(commid); + } + } + else + { + InitBuban104CommandBuffer(commid); + // 关闭网络端口 + Buban104CloseSocket(commid); + } + } + + if(CheckPollCmdBufEmpty(commid) <= 0) + { + return; + } + + if(pPortParam->bAckRight) + { + if(pPortParam->Initdata) + { + // 一类数据( 遥信变位 ) + ProvBuban104SendClass1(commid); + if(CheckPollCmdBufEmpty(commid) <= 0) + { + pPortParam->m_lNoDataCnt = 0; + return; + } + + // 转发soe数据 + ProvBuban104SendSoe(commid); + if(CheckPollCmdBufEmpty(commid) <= 0) + { + pPortParam->m_lNoDataCnt = 0; + return; + } + + // 二类数据( 遥测变化) + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 支持浮点数遥测的传送 + //ProvBuban104SendClass2(commid); + //==================================================================== + if(pPortParam->m_bProvAiType == 13) + { + ProvBuban104SendClass2withFloat(commid); + } + else + { + ProvBuban104SendClass2(commid); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(CheckPollCmdBufEmpty(commid) <= 0) + { + pPortParam->m_lNoDataCnt = 0; + return; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 修改超时时是否发送测试报文 + //pPortParam->m_lNoDataCnt++; + //if(pPortParam->m_lNoDataCnt >= pPortParam->lTimeOutConst) + //{ + // pPortParam->m_lNoDataCnt = 0; + // MakeBuban104Command(commid, FORMAT_U_TEST_ACT); + //} + //====================================================== + if(pPortParam->lTimeOutSendTest) + { + pPortParam->m_lNoDataCnt++; + if(pPortParam->m_lNoDataCnt >= pPortParam->lTimeOutConst) + { + pPortParam->m_lNoDataCnt = 0; + MakeBuban104Command(commid, FORMAT_U_TEST_ACT); + } + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + } +} + +void Buban104SendCmdFormPollCmdBuf(int commid) +{ + BYTE fcb = 0x20; + BYTE buf[MAX_MSG_BUF_SIZE]; + i_32 len; + BUBAN104PORTPARAM *pPortParam; + + if((commid < 0) || (commid >= GetMaxPort())) + { + return; + } + + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->m_psBaoHu->ForceWaitFlag + && pPortParam->m_psBaoHu->ForceWaitCnt) + { + pPortParam->m_psBaoHu->ForceWaitCnt--; + if(pPortParam->m_psBaoHu->ForceWaitCnt == 0) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + } + } + + if(pPortParam->m_psBaoHu->SendCmdFlag + && (pPortParam->m_psBaoHu->RevCmdFlag == 0)) + { + pPortParam->m_psBaoHu->RetryTimeCnt++; + if(pPortParam->m_psBaoHu->RetryTimeCnt < pPortParam->m_psBaoHu->RetryTime) + { + return; + } + + pPortParam->m_psBaoHu->RetryTimeCnt = 0; + + pPortParam->m_psBaoHu->RetryCnt++; + if(pPortParam->m_psBaoHu->RetryCnt > pPortParam->m_psBaoHu->Retry) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + } + else + { + pPortParam->m_psBaoHu->SendCmdFlag = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 0; + pPortParam->m_psBaoHu->ReSendCmdFlag = 1; + } + } + + if(pPortParam->m_psBaoHu->SendCmdFlag + && pPortParam->m_psBaoHu->RevCmdFlag) + { + // 清除当前命令 + ClearCmdFormPollCmdBuf(commid); + //ClearCmdAllFlag(commid); + if(pPortParam->bSendFormatI) + { + //pPortParam->wSendSequence++; + //pPortParam->wSendSequence %= MAX_SEQUENCE; + pPortParam->bSendFormatI = FALSE; + } + } + + if(pPortParam->m_psBaoHu->WaitTime) + { + pPortParam->m_psBaoHu->WaitTimeCnt++; + if(pPortParam->m_psBaoHu->WaitTimeCnt + < pPortParam->m_psBaoHu->WaitTime) + { + return; + } + } + pPortParam->m_psBaoHu->WaitTimeCnt = 0; + + if(pPortParam->m_psBaoHu->ReSendCmdFlag) + { + len = ReGetCmdFormPollCmdBuf(commid, buf, sizeof(buf)); + } + else + { + len = GetCmdFormPollCmdBuf(commid, buf, sizeof(buf)); + // 清除标识已经在前面 ClearCmdAllFlag(commid)动作中完成 + //pPortParam->m_psBaoHu->RetryCnt = 0; + } + + if(len < 3) + { + return; + } + +#ifndef OS_LINUX + if(isUdpSocketExist() == TRUE) +#endif + { + if(buf[4] & 0x01 ) + { + // format_s + if((buf[4] & 0x02) == 0 ) + { + buf[6] = LOBYTE(pPortParam->wRecvSequence << 1); + buf[7] = HIBYTE(pPortParam->wRecvSequence << 1); + } + // else format_u + } + // format_i + else + { + buf[4] = LOBYTE(pPortParam->wSendSequence << 1); + buf[5] = HIBYTE(pPortParam->wSendSequence << 1); + buf[6] = LOBYTE(pPortParam->wRecvSequence << 1); + buf[7] = HIBYTE(pPortParam->wRecvSequence << 1); + pPortParam->bSendFormatI = TRUE; + //4.bug_1.2.3_20060807_3/bug_2.0.1_20060807_4 104规约不能转发第二个端口的遥测数据 + //发送数据后应当立即将发送序号+1,而不应当在清除命令时+1 + pPortParam->wSendSequence++; + pPortParam->wSendSequence %= MAX_SEQUENCE; + } + + SendDataToPort(commid, (char *)&buf[2], len-2); + + pPortParam->m_psBaoHu->SendCmdFlag = 1; + pPortParam->m_psBaoHu->ReSendCmdFlag = 0; + pPortParam->m_psBaoHu->RevCmdFlag = 0; + pPortParam->m_psBaoHu->RetryTimeCnt = 0; + } + +#ifdef OS_LINUX + if(pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE) +#else + if((pPortParam->m_psBaoHu->LastGetCmdBuf == FAST_CMD_TYPE) + || !isUdpSocketExist()) +#endif + { + pPortParam->m_psBaoHu->ForceWaitCnt = BYTE1(buf[0])+BYTE0(buf[1])+TIMER_CNT-1; + pPortParam->m_psBaoHu->ForceWaitCnt /= TIMER_CNT; + if(pPortParam->m_psBaoHu->ForceWaitCnt) + { + pPortParam->m_psBaoHu->ForceWaitFlag = 1; + } + else + { + ClearCmdFormPollCmdBuf(commid); // 清除当前命令 + //ClearCmdAllFlag(commid); // 清除当前命令 + if(pPortParam->bSendFormatI) + { + //pPortParam->wSendSequence++; + //pPortParam->wSendSequence %= MAX_SEQUENCE; + pPortParam->bSendFormatI = FALSE; + } + } + } +} +//===========================指令生成函数结束========================= + +//===========================以下为数据处理函数======================= +void Buban104ProcessData(u_32 commid, BUBAN104PORTPARAM *psPortParam, BOOL bProcess) +{ + RTUMSG msg; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = psPortParam; + + if(TRUE == bProcess) + { + msg.PortIdx = (BYTE)commid; + msg.MsgLen = psPortParam->m_iRecvLen; + memcpy(msg.MsgData, psPortParam->m_au8RecvBuf, msg.MsgLen); + msg.MsgData[msg.MsgLen] = CHECK_WHOLE; + msg.MsgData[msg.MsgLen+1] = 0; + + // 超时计数清零 + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = FALSE; + + // 子站数据处理 + if(PROTOCOL_SLAVE == pPortParam->m_psBaoHu->PortType) + { + ProvBuban104dataProcess(commid, &msg); + return; + } + + // format-i + if((msg.MsgData[2] & 0x01) == 0) + { + Buban104FormatI(&msg); + } + // format-s,format-u + else + { + // format-u + if((msg.MsgData[2] & 0x02) != 0 ) + { + Buban104FormatU(&msg); + } + // format-s( 主站不会收到's'帧格式) + //else Buban104FormatS(&msg); + } + } +} + +//*************************************************************** +//* I帧数据的处理程序 +//*参数 RTUMSG* rtumsg:接收到的数据信息 +//*************************************************************** +void Buban104FormatI(RTUMSG *rtumsg) +{ + int commid, iSequenceInc; + BUBAN104PORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + // length + if(rtumsg->MsgData[1] < 4) + { + return; + } + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + pPortParam->wAckSequence = (rtumsg->MsgData[4]+(rtumsg->MsgData[5] << 8)) >> 1; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// + // wen 2005.09.19 帧序匹配算法修改 + /* + if(pPortParam->wSendSequence != pPortParam->wAckSequence ) + { + pPortParam->bAckRight = FALSE; + } + //??? WEN 2002.09.17 WHY + else + { + pPortParam->bAckRight = TRUE; + } + */ + + iSequenceInc = pPortParam->wSendSequence - pPortParam->wAckSequence; + if(iSequenceInc < 0) + { + iSequenceInc += MAX_SEQUENCE; + } + //不大于帧序应答尺寸(缺省值=MAX_FRAMEMATCHING_SIZE) + if((pPortParam->wSendSequence != pPortParam->wAckSequence ) + && (iSequenceInc > pPortParam->m_iFrameSize)) + { + pPortParam->bAckRight = FALSE; + } + //??? WEN 2002.09.17 WHY + else + { + pPortParam->bAckRight = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// + + pPortParam->wRecvSequence = (rtumsg->MsgData[2]+(rtumsg->MsgData[3] << 8)) >> 1; + pPortParam->wRecvSequence += 1; + pPortParam->wRecvSequence %= MAX_SEQUENCE; + + switch (rtumsg->MsgData[6]) + { + case 1: // 单点遥信处理 + Buban104DiDataProcess( rtumsg, 0 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command(commid, FORMAT_S ); + break; + + case 2: // 单点遥信SOE处理 + Buban104SoeDataProcess( rtumsg, 0 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command(commid, FORMAT_S); + break; + + case 3: // 双点遥信处理 + Buban104DiDataProcess( rtumsg, 1 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command(commid, FORMAT_S); + break; + + case 4: // 双点遥信SOE处理 + Buban104SoeDataProcess( rtumsg, 1 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command(commid, FORMAT_S); + break; + + case 5: // 变压器分接头位置 + break; + case 6: // 变压器分接头位置带时标 + break; + case 7: // 子站远动终端状态 + break; + + case 9: // 带品质无时标遥测 + Buban104AiWithPzDataProcess( rtumsg, 0 ); + break; + + case 10: // 带品质带时标遥测 + Buban104AiWithPzDataProcess( rtumsg, 1 ); + break; + + case 13: + Buban104AllFloatAiDataProcess( rtumsg ); + break; + + case 20: // 子站传送遥信变位帧 + Buban104AutoSendDiProcess( rtumsg ); + break; + + case 21: // 全遥测数据处理 或变化数据 + Buban104AllAiDataProcess( rtumsg ); + break; + + case 15: // 不带时标电度 + Buban104PiDataProcess( rtumsg ); + break; + case 16: // 带时标电度 + Buban104PiWithTimeDataProcess( rtumsg ); + break; + + case 17: // 继电保护装置单个事件顺序记录帧 + case 18: // 继电保护装置成组记录启动事件顺序 + case 19: // 继电保护装置成组输出电路的事件顺序记录 + Buban104BaoHuDataProcess( rtumsg ); + break; + + // wen 2004.05.27 华东104规约修改点(???) + case 30: // 带CP56Time2a时标的单点信息 M_SP_TB_1 + Buban104SoeDataProcessWithCP56Time2a( rtumsg, 0 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command( commid, FORMAT_S ); + break; + case 31: // 带CP56Time2a时标的双点信息 M_DP_TB_1 + Buban104SoeDataProcessWithCP56Time2a( rtumsg, 1 ); + // wen 2004.09.02 修改为对于遥信变位和soe数据帧确认,以使对方能确认数据收到(拓邦公司用) + MakeBuban104Command( commid, FORMAT_S ); + break; + case 32: // 带CP56Time2a时标的步位置信息 M_ST_TB_1 + break; + case 33: // 带CP56Time2a时标的32比特串 M_BO_TB_1 + break; + case 34: // 带CP56Time2a时标的测量值, 规一化值 M_ME_TD_1 + Buban104AiWithDataProcessWithM_ME_TD_1( rtumsg ); + break; + case 35: // 带CP56Time2a时标的测量值, 标度化值 M_ME_TE_1 + Buban104AiWithDataProcessWithM_ME_TE_1( rtumsg ); + break; + case 36: // 带CP56Time2a时标的测量值, 短浮点数 M_ME_TF_1 + Buban104AiWithDataProcessWithM_ME_TF_1( rtumsg ); + break; + case 37: // 带CP56Time2a时标的累计量 M_IT_TB_1 + Buban104PiWithTimeDataProcessWithM_IT_TB_1( rtumsg ); + break; + case 38: // 带CP56Time2a时标的继电保护装置事件 M_EP_TD_1 + break; + case 39: // 带CP56Time2a时标的继电保护装置成组启动事件 M_EP_TE_1 + break; + case 40: // 带CP56Time2a时标的继电保拌装置成组输出电路信息M_EP_TF_1 + break; + + case 45: + case 46: // 遥控返校 + case 47: // 遥调返校 + Buban104YkYtAck( rtumsg ); + break; + case 48: // 设定确认 + Buban104SetAck( rtumsg ); + break; + case 100: // 总召唤确认 + Buban104InitdataProecss( rtumsg ); + break; + + case 101: // 电度结束帧 + Buban104PidataEnd( rtumsg ); + break; + case 103: // 时间同步确认帧 + Buban104SynTime( rtumsg ); + break; + + default: +#ifdef _DEBUG_MSG_ + DebugPrint("接收到不认识的命令,请检查程序.\n"); +#endif + break; + } +} + +void Buban104FormatU(RTUMSG *rtumsg) +{ + int commid; + BUBAN104PORTPARAM *pPortParam; + + // length + if(rtumsg->MsgData[1] < 4) + { + return; + } + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + switch(rtumsg->MsgData[2] & 0xfc) + { + case 0x08: // 启动动作响应 + InitBuban104CommandBuffer(commid); + pPortParam->bAckRight = TRUE; + pPortParam->LinkOk = TRUE; + break; + case 0x20: // 停止动作响应 + pPortParam->bAckRight = TRUE; + break; + case 0x40: // 测试动作 + //pPortParam->bAckRight = TRUE; + MakeBuban104Command(commid, FORMAT_U_TEST_CON); + if( !pPortParam->bAckRight ) + { + pPortParam->bAckRight = TRUE; + pPortParam->wSendSequence = pPortParam->wAckSequence; + } + break; + // wen 2005.11.02 增加测试响应处理 + case 0x80: // 测试响应 + if(!pPortParam->bAckRight) + { + pPortParam->bAckRight = TRUE; + } + break; + default: // 错误的响应 + pPortParam->bAckRight = FALSE; + break; + } +} + +/* Buban104 初始化数据处理 */ +void Buban104InitdataProecss(RTUMSG * rtumsg) +{ + int commid; + WORD wTransCause; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9] << 8); + } + switch(wTransCause) + { + case 7: + case 9://总召唤确认 + break; + + case 10://总召唤结束 + pPortParam->Initdata = TRUE; + break; + } +} + +/* 电度结束帧 */ +void Buban104PidataEnd(RTUMSG * rtumsg) +{ + int commid; + WORD wTransCause; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9] << 8); + } + + if(wTransCause & 0x0040) + { + pPortParam->Initdata = TRUE; + return; + } + + switch(wTransCause) + { + case 7://总召唤确认 + break; + + case 10://电度召唤结束 + pPortParam->Initdata = TRUE; + break; + } +} + +//设定确认 +void Buban104SetAck( RTUMSG *rtumsg) +{ + +} + +//Buban104 遥控遥调返校程序 +void Buban104YkYtAck(RTUMSG * rtumsg) +{ + int commid; + BYTE bYkOperate; + WORD wTransCause; + YKYT_PARAM YkYtParam; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + YkYtParam.m_iYkYtPnt = (rtumsg->MsgData[11]<<8) + rtumsg->MsgData[10]; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.24 + //YkYtParam.m_iYkYtPnt -= pPortParam->iYkBaseAddr; + //======================================================================= + YkYtParam.m_iYkYtPnt -= (pPortParam->iYkBaseAddr-1); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + YkYtParam.m_iYkYtPnt %= 256; + + wTransCause = rtumsg->MsgData[8]; + bYkOperate = rtumsg->MsgData[12]; + } + else + { + YkYtParam.m_iYkYtPnt = (rtumsg->MsgData[14] << 16) + + (rtumsg->MsgData[13]<<8) + rtumsg->MsgData[12]; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.24 + //YkYtParam.m_iYkYtPnt -= pPortParam->iYkBaseAddr; + //======================================================================= + YkYtParam.m_iYkYtPnt -= (pPortParam->iYkBaseAddr-1); + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + YkYtParam.m_iYkYtPnt %= 256; + + wTransCause = (rtumsg->MsgData[9]<<8) + rtumsg->MsgData[8]; + bYkOperate = rtumsg->MsgData[15]; + } + + if(bYkOperate & 0x80) //选择返校 + { + YkYtParam.m_iYkYtStep = STEP_YKYT_SELECT; + + //此位为肯定或否定确认位 || 撤销确认 + if((wTransCause & 0x0040) || (wTransCause == 0x0009)) + { + YkYtParam.m_iYkYtOperate = 3; + } + else if(wTransCause == 0x0007) + { + if(rtumsg->MsgData[6] != 45) + { + switch(bYkOperate & 0x03) + { + case 1://控分 + if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 2) + { + YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate; + } + else + { + YkYtParam.m_iYkYtOperate = 3; + } + break; + case 2://控合 + if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 1) + { + YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate; + } + else + { + YkYtParam.m_iYkYtOperate = 3; + } + break; + default: + YkYtParam.m_iYkYtOperate = 3; + break; + } + } + else + { + // 控合 + if( bYkOperate & 0x01 ) + { + if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 1) + { + YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate; + } + else + { + YkYtParam.m_iYkYtOperate = 3; + } + } + // 控分 + else + { + if(pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate == 2) + { + YkYtParam.m_iYkYtOperate = pPortParam->m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate; + } + else + { + YkYtParam.m_iYkYtOperate = 3; + } + } + } + } + + YkYtParam.m_iYkYtUpDown = YKYT_SEND_UP; + SendYkYtCommand2(commid, &YkYtParam); + } + else //执行并完成 + { + //此位为肯定或否定确认位 + if((wTransCause & 0x0040) == 0) + { + switch(wTransCause) + { + case 0x0007://执行确认 + break; + case 0x000a://执行完成 + break; + default: + break; + } + } + } +} + +/* Buban104 对时程序 */ +void Buban104SynTime(RTUMSG * rtumsg) +{ + int commid; + WORD wTransCause; + DAY_TIME stime; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(1 != pPortParam->m_psBaoHu->CheckTime) + { + return; + } + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9]<<8); + } + + if(wTransCause != 0x0007) + { + return; + } + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + stime.mSec = (rtumsg->MsgData[13]<<8) + rtumsg->MsgData[12]; + stime.Sec = stime.mSec / 1000; + stime.mSec %= 1000; + stime.Min = rtumsg->MsgData[14] & 0x3F; + stime.Hour = rtumsg->MsgData[15] & 0x1F; + stime.Day = rtumsg->MsgData[16] & 0x1F; + stime.Month= rtumsg->MsgData[17] & 0x0F; + stime.Year = (rtumsg->MsgData[18] & 0x7F)+2000; + } + else + { + stime.mSec = (rtumsg->MsgData[16]<<8) + rtumsg->MsgData[15]; + stime.Sec = stime.mSec / 1000; + stime.mSec %= 1000; + stime.Min = rtumsg->MsgData[17] & 0x3F; + stime.Hour = rtumsg->MsgData[18] & 0x1F; + stime.Day = rtumsg->MsgData[19] & 0x1F; + stime.Month= rtumsg->MsgData[20] & 0x0F; + stime.Year = (rtumsg->MsgData[21] & 0x7F)+2000; + } + SetLocalTimeEx(&stime); +} + +/* 子站主动传送遥信变位帧 */ +void Buban104AutoSendDiProcess(RTUMSG *rtumsg) +{ + int i, j, dipnt, len, istart; + DI_DEF pntmsg; + WORD wStatus, wStatusBit, wTransCause; + + int commid; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + istart = 10; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9]<<8); + istart = 12; + } + + if(wTransCause == 0x0003) + { + for(i = istart; i < (2 + len); ) + { + dipnt = rtumsg->MsgData[i++]; + dipnt += (rtumsg->MsgData[i++]<<8); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + dipnt += (rtumsg->MsgData[i++]<<16); + } + dipnt -= pPortParam->iDiBaseAddr; + + wStatus = rtumsg->MsgData[i++]; + wStatus = (wStatus<<8) + rtumsg->MsgData[i++]; + wStatusBit = rtumsg->MsgData[i++]; + wStatusBit = (wStatusBit<<8) + rtumsg->MsgData[i++]; + + for( j = 0; j < 16; j++ ) + { + if( wStatusBit & (0x0001 << j) ) + { + if( wStatus & (0x0001 << j) ) + pntmsg.Status = 1; + else + pntmsg.Status = 0; + SetPntMsg(commid, dipnt+j, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } + } + } + } +} + +// Buban104 带品质描述的遥测数据处理 +void Buban104AiWithPzDataProcess(RTUMSG * rtumsg, int flag) +{ + int i, aipnt, len; + AI_DEF pntmsg; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + + //处理变化遥测 + for(i = istart; i < (2 + len);) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + aipnt -= pPortParam->iAiBaseAddr; + + pntmsg.RawValue = (short)(rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)); + // 品质描述 + // rtumsg->MsgData[i+2]; + i += 3; + + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + + // 时标 + if(flag) + { + i += 3; + } + } +} + +void Buban104AllAiDataProcess(RTUMSG *rtumsg) +{ + int i, aipnt, len; + AI_DEF pntmsg; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(len <= 0) + { + return; + } + + aipnt = 0; + //处理变化遥测 + if((rtumsg->MsgData[7] & 0x80)==0) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + + for(i = istart; i < len + 2;) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + + aipnt -= pPortParam->iAiBaseAddr; + + pntmsg.RawValue = (short)((rtumsg->MsgData[i+1]<<8) + rtumsg->MsgData[i]); + i += 2; + + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } + return; + } + + //处理全遥测 + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 12; + aipnt = rtumsg->MsgData[10]+(rtumsg->MsgData[11]<<8); + } + else + { + istart = 15; + aipnt = rtumsg->MsgData[12]+(rtumsg->MsgData[13]<<8)+(rtumsg->MsgData[14]<<16); + } + aipnt -= pPortParam->iAiBaseAddr; + + for(i=istart; i < (len+2); i+=2) + { + pntmsg.RawValue = (short)(rtumsg->MsgData[i] + (rtumsg->MsgData[i+1]<<8)); + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aipnt++; + } +} + +void Buban104AllFloatAiDataProcess(RTUMSG *rtumsg) +{ + int i, aipnt, len; + float fValue; + AI_DEF pntmsg; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(len <= 0) + { + return; + } + + aipnt = 0; + //处理变化遥测 + if((rtumsg->MsgData[7] & 0x80)==0) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + + for(i = istart; i < len + 4;) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + + aipnt -= pPortParam->iAiBaseAddr; + + fValue = SequenceRtuToHostfloat((*((float *)&rtumsg->MsgData[i]))); + pntmsg.RawValue = (unsigned long)fValue; + // 含有一个字节的品质描述 + i += sizeof(float)+1; + + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } + return; + } + + //处理全遥测 + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 12; + aipnt = rtumsg->MsgData[10]+(rtumsg->MsgData[11]<<8); + } + else + { + istart = 15; + aipnt = rtumsg->MsgData[12]+(rtumsg->MsgData[13]<<8)+(rtumsg->MsgData[14]<<16); + } + aipnt -= pPortParam->iAiBaseAddr; + + for(i=istart; i < (len+2); i+=5) + { + fValue = SequenceRtuToHostfloat((*((float *)&rtumsg->MsgData[i]))); + pntmsg.RawValue = (unsigned long)fValue; + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aipnt++; + } +} + +void Buban104DiDataProcess(RTUMSG *rtumsg, int flag) +{ + int i, dipnt, len; + DI_DEF pntmsg; + WORD wTransCause; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9]<<8); + } + + //从站主动上发 变化遥信 + if(wTransCause == 0x0003) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < 2 + len; ) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + dipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + dipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + dipnt -= pPortParam->iDiBaseAddr; + + if ( flag == 0 ) + pntmsg.Status = rtumsg->MsgData[i++] & 0x1; + else + { + switch ( rtumsg->MsgData[i++] & 0x3 ) + { + case 1: + pntmsg.Status = 1; + break; + case 2: + pntmsg.Status = 0; + break; + default: + pntmsg.Status = 0xff; + break; + } + } + if ( pntmsg.Status != 0xff ) + { + SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } + } + + return; + } + + if(rtumsg->MsgData[7] & 0x80) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 12; + dipnt = rtumsg->MsgData[10]+(rtumsg->MsgData[11]<<8); + } + else + { + istart = 15; + dipnt = rtumsg->MsgData[12]+(rtumsg->MsgData[13]<<8)+(rtumsg->MsgData[14]<<16); + } + dipnt -= pPortParam->iDiBaseAddr; + + for ( i = istart; i < 2 + len; i++,dipnt++ ) + { + if ( flag == 0 ) + pntmsg.Status = rtumsg->MsgData[i] & 0x1; + else + { + switch ( rtumsg->MsgData[i] & 0x3 ) + { + case 1: + pntmsg.Status = 1; + break; + case 2: + pntmsg.Status = 0; + break; + default: + pntmsg.Status = 0xff; + break; + } + } + if(pntmsg.Status != 0xff) + { + SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } + } + } + else + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < 2 + len; ) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + dipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + dipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + dipnt -= pPortParam->iDiBaseAddr; + + if ( flag == 0 ) + pntmsg.Status = rtumsg->MsgData[i++] & 0x1; + else + { + switch ( rtumsg->MsgData[i++] & 0x3 ) + { + case 1: + pntmsg.Status = 1; + break; + case 2: + pntmsg.Status = 0; + break; + default: + pntmsg.Status = 0xff; + break; + } + } + if(pntmsg.Status != 0xff) + { + SetPntMsg(commid, dipnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_STATUS); + } + } + } +} + +void Buban104SoeDataProcess(RTUMSG *rtumsg, int flag) +{ + _int64 i64Millseconds; + time_t iTime; + int i, pnt, len; + char st; + int sec; + DI_DEF pntmsg; + DAY_TIME sm; + struct tm *testtm; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < len + 2;) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + pnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + pnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + pnt -= pPortParam->iDiBaseAddr; + + if ( flag == 0 ) + st = rtumsg->MsgData[i++] & 0x01; + else + { + switch ( rtumsg->MsgData[i++] & 0x3 ) + { + case 1: + st = 1; + break; + case 2: + st = 0; + break; + default: + st = 0x0f; + break; + } + } + if ( st == 0x0f ) + continue; + + sec = rtumsg->MsgData[i] + ( rtumsg->MsgData[i+1] << 8 ); + pntmsg.SoeTime.mSec = sec % 1000; + pntmsg.SoeTime.Sec = sec / 1000; + pntmsg.SoeTime.Min = (rtumsg->MsgData[i+2] & 0x3f); // 分 + i += 3; + GetLocalTimeEx(&sm); + if(abs(pntmsg.SoeTime.Min-sm.Min) > 50) + { + i64Millseconds = SystemTimeToMillseconds(&sm, 0); + if(i64Millseconds > 0) + { + // 减去一小时 + iTime = (long)(i64Millseconds/1000) - 3600; + testtm = localtime(&iTime); + sm.Year = testtm->tm_year + 1900; + sm.Month = testtm->tm_mon + 1; + sm.Day = testtm->tm_mday; + sm.Hour = testtm->tm_hour; + sm.Min = testtm->tm_min; + sm.Sec = testtm->tm_sec; + } + } + + pntmsg.SoeTime.Hour = sm.Hour; + pntmsg.SoeTime.Day = sm.Day; + pntmsg.SoeTime.Month = sm.Month; + pntmsg.SoeTime.Year = sm.Year; + pntmsg.Status = st; + + SetPntMsg(commid, pnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_SOE_TIME); + } +} + +void Buban104PiDataProcess( RTUMSG * rtumsg ) +{ + int i, point, len; + PI_DEF pntmsg; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < 2 + len; ) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + point -= pPortParam->iPiBaseAddr; + + pntmsg.RawValue = (rtumsg->MsgData[i+3]<<24) + (rtumsg->MsgData[i+2]<<16) + + (rtumsg->MsgData[i+1]<<8) + rtumsg->MsgData[i]; + //rtumsg->MsgData[i+4]; // 顺序记号 + i += 5; + + SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban104PiWithTimeDataProcess( RTUMSG *rtumsg ) +{ + int i, point, len; + PI_DEF pntmsg; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < 2 + len; ) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + + point -= pPortParam->iPiBaseAddr; + + pntmsg.RawValue = (rtumsg->MsgData[i+3]<<24) + (rtumsg->MsgData[i+2]<<16) + + (rtumsg->MsgData[i+1]<<8) + rtumsg->MsgData[i]; + //rtumsg->MsgData[i+4]; // 顺序记号 + // 3bytes 时间 + i += 8; + + SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + } +} + +void Buban104BaoHuDataProcess( RTUMSG *rtumsg ) +{ + // 该功能不做处理 +} + +void Buban104DefaultBaoHuDataProcess( RTUMSG *rtumsg ) +{ + // 该功能不做处理 +} + +// 新增函数,含有 7 BYTE 的时标 +//*************************************************************** +//* Buban104 SOE 数据处理(7 bytes 时间) * +//*************************************************************** +void Buban104SoeDataProcessWithCP56Time2a( RTUMSG *rtumsg, int flag ) +{ + _int64 i64Millseconds; + time_t iTime; + int i, pnt, len; + char st; + int sec; + DI_DEF pntmsg; + DAY_TIME sm; + struct tm *testtm; + int commid, istart; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + } + else + { + istart = 12; + } + for ( i = istart; i < len + 2; ) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + pnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + pnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + pnt -= pPortParam->iDiBaseAddr; + + if(flag == 0) + { + st = rtumsg->MsgData[i++] & 0x01; + } + else + { + switch ( rtumsg->MsgData[i++] & 0x3 ) + { + case 1: + st = 1; + break; + case 2: + st = 0; + break; + default: + st = 0x0f; + break; + } + } + if(st == 0x0f) + { + continue; + } + + sec = rtumsg->MsgData[i] + (rtumsg->MsgData[i+1] << 8); + pntmsg.SoeTime.mSec = sec % 1000; + pntmsg.SoeTime.Sec = sec / 1000; + pntmsg.SoeTime.Min = (char)(rtumsg->MsgData[i+2] & 0x3f); + pntmsg.SoeTime.Hour = (char)(rtumsg->MsgData[i+3] & 0x1f); + pntmsg.SoeTime.Day = (char)(rtumsg->MsgData[i+4] & 0x1f); + //rtumsg->MsgData[i+5]; // month + //rtumsg->MsgData[i+6]; // year + i += 7; + + GetLocalTimeEx(&sm); + if((pntmsg.SoeTime.Day-sm.Day) < 0) + { + i64Millseconds = SystemTimeToMillseconds(&sm, 0); + if(i64Millseconds > 0) + { + // 减去一小时 + iTime = (long)(i64Millseconds/1000) - 3600; + testtm = localtime(&iTime); + sm.Year = testtm->tm_year + 1900; + sm.Month = testtm->tm_mon + 1; + sm.Day = testtm->tm_mday; + sm.Hour = testtm->tm_hour; + sm.Min = testtm->tm_min; + sm.Sec = testtm->tm_sec; + } + } + + pntmsg.SoeTime.Month = sm.Month; + pntmsg.SoeTime.Year = sm.Year; + pntmsg.Status = st; + SetPntMsg(commid, pnt, (void *)&pntmsg, DI_PNT_TYPE, PNT_SOE_TIME); + } +} + +void Buban104AiWithDataProcessWithM_ME_TD_1(RTUMSG * rtumsg) +{ + int i, aipnt, len; + AI_DEF pntmsg; + char szbuf[256]; + int commid, istart, istep; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + istep = 11; + } + else + { + istart = 12; + istep = 12; + } + //处理变化遥测 + for ( i = istart; i < 2 + len; ) + { + if( ( i + istep ) > (2 + len)) + { + sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban104AiWithDataProcessWithM_ME_TD_1", + _getpid(), commid, len); + DebugPrint(szbuf); + break; + } + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + + aipnt -= pPortParam->iAiBaseAddr; + + pntmsg.RawValue = (short)((rtumsg->MsgData[i+1]<<8) + rtumsg->MsgData[i]); + + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + + // 7字节时标 + i += 9; + } +} + +void Buban104AiWithDataProcessWithM_ME_TE_1(RTUMSG * rtumsg) +{ + Buban104AiWithDataProcessWithM_ME_TD_1(rtumsg); +} + +void Buban104AiWithDataProcessWithM_ME_TF_1(RTUMSG * rtumsg) +{ + int i, aipnt, len; + AI_DEF pntmsg; + char szbuf[256]; + float fValue; + int commid, istart, istep; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + len = (int)rtumsg->MsgData[1]; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + istep = 14; + } + else + { + istart = 12; + istep = 15; + } + //处理变化遥测 + for ( i = istart; i < 2 + len; ) + { + if( ( i + istep ) > (2 + len)) + { + sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban104AiWithDataProcessWithM_ME_TF_1", + _getpid(), commid, len); + DebugPrint(szbuf); + break; + } + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + aipnt = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + + aipnt -= pPortParam->iAiBaseAddr; + + fValue = *((float *)&rtumsg->MsgData[i]); + SequenceRtuToHost((char *)&fValue, sizeof(float)); + + // 品质描述 + // rtumsg->MsgData[i+1]; + + // 保留2位小数 + pntmsg.RawValue = (int)(fValue * 100); + SetPntMsg(commid, aipnt, (void *)&pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + + // 7字节时标 + i += 12; + } +} + +//Buban104 电度数据处理with time +void Buban104PiWithTimeDataProcessWithM_IT_TB_1(RTUMSG *rtumsg) +{ + int i, point, len; + AI_DEF pntmsg; + char szbuf[256]; + int commid, istart, istep; + BUBAN104PORTPARAM *pPortParam; + + commid = rtumsg->PortIdx; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + istart = 10; + istep = 14; + } + else + { + istart = 12; + istep = 15; + } + len = (int)rtumsg->MsgData[1]; + for ( i = istart; i < 2 + len; ) + { + if( ( i + istep ) > (2 + len)) + { + sprintf(szbuf, ">>>>>WARN(%04d): Commid_%02d (iLen=%d) is not enough in Buban104PiWithTimeDataProcessWithM_IT_TB_1", + _getpid(), commid, len); + DebugPrint(szbuf); + break; + } + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8); + i += 2; + } + else + { + point = rtumsg->MsgData[i]+(rtumsg->MsgData[i+1]<<8)+(rtumsg->MsgData[i+2]<<16); + i += 3; + } + point -= pPortParam->iPiBaseAddr; + + pntmsg.RawValue = (rtumsg->MsgData[i+3]<<24) + (rtumsg->MsgData[i+2]<<16) + + (rtumsg->MsgData[i+1]<<8) + rtumsg->MsgData[i]; + + SetPntMsg(commid, point, (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + + // 1 BYTE (IV CA CY 顺序号) + // 7 BYTE 时标 + i += 12; + } +} + +//=========================以下为Buban104转发数据功能=======================// +void ProvBuban104dataProcess(int commid, RTUMSG *rtumsg) +{ + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + // 数据校验错误( 附加字节的第二个字节) + if(rtumsg->MsgData[rtumsg->MsgLen+1] > 0) + { + return; + } + + // format-i + if((rtumsg->MsgData[2] & 0x01) == 0) + { + if(pPortParam->LinkOk) + { + ProvBuban104FormatI(commid, rtumsg); + } + } + // format-s,format-u + else + { + // format-u + if((rtumsg->MsgData[2] & 0x02) != 0) + { + ProvBuban104FormatU( commid, rtumsg ); + } + // format-s + else + { + ProvBuban104FormatS( commid, rtumsg ); + } + } +} + +void ProvBuban104FormatI(int commid, RTUMSG *rtumsg) +{ + //WORD wLastSequence; + int iSequenceInc; + BUBAN104PORTPARAM *pPortParam; + + // length + if( rtumsg->MsgData[1] < 4 ) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + // 超时计数清零 + pPortParam->lTimeOutCnt = 0; + + pPortParam->wAckSequence = (rtumsg->MsgData[4] + (rtumsg->MsgData[5]<<8)) >> 1; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// + // wen 2005.09.19 帧序匹配算法修改 + /* + if(pPortParam->wAckSequence == 0 ) + { + wLastSequence = MAX_SEQUENCE; + } + else + { + wLastSequence = pPortParam->wAckSequence-1; + } + if((pPortParam->wSendSequence != pPortParam->wAckSequence) + && (pPortParam->wSendSequence != wLastSequence)) + { + pPortParam->bAckRight = FALSE; + } + else + { + pPortParam->bCloseSocket = FALSE; + pPortParam->bAckRight = TRUE; + } + */ + iSequenceInc = pPortParam->wSendSequence - pPortParam->wAckSequence; + if(iSequenceInc < 0) + { + iSequenceInc += MAX_SEQUENCE; + } + //不大于帧序应答尺寸(缺省值=MAX_FRAMEMATCHING_SIZE) + if((pPortParam->wSendSequence != pPortParam->wAckSequence ) + && (iSequenceInc > pPortParam->m_iFrameSize)) + { + pPortParam->bAckRight = FALSE; + } + else + { + pPortParam->bCloseSocket = FALSE; + pPortParam->bAckRight = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// + + pPortParam->wRecvSequence = ((rtumsg->MsgData[2] + (rtumsg->MsgData[3]<<8)) >> 1)+1; + pPortParam->wRecvSequence %= MAX_SEQUENCE; + + switch(rtumsg->MsgData[6]) + { + case 1: // 单点遥信处理 + break; + + case 2: // 单点遥信SOE处理 + break; + + case 3: // 双点遥信处理 + break; + + case 4: // 单点遥信SOE处理 + break; + + case 5: // 变压器分接头位置 + break; + case 6: // 变压器分接头位置带时标 + break; + case 7: // 总召唤数据 + ProvBuban104SendAllData(commid, rtumsg); + break; + + case 9: // 带品质无时标遥测 + break; + + case 10: // 带品质带时标遥测 + break; + + case 21: // 全遥测数据处理 或变化数据 + break; + + case 15: // 不带时标电度 + break; + case 16: // 带时标电度 + break; + + case 17: + case 18: + case 19: // 保护数据 + break; + + case 45: // wen 2006.07.11 + case 46: // 遥控返校 + case 47: // 遥调返校 + //ProvBuban104YkYtData(commid, rtumsg); + break; + + case 100: // 召唤数据 + //ProvBuban104SendAllData(commid, rtumsg); + break; + + case 101: // 召唤电度 + //ProvBuban104SendPIData(commid, rtumsg); + break; + + case 103: // 时间同步确认帧 + ProvBuban104ProcessTime(commid, rtumsg); + break; + } +} + +void ProvBuban104FormatU(int commid, RTUMSG *rtumsg) +{ + BUBAN104PORTPARAM *pPortParam; + + // length + if( rtumsg->MsgData[1] != 4 ) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + switch(rtumsg->MsgData[2] & 0xfc) + { + case 0x04: // 启动动作 + InitBuban104CommandBuffer(commid); + pPortParam->LinkOk = TRUE; + MakeBuban104Command(commid, FORMAT_U_START_CON); + break; + case 0x10: // 停止动作 + pPortParam->LinkOk = FALSE; + MakeBuban104Command(commid, FORMAT_U_STOP_CON); + break; + case 0x80: // 测试动作响应 + pPortParam->bAckRight = TRUE; + // 超时计数清零 + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = FALSE; + break; + case 0x40: // 测试动作 + if(!pPortParam->LinkOk) + { + break; + } + + MakeBuban104Command(commid, FORMAT_U_TEST_CON); + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = FALSE; + pPortParam->bAckRight = TRUE; + break; + default: // 错误的响应 + pPortParam->bAckRight = FALSE; + break; + } +} + +void ProvBuban104FormatS(int commid, RTUMSG *rtumsg) +{ + //WORD wLastSequence; + int iSequenceInc; + BUBAN104PORTPARAM *pPortParam; + + // length + if( rtumsg->MsgData[1] != 4 ) + { + return; + } + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + pPortParam->wAckSequence = (rtumsg->MsgData[4] + (rtumsg->MsgData[5]<<8)) >> 1; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// + // wen 2005.09.19 帧序匹配算法修改 + /* + if(pPortParam->wAckSequence == 0) + { + wLastSequence = MAX_SEQUENCE; + } + else + { + wLastSequence = pPortParam->wAckSequence-1; + } + + if((pPortParam->wSendSequence == (pPortParam->wAckSequence + 1) ) + || (pPortParam->wSendSequence == wLastSequence)) + { + pPortParam->bAckRight = TRUE; + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = FALSE; + } + */ + + iSequenceInc = pPortParam->wSendSequence - pPortParam->wAckSequence; + if(iSequenceInc < 0) + { + iSequenceInc += MAX_SEQUENCE; + } + //不大于帧序应答尺寸(缺省值=MAX_FRAMEMATCHING_SIZE) + if((pPortParam->wSendSequence == pPortParam->wAckSequence) + || (iSequenceInc < pPortParam->m_iFrameSize)) + { + pPortParam->bAckRight = TRUE; + pPortParam->lTimeOutCnt = 0; + pPortParam->bCloseSocket = FALSE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// +} + +//响应分组召唤和总召唤 +//总召唤确认(传送原因[8]=0x07,0x09确认; =0x0a 总召唤结束) +void ProvBuban104SendAllData(int commid, RTUMSG * rtumsg) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + int iGroup, iCmdType, iLen=0; + WORD wTransCause; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + iGroup = rtumsg->MsgData[12]; + wTransCause = rtumsg->MsgData[8]; + + iCmdType = FAST_POLL_CMD; + + //总召唤应答 + commandbuf[0] = 0x68; + iLen = 2; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 8; // 应答总召结束 + commandbuf[iLen++] = 0x81; // 限定词VSQ + commandbuf[iLen++] = 9; // 传送原因 + commandbuf[iLen++] = 0; // 应用服务单元公共地址 + commandbuf[iLen++] = 0; // 应用服务单元公共地址 + commandbuf[iLen++] = 0xFF; // 功能类型FUN + commandbuf[iLen++] = 0; // 信息序号INF + commandbuf[iLen++] = 0; // 扫描序号SCN + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLen); + + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 支持浮点数遥测的传送 + //ProvBuban104SendAI(commid, rtumsg, 0); + //==================================================================== + if(pPortParam->m_bProvAiType == 13) + { + ProvBuban104SendAIwithFloat(commid, rtumsg, 0); + } + else + { + ProvBuban104SendAI(commid, rtumsg, 0); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ProvBuban104SendDI(commid, rtumsg, 0); + + //总召唤结束 + ProvMakeBuban104Command(commid, ASK_ALLDATA_END); + pPortParam->m_psBaoHu->DiChange = FALSE; + pPortParam->Initdata = TRUE; +} + +/* +void ProvBuban104SendAllData(int commid, RTUMSG * rtumsg) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + int iGroup, iCmdType, iLen = 0; + WORD wTransCause; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if (VER_BUBAN_104 == pPortParam->RtuVersion) + { + iGroup = rtumsg->MsgData[12]; + wTransCause = rtumsg->MsgData[8]; + } + else + { + iGroup = rtumsg->MsgData[15]; + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9] << 8); + } + + //分组召唤 + if (iGroup != 20) + { + iGroup -= 20; + //无效组号 + if ((iGroup <= 0) || (iGroup > 12)) + { + return; + } + if (iGroup > 8) + { + iGroup -= 8; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 支持浮点数遥测的传送 + //ProvBuban104SendAI(commid, rtumsg, iGroup); + //==================================================================== + if (pPortParam->m_bProvAiType == 13) + { + ProvBuban104SendAIwithFloat(commid, rtumsg, iGroup); + } + else + { + ProvBuban104SendAI(commid, rtumsg, iGroup); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + else + ProvBuban104SendDI(commid, rtumsg, iGroup); + return; + } + + if (pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + //总召唤 + commandbuf[0] = 0x68; + iLen = 2; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 100; + commandbuf[iLen++] = 0; + if (VER_BUBAN_104 == pPortParam->RtuVersion) + { + switch (wTransCause) + { + case 0x0006://激活 + commandbuf[iLen++] = 7; + break; + case 0x0008://停止激活 + default: + commandbuf[iLen++] = 9; + break; + } + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + switch (wTransCause) + { + case 0x0006://激活 + commandbuf[iLen++] = 7; + commandbuf[iLen++] = 0; + break; + case 0x0008://停止激活 + default: + commandbuf[iLen++] = 9; + commandbuf[iLen++] = 0; + break; + } + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 0x14; + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLen); + + if (wTransCause != 0x0006) + { + return; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 支持浮点数遥测的传送 + //ProvBuban104SendAI(commid, rtumsg, 0); + //==================================================================== + if (pPortParam->m_bProvAiType == 13) + { + ProvBuban104SendAIwithFloat(commid, rtumsg, 0); + } + else + { + ProvBuban104SendAI(commid, rtumsg, 0); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + ProvBuban104SendDI(commid, rtumsg, 0); + + //总召唤结束 + ProvMakeBuban104Command(commid, ASK_ALLDATA_END); + pPortParam->m_psBaoHu->DiChange = FALSE; + pPortParam->Initdata = TRUE; +} +*/ + +void ProvBuban104SendPIData(int commid, RTUMSG * rtumsg) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + int iLen, iCmdType, iGroup; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + iGroup = rtumsg->MsgData[12] & 0x3F; + } + else + { + iGroup = rtumsg->MsgData[15] & 0x3F; + } + + // wen 2006.04.03 发布时间97版和2000版组分配不同 + if(pPortParam->m_iPublishYear == 1997) + { + //分组召唤 + if( iGroup != 1 ) + { + //无效或者扩展组号 + if(( iGroup <= 0 ) || ( iGroup > 5 )) + { + return; + } + + ProvBuban104SendPI(commid, rtumsg, iGroup-1); + return; + } + } + else + { + //分组召唤 + if( iGroup != 5 ) + { + //无效或者扩展组号 + if(( iGroup <= 0 ) || ( iGroup > 5 )) + { + return; + } + + ProvBuban104SendPI(commid, rtumsg, iGroup); + return; + } + } + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + //总召唤确认 + commandbuf[0] = 0x68; + iLen = 2; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 101; + commandbuf[iLen++] = 0; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 7; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = rtumsg->MsgData[12]; + } + else + { + commandbuf[iLen++] = 7; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = rtumsg->MsgData[15]; + } + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLen); + + ProvBuban104SendPI(commid, rtumsg, 0); + + //总召唤结束 + commandbuf[0] = 0x68; + iLen = 2; + //commandbuf[1] = 14; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 101; + commandbuf[iLen++] = 0; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 10; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = rtumsg->MsgData[12]; + } + else + { + commandbuf[iLen++] = 10; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = rtumsg->MsgData[15]; + } + commandbuf[1] = (BYTE)(iLen - 2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLen); + + pPortParam->Initdata = TRUE; +} + +void ProvBuban104ProcessTime(int commid, RTUMSG *rtumsg) +{ + int iLen, iCmdType; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + WORD wTransCause; + DAY_TIME sCurTime; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + wTransCause = rtumsg->MsgData[8]; + } + else + { + wTransCause = rtumsg->MsgData[8] + (rtumsg->MsgData[9]<<8); + } + //传送原因 + switch(wTransCause) + { + case 0x0006://激活(对时) + commandbuf[0] = 0x68; + //commandbuf[1] = 20; + iLen = 2; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 103; + commandbuf[iLen++] = 1; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = 7; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 7; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + GetLocalTimeEx(&sCurTime); + sCurTime.mSec = sCurTime.Sec * 1000 + sCurTime.mSec; + commandbuf[iLen++] = sCurTime.mSec % 256; + commandbuf[iLen++] = sCurTime.mSec / 256; + commandbuf[iLen++] = (u_char)sCurTime.Min; + commandbuf[iLen++] = (u_char)sCurTime.Hour; + commandbuf[iLen++] = (u_char)sCurTime.Day; + commandbuf[iLen++] = (u_char)sCurTime.Month; + commandbuf[iLen++] = (u_char)(sCurTime.Year%100); + commandbuf[1] = (BYTE)(iLen - 2); + if(pPortParam->ProvAckOrNot) + { + iCmdType = INSERT_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLen); + + // 对时 + if(1 == pPortParam->m_psBaoHu->CheckTime) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + sCurTime.mSec = rtumsg->MsgData[12] + (rtumsg->MsgData[13] << 8); + sCurTime.Sec = sCurTime.mSec/1000; + sCurTime.mSec = sCurTime.mSec % 1000; + sCurTime.Min = rtumsg->MsgData[14] & 0x3F; + sCurTime.Hour = rtumsg->MsgData[15] & 0x1F; + sCurTime.Day = rtumsg->MsgData[16] & 0x1F; + sCurTime.Month= rtumsg->MsgData[17] & 0x0F; + sCurTime.Year = (rtumsg->MsgData[18] & 0x7F)+2000; + } + else + { + sCurTime.mSec = rtumsg->MsgData[15] + (rtumsg->MsgData[16] << 8); + sCurTime.Sec = sCurTime.mSec/1000; + sCurTime.mSec = sCurTime.mSec % 1000; + sCurTime.Min = rtumsg->MsgData[17] & 0x3F; + sCurTime.Hour = rtumsg->MsgData[18] & 0x1F; + sCurTime.Day = rtumsg->MsgData[19] & 0x1F; + sCurTime.Month= rtumsg->MsgData[20] & 0x0F; + sCurTime.Year = (rtumsg->MsgData[21] & 0x7F)+2000; + } + SetLocalTimeEx(&sCurTime); + } + break; + + case 0x07://激活确认 + break; + } +} + +void ProvBuban104SendPI(int commid, RTUMSG *rtumsg, int iGroupNo) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int i, j, iAllDataCount, iSendNum; + int iNo; + int iCmdType; + PI_DEF pntmsg; + PROV_PI_PNT *piprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + if(iGroupNo == 0)//总召唤 + { + dwStartAddr = MAX_GROUP_PINUM*iGroupNo + pPortParam->iPiBaseAddr; + + iAllDataCount = pPortParam->m_psBaoHu->PiNum; + iSendCount = (iAllDataCount+MAX_104_PINUM-1)/MAX_104_PINUM; + iCmdType = FAST_POLL_CMD; + } + else//分组召唤 + { + dwStartAddr = MAX_GROUP_PINUM*(iGroupNo-1); + iAllDataCount = pPortParam->m_psBaoHu->PiNum - dwStartAddr; + + dwStartAddr += pPortParam->iPiBaseAddr; + + if( iAllDataCount > MAX_GROUP_PINUM) + { + iSendCount = 2; + if((iAllDataCount - MAX_GROUP_PINUM)>0) + iAllDataCount = MAX_GROUP_PINUM; + } + } + + piprovptr = (PROV_PI_PNT *)pPortParam->m_psBaoHu->PiPtr; + for(i = 0; i < iSendCount; i++) + { + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 15; + commandbuf[8] = 37+iGroupNo; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + iLenth = 10; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + iLenth = 12; + } + //遥测值 + if(iAllDataCount>MAX_104_PINUM) + { + iAllDataCount -= MAX_104_PINUM; + iSendNum = MAX_104_PINUM; + } + else + { + iSendNum = iAllDataCount; + } + + for(j = 0; j < iSendNum; j++, dwStartAddr++) + { + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = (char)(dwStartAddr & 0x00ff); + commandbuf[iLenth++] = (char)((dwStartAddr & 0xff00)>>8); + } + else + { + commandbuf[iLenth++] = (char)(dwStartAddr & 0x00ff); + commandbuf[iLenth++] = (char)((dwStartAddr & 0xff00)>>8); + commandbuf[iLenth++] = (char)((dwStartAddr & 0xff0000)>>16); + } + + iNo = dwStartAddr - pPortParam->iPiBaseAddr; + + pntmsg.RawValue = 0; + GetPntMsg(piprovptr[iNo].PortNo, piprovptr[iNo].PntNo, + (void *)&pntmsg, PI_PNT_TYPE, PNT_RAWVALUE); + piprovptr[iNo].ChangeFlag = FALSE; + + commandbuf[iLenth++] = (char)(pntmsg.RawValue & 0x000000ff); + commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0x0000ff00)>>8); + commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0x00ff0000)>>16); + commandbuf[iLenth++] = (char)((pntmsg.RawValue & 0xff000000)>>24); + commandbuf[iLenth++] = (char)(j+1); + } + + commandbuf[7] = (BYTE)j; + commandbuf[1] = (char)(iLenth-2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + } +} + +void ProvBuban104SendAI(int commid, RTUMSG *rtumsg, int iGroupNo) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int i, j, iAllDataCount, iSendNum; + int iNo, iCmdType; + AI_DEF pntmsg; + PROV_AI_PNT *aiprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + if( iGroupNo == 0 )//总召唤 + { + dwStartAddr = MAX_GROUP_AINUM*iGroupNo + pPortParam->iAiBaseAddr; + + iAllDataCount = pPortParam->m_psBaoHu->AiNum; + iSendCount = (iAllDataCount+MAX_AINUM-1)/MAX_AINUM; + iCmdType = FAST_POLL_CMD; + } + else//分组召唤 + { + dwStartAddr = MAX_GROUP_AINUM*(iGroupNo-1); + iAllDataCount = pPortParam->m_psBaoHu->AiNum - dwStartAddr; + dwStartAddr += pPortParam->iAiBaseAddr; + + if(iAllDataCount > MAX_AINUM) + { + iSendCount = 2; + if((iAllDataCount - MAX_GROUP_AINUM) > 0) + { + iAllDataCount = MAX_GROUP_AINUM; + } + } + } + + aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr; + for( i = 0; i < iSendCount; i++ ) + { + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 21; + //commandbuf[8] = rtumsg->MsgData[15]; + commandbuf[8] = rtumsg->MsgData[8]; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + // 信息体地址为2个字节 + //*((DWORD*)(&commandbuf[12])) = dwStartAddr; + commandbuf[10] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[11] = HIBYTE(LOWORD(dwStartAddr)); + iLenth = 12; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + // 信息体地址为3个字节 + //*((DWORD*)(&commandbuf[12])) = dwStartAddr; + commandbuf[12] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[13] = HIBYTE(LOWORD(dwStartAddr)); + commandbuf[14] = LOBYTE(HIWORD(dwStartAddr)); + iLenth = 15; + } + + //遥测值 + if(iAllDataCount > MAX_AINUM) + { + iAllDataCount -= MAX_AINUM; + iSendNum = MAX_AINUM; + } + else + { + iSendNum = iAllDataCount; + } + + iNo = dwStartAddr - pPortParam->iAiBaseAddr; + for( j = 0; j < iSendNum; j++ ) + { + GetPntMsg(aiprovptr[iNo+j].PortNo, aiprovptr[iNo+j].PntNo, + &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aiprovptr[iNo+j].ChangeFlag = FALSE; + commandbuf[iLenth++] = (char)(pntmsg.RawValue); + commandbuf[iLenth++] = (char)((pntmsg.RawValue&0xff00)>>8); + } + + commandbuf[7] = (BYTE)j; + commandbuf[7] |= 0x80; + commandbuf[1] = (char)(iLenth-2); + + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + + dwStartAddr += MAX_AINUM; + } +} + +void ProvBuban104SendDI(int commid, RTUMSG *rtumsg, int iGroupNo) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int i, j, iAllDataCount, iSendNum; + int iNo, iCmdType; + DI_DEF pntmsg; + PROV_DI_PNT *diprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + if(iGroupNo == 0)//总召唤 + { + dwStartAddr = MAX_GROUP_DINUM*iGroupNo + pPortParam->iDiBaseAddr; + + iAllDataCount = pPortParam->m_psBaoHu->DiNum; + iSendCount = (iAllDataCount+MAX_DINUM-1)/MAX_DINUM; + iCmdType = FAST_POLL_CMD; + } + else//分组召唤 + { + dwStartAddr = MAX_GROUP_DINUM*(iGroupNo-1); + iAllDataCount = pPortParam->m_psBaoHu->DiNum - dwStartAddr; + + dwStartAddr += pPortParam->iDiBaseAddr; + + if( iAllDataCount > MAX_GROUP_DINUM) + { + iAllDataCount = MAX_GROUP_DINUM; + } + } + + diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr; + for(i=0; iMsgData[12]; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[10] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[11] = HIBYTE(LOWORD(dwStartAddr)); + iLenth = 12; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + // 信息体地址为3个字节 + //*((DWORD*)(&commandbuf[12])) = dwStartAddr; + commandbuf[12] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[13] = HIBYTE(LOWORD(dwStartAddr)); + commandbuf[14] = LOBYTE(HIWORD(dwStartAddr)); + iLenth = 15; + } + + if(iAllDataCount > MAX_DINUM) + { + iAllDataCount -= MAX_DINUM; + iSendNum = MAX_DINUM; + } + else + { + iSendNum = iAllDataCount; + } + + iNo = dwStartAddr - pPortParam->iDiBaseAddr; + for( j = 0; j < iSendNum; j++ ) + { + GetPntMsg(diprovptr[iNo+j].PortNo, diprovptr[iNo+j].PntNo, + &pntmsg, DI_PNT_TYPE, PNT_STATUS); + diprovptr[iNo+j].ChangeFlag = FALSE; + commandbuf[iLenth++] = pntmsg.Status; + } + + commandbuf[7] = (char)j; + commandbuf[7] |= 0x80; + commandbuf[1] = (char)(iLenth-2); + + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + + dwStartAddr += MAX_DINUM; + } +} + +void ProvBuban104SendSoe(int commid) +{ + u_char commandbuf[MAX_POLLCMD_BUF_LEN]; + + BOOL bHaveData = FALSE; + WORD wmSec; + DWORD dwAddr; + int iLenth, iSendCount=1; + int iDataNum, iCmdType; + SOE_DEF soemsg; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(ProvHaveSoeData(commid) <= 0) + { + return; + } + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 2;//单点soe + commandbuf[8] = 3; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + } + + bHaveData = TRUE; + iLenth = 12; + iDataNum = 0; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.07.12 修改soe为单个时,数据丢失的问题. + /*while(ProvAndDelGetSoeData(commid, &soemsg) > 0) + { + iDataNum++; + dwAddr = (DWORD)(pPortParam->iDiBaseAddr+soemsg.iPntNo); + + commandbuf[iLenth++] = LOBYTE(LOWORD(dwAddr)); + commandbuf[iLenth++] = HIBYTE(LOWORD(dwAddr)); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = LOBYTE(HIWORD(dwAddr)); + } + commandbuf[iLenth++] = soemsg.bStatus; + wmSec = soemsg.SoeTime.mSec + soemsg.SoeTime.Sec*1000; + commandbuf[iLenth++] = LOBYTE(wmSec); + commandbuf[iLenth++] = HIBYTE(wmSec); + commandbuf[iLenth++] = soemsg.SoeTime.Min & 0x3f; + if(iLenth >= 251) + { + break; + } + }*/ + //=========================================================== + while(ProvHaveSoeData(commid) > 0) + { + ProvAndDelGetSoeData(commid, &soemsg); + iDataNum++; + dwAddr = (DWORD)(pPortParam->iDiBaseAddr+soemsg.iPntNo); + + commandbuf[iLenth++] = LOBYTE(LOWORD(dwAddr)); + commandbuf[iLenth++] = HIBYTE(LOWORD(dwAddr)); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = LOBYTE(HIWORD(dwAddr)); + } + commandbuf[iLenth++] = soemsg.bStatus; + wmSec = soemsg.SoeTime.mSec + soemsg.SoeTime.Sec*1000; + commandbuf[iLenth++] = LOBYTE(wmSec); + commandbuf[iLenth++] = HIBYTE(wmSec); + commandbuf[iLenth++] = soemsg.SoeTime.Min & 0x3f; + if(iLenth >= 248) + { + break; + } + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + commandbuf[7] = (BYTE)iDataNum; + commandbuf[1] = (BYTE)(iLenth-2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); +} + +void ProvBuban104YkYtData(int commid, RTUMSG *rtumsg) +{ + PROV_DI_PNT *diprovptr; + DI_DEF *diptr; + int ykytcommid, provpnt; + int ykytpnt, ykytop, step; + BYTE bYkOperate; + YKYT_PARAM YkYtParam; + BUBAN104PORTPARAM *pPortParam; + char szbuf[128]; + + ykytpnt = 0; + ykytop = 3; + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + bYkOperate = rtumsg->MsgData[12]; + ykytpnt = rtumsg->MsgData[10] + (rtumsg->MsgData[11]<<8); + } + else + { + bYkOperate = rtumsg->MsgData[15]; + // wen 2005.11.27 修改最高字节信息体地址不做判断 + //ykytpnt = rtumsg->MsgData[12] + (rtumsg->MsgData[13]<<8) + (rtumsg->MsgData[14]<<16); + ykytpnt = rtumsg->MsgData[12] + (rtumsg->MsgData[13]<<8); + } + + if(rtumsg->MsgData[8] == 8) + { + step = STEP_YKYT_CANCEL; + } + else + { + if(bYkOperate & 0x80) //选择返校 + { + step = STEP_YKYT_SELECT; + } + else + { + step = STEP_YKYT_EXEC; + } + } + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d recv ykyt select.\n", _getpid(), commid); + } + + ykytpnt -= pPortParam->iYkBaseAddr; + ykytpnt += 1; + + if(rtumsg->MsgData[6] == 45) + { + // ykytop == 1 控合, == 2 控分 + ykytop = ((bYkOperate & 0x03) == 1) ? 1 : 2; + } + else if(rtumsg->MsgData[6] == 46) + { + ykytop = ((bYkOperate & 0x03) == 2) ? 1 : 2; + } + else // == 47 + { + //step = STEP_YKYT_CANCEL; + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + return; + } + + provpnt = FindProvPntFromYkYtPnt(commid, ykytpnt, pPortParam->m_psBaoHu); + if(provpnt < 0) // 控点号错 + { + sprintf(szbuf, "WARN(%04d): 控点错误.\n", _getpid()); + DebugPrint(szbuf); + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + } + else + { + diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr; + ykytcommid = diprovptr[provpnt].PortNo; + if(!SioParam[ykytcommid].m_psBaoHu) + { + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + return; + } + + if(!SioParam[ykytcommid].m_psBaoHu->DiPtr) + { + sprintf(szbuf, "WARN(%04d): 没有控点m_psBaoHu->DiPtr=NULL.\n", _getpid()); + DebugPrint(szbuf); + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + return; + } + + diptr = (DI_DEF *)SioParam[ykytcommid].m_psBaoHu->DiPtr; + + // 如果对应点没有控点或者控点不相等 + if(!diptr[diprovptr[provpnt].PntNo].CtrlEnable) + { + sprintf(szbuf, "WARN(%04d): 对应点没有控点或者控点不相等.\n", _getpid()); + DebugPrint(szbuf); + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + return; + } + + if(STEP_YKYT_SELECT == step) + { + if(STEP_YKYT_SELECT == SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtStep) + { + if(!ProvPortYkYtIsTimeOut(ykytcommid, &SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg)) + { + sprintf(szbuf, "WARN(%04d): 超时 failed.\n", _getpid()); + DebugPrint(szbuf); + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, 3, step); + return; + } + } + } + + SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvPntIdx = provpnt; + SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvPortIdx = commid; + SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx = ykytpnt; + SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtPointIdx = diptr[diprovptr[provpnt].PntNo].ControlNo; + SioParam[ykytcommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate = ykytop; + + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=成功, 0=失败) + //buf[0] = ykytcommid & 0xFF; + //buf[1] = (ykytcommid & 0xFF00) >> 8; + //buf[2] = (ykytcommid & 0xFF0000) >> 16; + //buf[3] = (ykytcommid & 0xFF000000) >> 24; + //buf[4] = diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF; + //buf[5] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF00) >> 8; + //buf[6] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF0000) >> 16; + //buf[7] = (diptr[diprovptr[provpnt].PntNo].ControlNo & 0xFF000000) >> 24; + //buf[8] = STEP_YKYT_SELECT; + //buf[9] = ykytop; + //SendYkYtCommand(ykytcommid, (char *)buf, 10); // 发送遥控遥调命令 + + YkYtParam.m_iYkYtOperate = ykytop; + YkYtParam.m_iYkYtPnt = diptr[diprovptr[provpnt].PntNo].ControlNo; + YkYtParam.m_iYkYtStep = step; + YkYtParam.m_iYkYtUpDown = YKYT_SEND_DOWN; + SendYkYtCommand2(ykytcommid, &YkYtParam); + + if(STEP_YKYT_EXEC == step) + { + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, ykytop, step); + MakeProvBuban104YkYtAckMsg(commid, ykytpnt, ykytop, STEP_YKYT_NOEXEC); + } + } +} + +void MakeProvBuban104YkYtAckMsg(int commid, int pnt, int op, int step) +{ + int iCount, ykpoint, iLen; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + memset(commandbuf, 0, sizeof(commandbuf)); + iCount = 4; + commandbuf[0] = 0x68; + commandbuf[1] = 14; + switch(pPortParam->YkMode) + { + case CONTROL_SINGAL: // 单点控制 + commandbuf[6] = 45; + break; + case CONTROL_DOUBLE: // 双点控制 + case CONTROL_DIRECT: // 直接控制 + commandbuf[6] = 46; // 47; + break; + } + commandbuf[7] = 1; + //commandbuf[8];// 传送原因 + + iLen = 9; + ykpoint = (pnt-1) + pPortParam->iYkBaseAddr; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = LOBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = HIBYTE(LOWORD(ykpoint)); + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = LOBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = HIBYTE(LOWORD(ykpoint)); + commandbuf[iLen++] = LOBYTE(HIWORD(ykpoint)); + } + + switch(step) + { + case STEP_YKYT_SELECT: // 选择 + commandbuf[8] = 7; + commandbuf[iLen] = 0xfc; + break; + + case STEP_YKYT_EXEC: // 执行 + commandbuf[8] = 7; + commandbuf[iLen] = 0x7c; + break; + + case STEP_YKYT_CANCEL: // 撤销 + commandbuf[8] = 9; + commandbuf[iLen] = 0xfc; + break; + + default:// 结束帧 + commandbuf[8] = 10; + commandbuf[iLen] = 0; + break; + } + + // DCS/RCS + switch(op) + { + case 1: // 选择合 + if(CONTROL_SINGAL == pPortParam->YkMode) + { + commandbuf[iLen] |= 1; + } + else + { + commandbuf[iLen] |= 2; + } + break; + case 2: // 选择分 + if(CONTROL_SINGAL != pPortParam->YkMode) + { + commandbuf[iLen] |= 1; + } + break; + case 3: // 选择失败 + default: + commandbuf[8] |= 0x40; + break; + } + + iLen++; + PutPollCmdToBuf(commid, INSERT_POLL_CMD, 0, (char *)commandbuf, iLen); + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d ykytpnt=%d, op=%d checked.\n", _getpid(), commid, pnt, op); + } +} + +void ProvBuban104SendClass1(int commid) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int j, iDataNum, iCmdType; + DI_DEF pntmsg; + PROV_DI_PNT *diprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(!pPortParam->m_psBaoHu->DiChange) + { + return; + } + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + // wen 2005.01.15 修改数据信息体起始地址 + dwStartAddr = pPortParam->iDiBaseAddr; + + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 1;//=3,为双点 + commandbuf[8] = 3; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + iLenth = 10; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + iLenth = 12; + } + diprovptr = (PROV_DI_PNT *)pPortParam->m_psBaoHu->DiPtr; + for(j = 0, iDataNum = 0; jm_psBaoHu->DiNum; j++) + { + if(diprovptr[j].ChangeFlag) + { + iDataNum++; + commandbuf[iLenth++] = LOBYTE(LOWORD(dwStartAddr+j)); + commandbuf[iLenth++] = HIBYTE(LOWORD(dwStartAddr+j)); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = LOBYTE(HIWORD(dwStartAddr+j)); + } + + GetPntMsg(diprovptr[j].PortNo, diprovptr[j].PntNo, + &pntmsg, DI_PNT_TYPE, PNT_STATUS); + diprovptr[j].ChangeFlag = FALSE; + commandbuf[iLenth++] = pntmsg.Status; + if(iLenth > 256) + { + break; + } + } + } + + if(j >= pPortParam->m_psBaoHu->DiNum) + { + pPortParam->m_psBaoHu->DiChange = FALSE; + } + + commandbuf[7] = (char)iDataNum; + commandbuf[1] = (char)(iLenth-2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); +} + +void ProvBuban104SendClass2(int commid) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + + BOOL bHaveData = FALSE; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int j, iDataNum, iCmdType; + AI_DEF pntmsg; + PROV_AI_PNT *aiprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(!pPortParam->m_psBaoHu->AiChange) + { + return; + } + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 21; + commandbuf[8] = 3; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + iLenth = 10; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + iLenth = 12; + } + + // wen 2005.01.15 修改数据信息体起始地址 + dwStartAddr = pPortParam->iAiBaseAddr; + commandbuf[6] = 21; + //遥测值 + aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr; + for(j = 0, iDataNum = 0; j < pPortParam->m_psBaoHu->AiNum; j++) + { + if(aiprovptr[j].ChangeFlag) + { + iDataNum++; + bHaveData = TRUE; + + commandbuf[iLenth++] = LOBYTE(LOWORD(dwStartAddr+j)); + commandbuf[iLenth++] = HIBYTE(LOWORD(dwStartAddr+j)); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = LOBYTE(HIWORD(dwStartAddr+j)); + } + + GetPntMsg(aiprovptr[j].PortNo, aiprovptr[j].PntNo, + &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aiprovptr[j].ChangeFlag = FALSE; + commandbuf[iLenth++] = (char)(pntmsg.RawValue); + commandbuf[iLenth++] = (char)((pntmsg.RawValue&0xff00)>>8); + + if(iLenth >= 251) + { + break; + } + } + } + + if(j >= pPortParam->m_psBaoHu->AiNum) + { + pPortParam->m_psBaoHu->AiChange = false; + } + + if(bHaveData) + { + commandbuf[7] = (char)iDataNum; + commandbuf[1] = (char)(iLenth-2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + } +} + +void ProvMakeBuban104Command(int commid, u_char cmdidx) +{ + int iLen; + char commandbuf[MAX_POLLCMD_BUF_LEN]; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + switch(cmdidx) + { + case ASK_SECOND_DATA: // 召唤2级数据 + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.03.23 支持浮点数遥测的传送 + //ProvBuban104SendClass2(commid); + //==================================================================== + if(pPortParam->m_bProvAiType == 13) + { + ProvBuban104SendClass2withFloat(commid); + } + else + { + ProvBuban104SendClass2(commid); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + break; + + case ASK_FIRST_DATA: // 召唤1级数据 + ProvBuban104SendClass1(commid); + break; + + case ASK_ALLDATA_END: // 总召唤结束帧 + commandbuf[0] = 0x68; + //commandbuf[iLen++] = 14; + iLen = 2; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 100; + commandbuf[iLen++] = 1; + commandbuf[iLen++] = 10; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + else + { + commandbuf[iLen++] = 0; + commandbuf[iLen++] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = HIBYTE(pPortParam->wLinkAddr); + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + commandbuf[iLen++] = 0; + } + commandbuf[iLen++] = 0x14; + commandbuf[1] = (BYTE)(iLen - 2); + if(pPortParam->ProvAckOrNot) + { + PutPollCmdToBuf(commid, NORMAL_POLL_CMD, 0, (char *)commandbuf, iLen); + } + else + { + PutPollCmdToBuf(commid, FAST_POLL_CMD, 0, (char *)commandbuf, iLen); + } + pPortParam->Initdata = TRUE; + break; + + case RTU_TIME: // 时间同步 + break; + + case ASK_DI_DATA: // 召唤2级数据YX + break; + + case ASK_AI_DATA: // 召唤2级数据YC + break; + + case ASK_PI_DATA: // 召唤2级数据YM + break; + + case ASK_PI: //召唤电度量 + break; + + case ASK_ALL_DATA: // 召唤初始化数据 + break; + } +} +/* +int j // 对应数据库数据点号 +int *igno // 组号 +int* iItemNo 条目号 +DAY_TIME* sCurTime 时间 +float* pfValue 数据值 +typedef struct +{ + WORD Year; + u_char Month; + u_char Day; + u_char WeekDay; + u_char MonthDay; + u_char Hour; + u_char Min; + u_char Sec; + u_char reserved; + WORD mSec; +} DAY_TIME; +返回值1:成功取值 -1:取值失败 +*/ +int GetAIPntMsg(int j, int *igno, int* iItemNo, DAY_TIME* sCurTime, float* pfValue) +{ + *igno = 1; + *iItemNo = 1; + sCurTime->Hour = 12; + sCurTime->Min = 30; + sCurTime->Month = 11; + sCurTime->MonthDay = 1; + sCurTime->mSec = 600; + sCurTime->Sec = 26; + sCurTime->Year = 2023; + *pfValue = 36.6; + return 1; +} + +void ProvBuban104SendAIwithFloat(int commid, RTUMSG *rtumsg, int iGroupNo) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int i, j, iAllDataCount, iSendNum,flag; + int iNo, iCmdType, igno,iItemNo; + float *pfValue; + DAY_TIME sCurTime; + AI_DEF pntmsg; + PROV_AI_PNT *aiprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + iCmdType = FAST_POLL_CMD; + + if( iGroupNo == 0 )//总召唤 + { + dwStartAddr = MAX_GROUP_AINUM*iGroupNo + pPortParam->iAiBaseAddr; + + iAllDataCount = pPortParam->m_psBaoHu->AiNum; + iCmdType = FAST_POLL_CMD; + } + + aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr; + for( i = 0; i < iAllDataCount; i++ ) + { + memset(commandbuf, 0, sizeof(commandbuf)); + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 10; // 类型标识TYP + commandbuf[7] = 0x81; // 可变结构限定词VSQ + commandbuf[8] = 0x2A; // 传送原因COT + commandbuf[9] = 0; // + commandbuf[10] = 0; // 应用服务数据单元公共地址 + commandbuf[11] = 254; // 功能类型FUN + commandbuf[12] = 241; // 信息序号INF + commandbuf[13] = 0; // 返回信息标识码RII + + //遥测值 + if(iAllDataCount > MAX_FLOATAINUM) + { + iSendNum = MAX_FLOATAINUM; + commandbuf[14] = (iSendNum & 0x80); // 通用分类数据集数目NGD + } + else + { + iSendNum = iAllDataCount; + commandbuf[14] = iSendNum; // 通用分类数据集数目NGD + } + + iNo = i; + iLenth = 15; + for( j = iNo; j < iNo+iSendNum; j++ ) + { + pfValue = (float *)&commandbuf[iLenth+14]; + flag = GetAIPntMsg(j, &igno, &iItemNo, &sCurTime, pfValue); + commandbuf[iLenth] = igno; + commandbuf[iLenth++] = iItemNo; + commandbuf[iLenth++] = 1; // 描述类别KOD(实际值) + commandbuf[iLenth++] = 7; // 数据类型 + commandbuf[iLenth++] = 4; // 数据宽度 + commandbuf[iLenth++] = 4; // 数据数目 + commandbuf[iLenth++] = sCurTime.mSec % 256; + commandbuf[iLenth++] = sCurTime.mSec / 256; + commandbuf[iLenth++] = (u_char)sCurTime.Min; + commandbuf[iLenth++] = (u_char)sCurTime.Hour; + commandbuf[iLenth++] = (u_char)sCurTime.Day; + commandbuf[iLenth++] = (u_char)sCurTime.Month; + commandbuf[iLenth++] = (u_char)(sCurTime.Year % 100); + iLenth += 12; + //*pfValue = SequenceHostToRtufloat((float)((int)pntmsg.RawValue)); + + //iLenth += sizeof(float); + //commandbuf[iLenth++] = 0; + } + + if (flag = -1) + i = iAllDataCount; + else + i += iSendNum; + commandbuf[1] = (char)(iLenth-2); + + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + } +} + +/*void ProvBuban104SendAIwithFloat(int commid, RTUMSG *rtumsg, int iGroupNo) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int i, j, iAllDataCount, iSendNum; + int iNo, iCmdType; + float *pfValue; + AI_DEF pntmsg; + PROV_AI_PNT *aiprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + if( iGroupNo == 0 )//总召唤 + { + dwStartAddr = MAX_GROUP_AINUM*iGroupNo + pPortParam->iAiBaseAddr; + + iAllDataCount = pPortParam->m_psBaoHu->AiNum; + iSendCount = (iAllDataCount+MAX_FLOATAINUM-1)/MAX_FLOATAINUM; + iCmdType = FAST_POLL_CMD; + } + else//分组召唤 + { + dwStartAddr = MAX_GROUP_AINUM*(iGroupNo-1); + iAllDataCount = pPortParam->m_psBaoHu->AiNum - dwStartAddr; + dwStartAddr += pPortParam->iAiBaseAddr; + + if(iAllDataCount > MAX_FLOATAINUM) + { + iSendCount = 2; + if((iAllDataCount - MAX_GROUP_AINUM) > 0) + { + iAllDataCount = MAX_GROUP_AINUM; + } + } + } + + aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr; + for( i = 0; i < iSendCount; i++ ) + { + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 13; + //commandbuf[8] = rtumsg->MsgData[15]; + commandbuf[8] = rtumsg->MsgData[8]; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + // 信息体地址为2个字节 + //*((DWORD*)(&commandbuf[12])) = dwStartAddr; + commandbuf[10] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[11] = HIBYTE(LOWORD(dwStartAddr)); + iLenth = 12; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + // 信息体地址为3个字节 + //*((DWORD*)(&commandbuf[12])) = dwStartAddr; + commandbuf[12] = LOBYTE(LOWORD(dwStartAddr)); + commandbuf[13] = HIBYTE(LOWORD(dwStartAddr)); + commandbuf[14] = LOBYTE(HIWORD(dwStartAddr)); + iLenth = 15; + } + + //遥测值 + if(iAllDataCount > MAX_FLOATAINUM) + { + iAllDataCount -= MAX_FLOATAINUM; + iSendNum = MAX_FLOATAINUM; + } + else + { + iSendNum = iAllDataCount; + } + + iNo = dwStartAddr - pPortParam->iAiBaseAddr; + for( j = 0; j < iSendNum; j++ ) + { + GetPntMsg(aiprovptr[iNo+j].PortNo, aiprovptr[iNo+j].PntNo, + &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aiprovptr[iNo+j].ChangeFlag = FALSE; + pfValue = (float *)&commandbuf[iLenth]; + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.07.13 修改负数的传送 + //*pfValue = SequenceHostToRtufloat((float)pntmsg.RawValue); + //============================================================ + *pfValue = SequenceHostToRtufloat((float)((int)pntmsg.RawValue)); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + iLenth += sizeof(float); + commandbuf[iLenth++] = 0; + } + + commandbuf[7] = (BYTE)j; + commandbuf[7] |= 0x80; + commandbuf[1] = (char)(iLenth-2); + + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + + dwStartAddr += MAX_FLOATAINUM; + } +} +*/ + +void ProvBuban104SendClass2withFloat(int commid) +{ + char commandbuf[MAX_POLLCMD_BUF_LEN]; + + BOOL bHaveData = FALSE; + DWORD dwStartAddr; + int iLenth, iSendCount=1; + int j, iDataNum, iCmdType; + float *pfValue; + AI_DEF pntmsg; + PROV_AI_PNT *aiprovptr; + BUBAN104PORTPARAM *pPortParam; + + pPortParam = (BUBAN104PORTPARAM *)SioParam[commid].ExtInfo; + + if(!pPortParam->m_psBaoHu->AiChange) + { + return; + } + + if(pPortParam->ProvAckOrNot) + { + iCmdType = NORMAL_POLL_CMD; + } + else + { + iCmdType = FAST_POLL_CMD; + } + + commandbuf[0] = 0x68; + commandbuf[2] = 0; + commandbuf[3] = 0; + commandbuf[4] = 0; + commandbuf[5] = 0; + commandbuf[6] = 21; + commandbuf[8] = 3; + if(VER_BUBAN_104 == pPortParam->RtuVersion) + { + commandbuf[9] = LOBYTE(pPortParam->wLinkAddr); + iLenth = 10; + } + else + { + commandbuf[9] = 0; + commandbuf[10] = LOBYTE(pPortParam->wLinkAddr); + commandbuf[11] = HIBYTE(pPortParam->wLinkAddr); + iLenth = 12; + } + + // wen 2005.01.15 修改数据信息体起始地址 + dwStartAddr = pPortParam->iAiBaseAddr; + commandbuf[6] = 13; + //遥测值 + aiprovptr = (PROV_AI_PNT *)pPortParam->m_psBaoHu->AiPtr; + for(j = 0, iDataNum = 0; j < pPortParam->m_psBaoHu->AiNum; j++) + { + if(aiprovptr[j].ChangeFlag) + { + iDataNum++; + bHaveData = TRUE; + + commandbuf[iLenth++] = LOBYTE(LOWORD(dwStartAddr+j)); + commandbuf[iLenth++] = HIBYTE(LOWORD(dwStartAddr+j)); + if(VER_IEC870_5_104 == pPortParam->RtuVersion) + { + commandbuf[iLenth++] = LOBYTE(HIWORD(dwStartAddr+j)); + } + + GetPntMsg(aiprovptr[j].PortNo, aiprovptr[j].PntNo, + &pntmsg, AI_PNT_TYPE, PNT_RAWVALUE); + aiprovptr[j].ChangeFlag = FALSE; + + pfValue = (float *)&commandbuf[iLenth]; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.07.13 修改负数的传送 + //*pfValue = SequenceHostToRtufloat((float)pntmsg.RawValue); + //============================================================ + *pfValue = SequenceHostToRtufloat((float)((int)pntmsg.RawValue)); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + iLenth += sizeof(float); + commandbuf[iLenth++] = 0; + + //4.bug_1.2.3_20060807_3/bug_2.0.1_20060807_4 104规约不能转发第二个端口的遥测数据 + //不能操作251(原来使用255可能导致发送报文长度超过255,一个字节不能表述) + //另外命令缓冲区应当使用char而不应当使用u_char + if(iLenth >= 251) + { + break; + } + } + } + + if(j >= pPortParam->m_psBaoHu->AiNum) + { + pPortParam->m_psBaoHu->AiChange = false; + } + + if(bHaveData) + { + commandbuf[7] = (char)iDataNum; + commandbuf[1] = (char)(iLenth-2); + PutPollCmdToBuf(commid, iCmdType, 0, (char *)commandbuf, iLenth); + } +} +//===========================转发数据处理结束===============================// + +//===========================数据处理函数结束===============================// \ No newline at end of file diff --git a/buban104.h b/buban104.h new file mode 100644 index 0000000..316291c --- /dev/null +++ b/buban104.h @@ -0,0 +1,291 @@ +/************************************************************************************ + * + * Copyright (C) 2004-2005 SCADA Control Technology Co., Ltd. + * All rights reserved. + * + * 文件名称:buban104.h + * 文件标识:部颁104规约 + * 摘 要:104规约的处理的结构、宏还有函数定义 + * + * 当前版本:1.0 + * 作 者:aaawen + * 完成日期:2005/09/14 + * + * 取代版本:1.0 + * 原作者 : + * 完成日期: + * + * 说 明:数据定义规则 + * u8 --- BYTE(usigned char) + * ch --- char + * w --- WORD(u_short, usigned short) + * sh --- short + * b --- BOOL(bool) + * i --- int + * l --- long + * u32 --- u_32 + * ui --- unsigned int(u_int) + * ul --- unsigned long(u_long) + * f --- float + * db --- double + * c --- class + * s --- struct + * sta --- static + * g --- 全局变量 + * Array --- 数组 + * a --- 数组 + * m_ --- 数据成员 + * p --- 指针 + * str --- 字符串 + * 全部大写 --- 常量 + * 首字节必须大写--- 类名称,结构,函数 + **************************************************************************************/ +// buban104.h: interface for the buban104 class. +// +////////////////////////////////////////////////////////////////////// +#if !defined(_BUBAN104_H_200509141152__INCLUDED_) +#define _BUBAN104_H_200509141152__INCLUDED_ +#ifdef OS_LINUX +#include "baohulib/common.h" +#else +#include "common.h" +#endif + +////////////////////////////////////////////////////////////////////////// +// 宏定义 // +// WEN 2005.09.08 // +////////////////////////////////////////////////////////////////////////// +#define MAX_104_PINUM 30 + +#define FORMAT_I 14 // I-格式 +#define FORMAT_S 15 // S-格式 +#define FORMAT_U_START_ACT 16 // U-格式启动 +#define FORMAT_U_START_CON 17 // U-格式启动应答 +#define FORMAT_U_STOP_ACT 18 // U-格式停止 +#define FORMAT_U_STOP_CON 19 // U-格式停止应答 +#define FORMAT_U_TEST_ACT 20 // U-格式测试 +#define FORMAT_U_TEST_CON 21 // U-格式测试应答 + +// 定时召唤命令及命令名称 +#define BUBAN104_TIMER_CMD_NUM 3 // 最大命令数目 +#define MAX_SEQUENCE 0x7fff // 最大帧计数 + +#define MAX_FRAMEMATCHING_SIZE 2 // 帧序匹配最大尺寸 + +// 规约版本号 +#define VER_BUBAN_104 0 // 部颁104 +#define VER_IEC870_5_104 1 // IEC104 +/////////////////////////////结构定义///////////////////////////////// +typedef struct +{ + long CmdTimerCnt; + long CmdTimerConst; +} BUBAN104CMDDEF; + +typedef struct tagBUBAN104PORTPARAM +{ + BOOL LinkOk; // 主站初始化标志 1:ok; 0:no 初始化时:FALSE + BOOL Initdata; // 初始化总召唤标志 TRUE:收到总召唤结束帧 + // FALSE:未收到总召唤结束帧 + // 召唤电度标志 TRUE:收到召唤结束帧 + // FALSE:未收到召唤结束帧 + WORD wLinkAddr; // 地址域 + + WORD wSendSequence; // 发送帧计数 + WORD wRecvSequence; // 接收帧计数 + WORD wAckSequence; // 应答帧计数 + BOOL bAckRight; // 应答帧是否同步 (子站端有效) + BOOL bStopComm; // 通讯停止 + + BOOL bSendFormatI; + BYTE ProvAckOrNot; // 转发是否要求应答 + + long lTimeOutSendTest;// 超时发送测试帧 + long lTimeOutConst; // 超时时间间隔 + long lTimeOutCnt; // 超时时间计数 + long lYkYtAckTimeConst;// 返校超时时间间隔 + long lYkYtAckTime; // 返校超时时间计数 + BOOL bCloseSocket; // 关闭socket端口 + char YkCmdBuf[32]; // 遥控延迟发送返校缓冲区 + long lYkCmdBuflen; // 遥控延迟发送返校缓冲区数据长 + + long m_lNoDataCnt; // 无数据时间,超过超时时间发送测试帧 + + short RtuVersion; // 版本号 + int m_iPublishYear; // 发布时间(缺省为2000版) + + short CurCmdIdx; + short YkMode; // 遥控方式(=0:双点遥控,=1:单点遥控,=2:直控方式) + + // wen 2005.01.15 修改数据信息体起始地址 + int iAiBaseAddr; // 遥测起始地址 + int iDiBaseAddr; // 遥信起始地址 + int iPiBaseAddr; // 遥脉起始地址 + int iYkBaseAddr; // 遥控起始地址 + + BYTE m_au8RecvBuf[300]; + int m_iRecvLen; + + int m_iFrameSize; // 帧序应答尺寸 + + BYTE m_bProvAiType; // 转发遥测类型标识 + + BUBAN104CMDDEF CmdTime[BUBAN104_TIMER_CMD_NUM]; + + SIO_PARAM_BAOHU_DEF *m_psBaoHu; // 该规约的端口数据指针 +} BUBAN104PORTPARAM, *pBUBAN104PORTPARAM; + +/////////////////////////以下为通用函数接口/////////////////////////// +/*! + \brief 读取配置函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban104ReadConfig(int commid); // 初始化处理 +/*! + \brief 读取端口数据函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void Buban104RecvData(int commid, u_char *buf, int len);// 规约读数据处理 +/*! + \brief 规约数据处理定时器函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban104Timer(int commid); // 定时器处理 +/*! + \brief 遥控遥调数据处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void Buban104YkYtProcess(int commid, u_char *buf, int len); // 遥控遥调处理 +/*! + \brief 系统下发对时函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban104SendSystemTime(int commid); // 系统对时 +/*! + \brief 系统退出时规约处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban104Exit(int commid); // 规约退出 +/*! + \brief 保护命令处理函数 + \param commid -- 端口号 + \param rtumsg -- 下发的保护命令指针 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void Buban104BaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData); +/*! + \brief 取保护数据库指针函数 + \param commid -- 端口号 + \param iProvAddr -- 统一编排的保护转发地址 + \param ppBaoHuDB -- 存放保护数据指针的指针 + \retval -- 返回该装置保护数据组数 + */ +int Buban104GetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB); +/////////////////////////通用函数接口结束/////////////////////////////// + +/////////////////////////buban104公共函数接口/////////////////////////// +//指令缓冲区初始化 +void InitBuban104CommandBuffer(int commid); +//关闭socket通讯 +void Buban104CloseSocket(u_32 commid); +/////////////////////////buban104公共函数接口结束/////////////////////// + +/////////////////////////以下为通用函数支持接口///////////////////////// +void Buban104ProvMakeYkYtCommand(int commid, u_char *buf, int len); +/////////////////////////通用函数支持接口结束/////////////////////////// + +///////////////////////////以下为指令生成函数/////////////////////////// +//生成 Buban104 命令? +void MakeBuban104Command(u_32 commid, u_char cmdidx); +//生成遥控遥调指令 +void MakeBuBan104YkYtCommand(u_32 commid, u_char *buf, int len); +///////////////////////////指令生成函数结束///////////////////////////// + +/////////////////////以下为POLLING规约常规函数接口////////////////////// +void Buban104FindNextCmd(int commid); +void Buban104FindNextProvCmd(int commid); +void Buban104SendCmdFormPollCmdBuf(int commid); +//////////////////////POLLING规约常规函数接口结束/////////////////////// + +///////////////////////以下为规约处理函数接口/////////////////////////// +//======================以下为主站数据处理============================ +void Buban104ProcessData(u_32 commid, BUBAN104PORTPARAM *psPortParam, BOOL bProcess); +//处理数据格式I +void Buban104FormatI(RTUMSG *rtumsg); +//处理数据格式U +void Buban104FormatU(RTUMSG *rtumsg); + +//Buban104 初始化数据处理 +void Buban104InitdataProecss(RTUMSG * rtumsg); +//电度结束帧 +void Buban104PidataEnd(RTUMSG * rtumsg); +//设定确认 +void Buban104SetAck(RTUMSG *rtumsg); +//Buban104 遥控遥调返校程序 +void Buban104YkYtAck(RTUMSG * rtumsg); +//Buban104 对时程序 +void Buban104SynTime(RTUMSG * rtumsg); + +// 子站主动传送遥信变位帧 +void Buban104AutoSendDiProcess(RTUMSG *rtumsg); + +void Buban104AiWithPzDataProcess(RTUMSG *, int); +void Buban104AllAiDataProcess(RTUMSG *rtumsg); +void Buban104AllFloatAiDataProcess(RTUMSG *rtumsg); +void Buban104DiDataProcess(RTUMSG *rtumsg, int); +void Buban104SoeDataProcess(RTUMSG *rtumsg, int); +void Buban104PiDataProcess(RTUMSG * rtumsg); +void Buban104PiWithTimeDataProcess(RTUMSG *rtumsg); + +//保护数据处理 +void Buban104BaoHuDataProcess(RTUMSG *rtumsg); +void Buban104DefaultBaoHuDataProcess(RTUMSG *rtumsg); + +// 新增函数,含有 7 BYTE 的时标 +void Buban104SoeDataProcessWithCP56Time2a(RTUMSG *rtumsg, int flag); +void Buban104AiWithDataProcessWithM_ME_TD_1(RTUMSG * rtumsg); +void Buban104AiWithDataProcessWithM_ME_TE_1(RTUMSG * rtumsg); +void Buban104AiWithDataProcessWithM_ME_TF_1(RTUMSG * rtumsg); +void Buban104PiWithTimeDataProcessWithM_IT_TB_1(RTUMSG *rtumsg); + +//======================以下为子站数据处理============================ +void ProvBuban104dataProcess(int commid, RTUMSG *rtumsg); +void ProvBuban104FormatI(int commid, RTUMSG *rtumsg); +void ProvBuban104FormatU(int commid, RTUMSG *rtumsg); +void ProvBuban104FormatS(int commid, RTUMSG *rtumsg); +void ProvBuban104SendAllData(int commid, RTUMSG *rtumsg); +void ProvBuban104SendPIData(int commid, RTUMSG *rtumsg); +void ProvBuban104ProcessTime(int commid, RTUMSG *rtumsg); +//iGroupNo=0为响应总召唤 +void ProvBuban104SendPI(int commid, RTUMSG *rtumsg, int iGroupNo); +void ProvBuban104SendAI(int commid, RTUMSG *rtumsg, int iGroupNo); +void ProvBuban104SendDI(int commid, RTUMSG *rtumsg, int iGroupNo); +void ProvBuban104SendSoe(int commid); +void ProvBuban104YkYtData(int commid, RTUMSG *rtumsg); +void MakeProvBuban104YkYtAckMsg(int commid, int pnt, int op, int step); + +void ProvBuban104SendClass1(int commid); +void ProvBuban104SendClass2(int commid); +void ProvMakeBuban104Command(int commid, u_char cmdidx); + +void ProvBuban104SendAIwithFloat(int commid, RTUMSG *rtumsg, int iGroupNo); +void ProvBuban104SendClass2withFloat(int commid); +/////////////////////////规约处理函数接口结束/////////////////////////// +#endif // !defined(_BUBAN104_H_200509141152__INCLUDED_) diff --git a/chainlist.cpp b/chainlist.cpp new file mode 100644 index 0000000..1e4325b --- /dev/null +++ b/chainlist.cpp @@ -0,0 +1,174 @@ +//*************************************************************** +//* chainlist.cpp * +//* aaawen 2005.05.27 * +//*************************************************************** +//#ifdef OS_WINDOWS +#include +#include +//#endif +#include +#include +#include "chainlist.h" +#include "basefunc.h" +#include "os_heap.h" + +// SingleList +void SingleListInit(SINGLELIST *psSingleList, int iMaxNum) +{ + psSingleList->iDevId = 0; + psSingleList->iMaxNum = iMaxNum; + psSingleList->iNum = 0; + psSingleList->pHead = NULL; + psSingleList->pTail = NULL; +} + +void SingleListInitEx(SINGLELIST *psSingleList, int iMaxNum, int iDevId) +{ + psSingleList->iDevId = iDevId; + psSingleList->iMaxNum = iMaxNum; + psSingleList->iNum = 0; + psSingleList->pHead = NULL; + psSingleList->pTail = NULL; +} + +int SingleListHaveData(SINGLELIST *psSingleList) +{ + return psSingleList->iNum; +} + +BOOL SingleListAddData(SINGLELIST *psSingleList, BYTE *pu8Data, int iDataLen) +{ + char szDbg[128]; + SINGLELISTUNIT *pUnit; + + if(psSingleList->iNum >= psSingleList->iMaxNum) + { + sprintf(szDbg, "WARN(%04d): DevId=%08x SingleListAddData is Overflow.\n", + _getpid(), psSingleList->iDevId); + DebugPrint(szDbg); + return FALSE; + } + + pUnit = (SINGLELISTUNIT *)HEAP_MALLOC(sizeof(SINGLELISTUNIT)); + if(pUnit == NULL) + { + sprintf(szDbg, "WARN(%04d): DevId=%08x SingleListAddData malloc(%d) is failed in unit.\n", + _getpid(), psSingleList->iDevId, sizeof(SINGLELISTUNIT)); + DebugPrint(szDbg); + return FALSE; + } + + pUnit->pNext = NULL; + pUnit->pBuf = (BYTE *)HEAP_MALLOC(iDataLen+1); + if(pUnit->pBuf == NULL) + { + HEAP_FREE(pUnit); + sprintf(szDbg, "WARN(%04d): DevId=%08x SingleListAddData malloc(%d) is failed in content.\n", + _getpid(), psSingleList->iDevId, iDataLen+1); + DebugPrint(szDbg); + return FALSE; + } + pUnit->iLen = iDataLen; + memcpy(pUnit->pBuf, pu8Data, iDataLen); + + if(psSingleList->pTail == NULL) + { + psSingleList->pTail = pUnit; + } + else + { + psSingleList->pTail->pNext = pUnit; + psSingleList->pTail = pUnit; + } + + if(psSingleList->pHead == NULL) + { + psSingleList->pHead = pUnit; + } + + psSingleList->iNum++; + + return TRUE; +} + +int SingleListGetAndDelData(SINGLELIST *psSingleList, BYTE *pu8Data, int iMaxLen) +{ + int iDataLen; + SINGLELISTUNIT *pUnit; + + if(psSingleList->pHead == NULL) + { + return 0; + } + + pUnit = psSingleList->pHead; + + psSingleList->iNum--; + if(psSingleList->iNum <= 0) + { + psSingleList->iNum = 0; + psSingleList->pHead = NULL; + psSingleList->pTail = NULL; + } + else + { + psSingleList->pHead = pUnit->pNext; + } + + if(pUnit->iLen > iMaxLen) + { + iDataLen = iMaxLen; + } + else + { + iDataLen = pUnit->iLen; + } + memcpy(pu8Data, pUnit->pBuf, iDataLen); + + HEAP_FREE(pUnit->pBuf); + HEAP_FREE(pUnit); + + return iDataLen; +} + +BOOL SingleListDelData(SINGLELIST *psSingleList) +{ + SINGLELISTUNIT *pUnit; + + if(psSingleList->pHead == NULL) + { + return FALSE; + } + + pUnit = psSingleList->pHead; + + psSingleList->iNum--; + if(psSingleList->iNum <= 0) + { + psSingleList->iNum = 0; + psSingleList->pHead = NULL; + psSingleList->pTail = NULL; + } + else + { + psSingleList->pHead = pUnit->pNext; + } + + HEAP_FREE(pUnit->pBuf); + HEAP_FREE(pUnit); + + return TRUE; +} + +BOOL SingleListDelAllData(SINGLELIST *psSingleList) +{ + while(1) + { + if(SingleListDelData(psSingleList) == FALSE) + { + break; + } + } + + return TRUE; +} diff --git a/chainlist.h b/chainlist.h new file mode 100644 index 0000000..5959435 --- /dev/null +++ b/chainlist.h @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////// +#if !defined(_CHAINLIST_H_AAAWEN_200505271056__INCLUDED_) +#define _CHAINLIST_H_AAAWEN_200505271056__INCLUDED_ + +#include "basetype.h" + +// 单向链表 +typedef struct tagSINGLELISTUNIT +{ + int iLen; // 数据长度 + BYTE *pBuf; // 存储内容 + struct tagSINGLELISTUNIT *pNext; // 单项链表的下一个 +}SINGLELISTUNIT; + +typedef struct tagSINGLELIST +{ + int iDevId; // 端口号(高2个字节为端口号, 低2个字节为装置号) + int iNum; + int iMaxNum; + SINGLELISTUNIT *pHead; + SINGLELISTUNIT *pTail; +}SINGLELIST; + +typedef struct tagDOUBLELISTUNIT +{ + int iDataLen; // 数据长度 + BYTE *pDataBuf; // 存储内容 + struct tagDOUBLELISTUNIT *pNext; // 双向链表的下一个 + struct tagDOUBLELISTUNIT *pFore; // 双向链表的前一个 +}DOUBLELISTUNIT; + +typedef struct tagDOUBLELIST +{ + int iNum; + int iMaxNum; + DOUBLELISTUNIT *pHead; + DOUBLELISTUNIT *pTail; +}DOUBLELIST; + +// SingleList +DSLIB_API void SingleListInit(SINGLELIST *psSingleList, int iMaxNum); +DSLIB_API void SingleListInitEx(SINGLELIST *psSingleList, int iMaxNum, int iDevId); +DSLIB_API int SingleListHaveData(SINGLELIST *psSingleList); +DSLIB_API BOOL SingleListAddData(SINGLELIST *psSingleList, BYTE *pu8Data, int iDataLen); +DSLIB_API int SingleListGetAndDelData(SINGLELIST *psSingleList, BYTE *pu8Data, int iMaxLen); +DSLIB_API BOOL SingleListDelData(SINGLELIST *psSingleList); +DSLIB_API BOOL SingleListDelAllData(SINGLELIST *psSingleList); + +#endif // !defined(_CHAINLIST_H_AAAWEN_200505271056__INCLUDED_) diff --git a/common.h b/common.h new file mode 100644 index 0000000..679bf5c --- /dev/null +++ b/common.h @@ -0,0 +1,1221 @@ +/**************************************************************************** + * FileName : Common.h * + * Programmer : Li Liangchu * + * Writen at : 2002.09.20 * + * Version : * + * Description: header of the nport.c * + * Last modify: 2002.11.6 * + ****************************************************************************/ + +#ifndef __COMMON_H_ICL__ +#define __COMMON_H_ICL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "menu.h" + +// 基本函数库 +#include "basefunc.h" +#include "DSFileSystem.h" +#include "chainlist.h" +#include "os_heap.h" +#include "basetype.h" +#include "confrw.h" + +#define OPEN 0 +#define CLOSE 1 + +// wen 2005.04.12 定义输出信息格式 +/* !输出信息级别为提示信息 +*/ +#define MSG_CLASS_TIP 1 +/* !输出信息级别为警告信息 +*/ +#define MSG_CLASS_WARN 2 +/* !输出信息级别为错误信息 +*/ +#define MSG_CLASS_ERROR 3 + +/*! + * 端口读标识 +*/ +#define FLAG_READ 0x0001 + +/*! + * 端口写标识 +*/ +#define FLAG_WRITE 0x0002 + +/*! + * 端口读标识 +*/ +#define FLAG_OPEN (FLAG_READ | FLAG_WRITE) +#define OPEN_PORT 3 // 端口处于完全打开状态 +#define CLOSE_PORT 0 // 端口处于关闭状态 +// 网络端口创建标识FAIL_GREATE、SUCCEED_GREATE、SOCKET_BEING +#define FAIL_GREATE 0 // 创建socket失败 +#define SUCCEED_GREATE 1 // 创建socket成功 +#define SOCKET_BEING 2 // socket已经存在,无需重新创建 + + +#define AI_DATA_DISP 4 +#define DI_DATA_DISP 5 +#define PI_DATA_DISP 6 + +#define WATCH_DATA_DISP 8 + + +typedef u_char BYTE; +typedef u_short WORD; +typedef u_long DWORD; + + +#define BYTE3(a) (((a)&0xff)<<24) +#define BYTE2(a) (((a)&0xff)<<16) +#define BYTE1(a) (((a)&0xff)<<8) +#define BYTE0(a) ((a)&0xff) + +#define ExchWord(a) (HIBYTE(a) | (LOBYTE(a)<<8)) +#define ExchDWord(a) (ExchWord(HIWORD(a)) | (ExchWord(LOWORD(a))<<16)) +#define BcdByteToInt( c ) (((c&0xf0) >> 4)*10 + (c&0x0f)) +#define IntToBcdByte( c ) ((c/10)*16 + (c%10)) +#define HexDigitToChar( c ) (((c) >= 10) ? ((c)-10+'A') : ((c)+'0')) +#define HexCharToInt( c ) \ + ( ((c) >= '0') && ((c) <= '9') ? (c) - '0' : \ + ((c) >= 'a') && ((c) <= 'f') ? (c) - 'a' + 10 : \ + ((c) >= 'A') && ((c) <= 'F') ? (c) - 'A' + 10 : 0 ) + +#define INC_TOTAL_MSG( port ) (SioParam[port].MsgNum++) +#define INC_Lost_SYNC_CNT( port ) (SioParam[port].LostSyncCnt++) +#define INC_ERROR_MSG( port ) \ + do { \ + SioParam[port].ErrMsgNum++; \ + SioParam[port].MsgNum++; \ + } while ( 0 ) + + +//基本宏定义 +#define DEFAULT_UDP_COMM_PORT 0xff00 + +//定义用于读写EEPROM的PB6、PB7地址 +#define SUCC 1 +#define FAIL 0 + +#define MAX_NET_BUF_SIZE (80*1024) +#define MAX_MSG_BUF_SIZE 81920 + +#define NET_MAC_LEN 6 + +#define DEFAULT_MAX_SERIAL_PORT_NUM 16 +#define DEFAULT_MAX_NET_PORT_NUM 8 +#define DEFAULT_MAX_PORT_NUM (DEFAULT_MAX_SERIAL_PORT_NUM+DEFAULT_MAX_NET_PORT_NUM) + +#define MAX_DEV_NUM 16 + +#define MAX_PROV_PORT_NUM 16 + +#define MAX_NET_NUM 3 + +#define DEFAULT_BAUD 9600 + +//1、设备配置初始化类 +#define SDS_GET_IP_ADDR 0x101 +#define SDS_N_GET_IP_ADDR 0x102 +#define SDS_SET_IP_ADDR 0x103 + +#define SDS_GET_NET_MAC_CODE 0x109 +#define SDS_SET_NET_MAC_CODE 0x110 + +#define SDS_SIO_RECV_DATA 0x141 +#define SDS_SIO_SEND_DATA 0x142 + +#define SDS_SIO_SET_WATCH_PORT 0x161 +#define SDS_SIO_CLR_WATCH_PORT 0x162 + +//7、保护机信息类 +#define SDS_SIO_GET_PROTOCOL_NAME 0x201 // 读所有协议名称 +#define SDS_SIO_GET_PORT_CONFIG_INFO 0x203 // 读端口公共配置信息 +#define SDS_SIO_GET_PROTOCOL_CONFIG_INFO 0x204 // 根据协议号读协议配置信息 + +// 与接收数据有关项目 +#define SDS_SIO_GET_STAT_INFO 0x211 // 读所有端口统计信息 +#define SDS_SIO_CLR_STAT_INFO 0x212 // 端口统计信息清零 +#define SDS_SIO_GET_AI_DATA_INFO 0x213 // 读端口遥测 +#define SDS_SIO_GET_DI_DATA_INFO 0x214 // 读端口遥信 +#define SDS_SIO_GET_PI_DATA_INFO 0x215 // 读端口电度 + +#define SDS_SIO_GET_CONFIG_FILE 0x221 // 读portconfig.ini 文件 +#define SDS_SIO_SET_CONFIG_FILE 0x222 // 写portconfig.ini 文件 + +#define SDS_SIO_SET_SYSTEM_TIME 0x231 // 系统对时 + +#define SDS_SIO_RESET 0x255 // 读端口电度 + +#define MAX_MAP_REG_NUM 8 + +#define NO_HANDSHAKE_MODE 0x00 +#define HARDWARE_MODE 0x01 +#define SOFTWARE_MODE 0x02 + +#define RS232_COMM_MODE 0x00 +#define RS422_COMM_MODE 0x01 +#define RS485_COMM_MODE 0x02 + +#define RS485_INPUT 0 +#define RS485_OUTPUT 1 + +#define NO_COMM 0 +#define UDP_COMM 1 +#define TCP_S_COMM 2 +#define TCP_C_COMM 3 + +#define RECV_PROTOCOL 0 +#define PROV_PROTOCOL 1 +#define PROTOCOL_SLAVE PROV_PROTOCOL +#define PROTOCOL_MASTER RECV_PROTOCOL + +#define POLL_CMD_TYPE_NUM 3 +#define NORMAL_CMD_TYPE 0 +#define INSERAT_CMD_TYPE 1 +#define FAST_CMD_TYPE 2 + +//设定maskbit意义在于(&~maskbit)|bit确定位值 +// 数据位数 +#define BITMASK 0x03 +#define BIT5 0x00 +#define BIT6 0x01 +#define BIT7 0x02 +#define BIT8 0x03 + +// 停止位 +#define STOPMASK 0x0c +#define STOP1 0x04 +#define STOP2 0x08 +#define STOP15 0x0c + +// 校验位 +#define PARITYMASK 0xf0 +#define PARITYNONE 0x00 +#define PARITYODD 0x10 +#define PARITYEVE 0x20 +#define PARITYMRK 0x30 +#define PARITYSPC 0x40 + +// 流控制 +#define RTSMASK 0x01 +#define DTRMASK 0x02 +#define CTSMASK 0x04 + +#define PNT_ENABLE 0 // 点使能 +#define PNT_STATE 1 // 点状态 +#define PNT_RAWVALUE 3 // 点原值(遥测,电度) +#define PNT_POLAR 5 // 遥测点极性 +#define PNT_STATUS 6 // 遥信点状态 +#define PNT_CTRL_NO 7 // 遥信控点号 +#define PNT_PROV_MSG 10 // 转发信息 +#define PNT_SOE_TIME 20 // 遥信 SOE 时间 +#define PNT_ALL_MSG 21 // 读取点的所有信息 +#define PNT_SOE_TIME_EX 22 // 含有扩展信息的遥信SOE时间 + + +#define AI_PNT_TYPE 0 +#define DI_PNT_TYPE 1 +#define CN_PNT_TYPE 2 +//#define PI_PNT_TYPE 2 +#define PI_PNT_TYPE 3 +#define OD_PNT_TYPE 4 + +#define AO_PNT_TYPE 20 +#define DO_PNT_TYPE 21 + +/*! + \brief 保护模拟量类型 + */ +#define PROTECT_AI_PNT_TYPE 128 + +/*! + \brief 保护开关量类型 + */ +#define PROTECT_DI_PNT_TYPE 129 + +/*! + \brief 保护定值类型 + */ +#define PROTECT_FIX_PNT_TYPE 130 + +/*! + \brief 保护事件类型 + */ +#define PROTECT_EVENT_PNT_TYPE 131 + + +#define POLL_CMD_TYPE_CMD 3 +#define NORMAL_POLL_CMD 0 // 普通命令队列 +#define INSERT_POLL_CMD 1 // 插入命令队列 +#define FAST_POLL_CMD 2 // 快速命令队列 + +// TIMER_CNT, CREATE_CNT, LED_CNT必须能整除1000 +//#define TIMER_CNT 20 // Poll命令定时器时间 20 ms +#define TIMER_CNT 200 // Poll命令定时器时间 200 ms +#define DATA_PRO_CNT 10 // 定时器基本时间 10 ms +#define CREATE_CNT 100 // 100 ms +#define LED_CNT 250 // 250 ms + +#define BLK_SIZE 256 + +#define SYSTEM_TIME 300 // RTU 对时, 300秒一次 + +#define MAX_DISP_LINE 2048 + +#define MAX_PROV_SOE 128 + +#define STEP_YKYT_NOEXEC 0 // 无 操 作 +#define STEP_YKYT_SELECT 1 // 遥控选择 +#define STEP_YKYT_EXEC 2 // 遥控执行 +#define STEP_YKYT_CANCEL 3 // 遥控撤销 +#define STEP_YT_SELECT 4 // 遥调选择 +#define STEP_YT_EXEC 5 // 遥调执行 +#define STEP_YT_CANCEL 6 // 遥调撤销 +#define STEP_YKYT_DIRECT 7 // 直 控 +#define STEP_YKYT_STOP 8 // 遥调急停 + +// 数据类型 +/*! + 无效数据类型 +*/ +#define DT_NO 0 +/*! + 无符号整型数 +*/ +#define DT_UINT 1 +/*! + 整型数 +*/ +#define DT_INT 2 +/*! + 浮点数 +*/ +#define DT_FLOAT 3 +/*! + 字符串 +*/ +#define DT_STRING 4 +/*! + 二进制数据 +*/ +#define DT_BINARY 5 +/*! + 控制字 +*/ +#define DT_CONTROL 6 + +// 信息扩展数据至少扩展2个字节,其中第一字节指示数据类型, +// 第二字节根据不同数据类型有所不同。 +#define CHECK_NO 1 // 无校验,第二扩展字节无效,置0 +#define CHECK_WHOLE 2 // 总校验,第二扩展字节为校验错误数 +#define CHECK_GROUP 3 // 分组校验,第二扩展校验错误总数 + +#define DATATYPE_NO -1 +#define DATATYPE_AI 0 +#define DATATYPE_DI 1 +#define DATATYPE_OD 2 +#define DATATYPE_STRING 3 +#define DATATYPE_PI 4 + +// wen 2005.10.08 解决malloc分配内存不能释放的问题 +#define MIN_MALLOC_SIZE 200 // malloc分配内存的最小尺寸 +#define MAX_NO_WRITE_NUM 6000 // 网络最大不可写尺寸 +#define MAX_BUFUNIT_NUM 100 // 缓冲区单元最大数量 + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 增加fend功能的宏定义 +#define MAX_HOST 2 +#define MAX_FEND 2 +#define MAX_ADDR 2 +#define MAX_NET_BUF 16384 + +#define MMI_TYPE 0 +#define FEND_TYPE 1 +#define HOST_TYPE 2 + +#define TCPIP_ADDR_LEN 32 // TCP/IP 通讯地址最大长度 +#define MAX_MACHINE_NAME_LEN 48 // 计算机名最大长度 + +#define MAX_RTU_MSG_SIZE 8192 // RTU 信息包最大长度 + +#ifdef OS_LINUX +// 在linux下定义属性单字节对齐 +typedef int SOCKET; +#define INVALID_SOCKET (SOCKET)(~0) +#endif + +#define __attribute__(x) +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#define MAX_POLL_CMD_BUF_LEN 256 // 轮询指令缓冲区最大长度 + +enum Param_Type +{ + PARAM_NO=0, + PARAM_LINK, + PARAM_DEV, + PARAM_YC, + PARAM_YX, + PARAM_YM, + PARAM_YK, + PARAM_SYNCTIME, + PARAM_ASDU10 +}; + +#ifdef OS_WINDOWS + #pragma pack (push,1) +#else// OS_UNIX + #pragma pack(1) +#endif //OS_UNIX + +//SDS 包类型头 +typedef struct +{ + BYTE PortIdx; // 信息类型 + WORD MsgType; // 信息类型 + WORD MsgLen; // 信息长度 +} RTUMSGHEAD; + +//SDS包类型结构 +typedef struct +{ + BYTE PortIdx; // 信息类型 + WORD MsgType; // 信息类型 + WORD MsgLen; // 信息长度 + u_char MsgData[MAX_MSG_BUF_SIZE]; +} RTUMSG; + +//网络发包临时数据绶冲结构 +typedef struct +{ + int BufSize; + int MsgCnt; + int Front; + int Rear; + u_char MsgData[MAX_MSG_BUF_SIZE]; +} DATA_BUF; + +struct WR_DATA +{ +// u_short MsgType ; + u_short MsgLen; + u_char *MsgData; + int PLen; + struct WR_DATA *Next; +}; + +typedef struct +{ + WORD PortNo; + WORD PntNo; + u_char Enable; + u_char ChangeFlag; + float fFactor; + + // 模拟盘专用参数 + WORD wType; // 转发点类型 +} PROV_AI_PNT; + +typedef struct +{ + WORD PortNo; + WORD PntNo; + u_char Enable; + u_char ChangeFlag; + + u_char CtrlEnable; + short ControlNo; + + // 模拟盘专用参数 + WORD wType; // 转发点类型 +} PROV_DI_PNT; + +typedef PROV_AI_PNT PROV_PI_PNT; + +typedef struct +{ + WORD PortNo; + WORD PntNo; + u_char Enable; +} PROV_PNT; + +typedef struct +{ + BYTE Enable; + BYTE State; // 遥测状态 + + //WORD RawValue; // 遥测原值 + DWORD RawValue; // 遥测原值 + BYTE Polar; // 处理极性 + PROV_PNT Prov[MAX_PROV_PORT_NUM]; // 转发标志 +} AI_DEF; + +typedef struct +{ + BYTE Enable; + BYTE State; // 遥信状态 + + BYTE Status; // 遥信状态 + u_char CtrlEnable; + WORD ControlNo; + + DAY_TIME SoeTime; + + PROV_PNT Prov[MAX_PROV_PORT_NUM]; // 转发标志 +} DI_DEF; + +typedef struct +{ + BYTE Enable; + BYTE State; // 电度状态 + + u_long RawValue; // 电度原值 + + PROV_PNT Prov[MAX_PROV_PORT_NUM]; // 转发标志 +} PI_DEF; + +typedef struct +{ + int iPntNo; // SOE点号 + BYTE bStatus; // 状态值 + + // wen 2005.05.18 增加扩展字节处理(针对于103有效) + BYTE u8Type; // 103中表现为asdu号 + BYTE u8ProvFun; // 103转发中的FUN + BYTE u8ProvInf; // 103转发中的INF + WORD wRelativeTime; // 相对时间 + WORD wFaultNo; // 故障序号 + + DAY_TIME SoeTime; // SOE时间 + + // wen 2005.10.25 增加扩充字符串,用来解析保护事件中的故障参数 + char szMsgEx[64]; // 扩充字节数不得大于64字节 + +} SOE_DEF; + +typedef struct +{ + int iSoeNum; // soe数量 + int iFront; // 队列首指针 + int iRear; // 队列尾指针 + SOE_DEF *ptrProvSoe; // 端口soe数据缓冲区(最大=MAX_PROV_SOE)队列 +} PROV_SOE_DEF; + +#define YKYT_CMD_FROM_NO 0 // 没有数据来源 +#define YKYT_CMD_FROM_SCADA 1 // 来源于scada系统 +#define YKYT_CMD_FROM_PROVPORT 2 // 来源于转发端口 +// wen 2003.08.22 增加遥控遥调转发处理 +typedef struct +{ + int m_iProvPortIdx; // 转发厂站端口号 + int m_iProvPntIdx; // 转发厂站遥信点号 + int m_iProvYkYtPointIdx;// 转发厂站遥控遥调点号 + int m_iYkYtPointIdx; // 实际厂站遥控遥调点号 + + int m_iYkYtStep; // 遥控遥调转发步骤(无操作(=0)/选择(=1)/执行(=2)) + // 该结构成员是用来保存操作类型的(不仅仅针对转发遥控) + int m_iYkYtOperate; // 遥控遥调操作(控分、控合、失败) + int m_iYkYtMode; // 遥控遥调模式(仅对104有效) + + DAY_TIME m_sDayTime; // 遥控命令下发的时间 + int m_iTimeOut; // 转发遥控超时时间 + int m_iCmdFrom; // 指令来源(=0 无来源; =1 来源scada; =2 来源转发端口) +} PROV_YKYT_DEF; + +#define YKYT_SEND_UP 1 // +#define YKYT_SEND_DOWN 2 // + +typedef struct +{ + int m_iYkYtStep; // 遥控遥调执行步骤 + int m_iYkYtPnt; // 遥控遥调点 + int m_iYkYtOperate; // 遥控遥调操作状态(控分、控合、失败) + int m_iYkYtUpDown; // 上行命令还是下行命令(1=up, 0=down) +} YKYT_PARAM; + +typedef struct +{ + //******************** 串行端口信息 ************************ + DWORD Baud; // 波特率(cdt计算时间间隔) + + //**************** 数据收发缓冲区接收状态******************* + int m_iRevStatus; // 接收数据缓冲区状态 + int m_iNeedRevLength; // 还需要接收的数据长度 + + //******************** Poll Cmd **************************** + u_long Retry; // 重试命令次数 + u_long RetryCnt; // 重试命令计数 + u_long RetryTime; // 重试命令时间 + u_long RetryTimeCnt; // 重试命令时间计数 + u_long WaitTime; // 命令间隔时间 + u_long WaitTimeCnt; // 命令间隔时间计数 + + u_char ForceWaitFlag; // 强制等待标志 + u_short ForceWaitCnt; // 强制等待计数 + + u_char ReSendCmdFlag; // 重发命令标志 + u_char SendCmdFlag; // 命令发送标志 + u_char RevCmdFlag; // 命令正常接收标志 + + u_char LastGetCmdBuf; // 当前使用缓冲区 + DATA_BUF PollCmd[POLL_CMD_TYPE_NUM]; + + //******************* 端口数据库 *************************** + u_char PortType; // MAIN_PORT or SLAVE_PORT + u_char CheckTime; // 时间校正(=0, 不对时; =1, 上对时(接收); =2, 下对时(发送)) + + WORD AiNum; // 端口遥测数量 + WORD DiNum; // 端口遥信数量 + WORD PiNum; // 端口电度数量 + + void *AiPtr; // 遥测数据内存指针 + void *DiPtr; // 遥信数据内存指针 + void *PiPtr; // 电度数据内存指针 + + // wen 2004.11.16 数据转发时用 + u_char DiChange; // 遥信数据是否变化 + u_char AiChange; // 遥测数据是否变化 + // wen 2004.11.16 增加soe数据的转发存储 + PROV_SOE_DEF ProvSoeBuf; // 转发soe数据缓冲区 + PROV_YKYT_DEF ProvYkYtMsg; // 转发遥控信息缓冲区 +} SIO_PARAM_BAOHU_DEF; + +typedef struct +{ + //***************** 串行端口信息 ************************ + DWORD Baud; // 波特率 + u_char CommMode; // 数据位、校验和停止位 + u_char WorkMode; // 方式,RS323、422、485 + + int Rs485WaitCnt; // 485 切换等待计数 + + u_char ChipCheckOk; // 芯片检验标志 + u_char ChSelect; // 芯片型号 + u_char FreqSelect; // 芯片工作频率 + u_char WrRegMap[MAX_MAP_REG_NUM]; // 芯片寄存器映射 + + u_char HandshakeMode; // 通讯握手方式 + u_char XonChar1; // 软件握手ON字符1 + u_char XonChar2; // 软件握手ON字符2 + u_char XoffChar1; // 软件握手OFF字符1 + u_char XoffChar2; // 软件握手OFF字符2 + //********************************************************** +} SIO_PARAM_SERIAL_DEF; + +//串口相关所有参数集中定义 +typedef struct +{ + //******************** 端口基本信息 ************************ + u_char ProtocolIdx; // 规约索引,大于 0 + u_char ByPassFlag; // 旁路标志 + u_char OpenFlag; // 打开标志(该标识弃用,改在共享内存中) + u_char Status; // 端口状态,用来判断端口是否通讯正常 + // 在端口正常的1分钟后发送全数据, 避免数据未全部刷新导致的乱报警 + int iDelaySendAllData;// 全数据延迟传送 + int iForceSendFlag; // 强制下发标志 + + //******************** 网络端口信息 ************************ + u_char NetType; // UDP_COMM、TCP_S_COMM、TCO_C_COMM + DWORD NetPort; // 网络通讯端口 + u_long NetCommIpAddr; // 网络通讯地址 + int LiSock; // 侦听socket + int CommSock; // 通讯socket + //********************************************************** + + //******************** 数据收发缓冲区*********************** + DATA_BUF RecvBuf; // 接收数据缓冲区 + struct WR_DATA *WriteData; // 下行数据缓冲区 + + //******************** 统计信息 **************************** + u_long MsgNum; // 端口信息计数 + u_long LostSyncCnt; // 端口失步次数 + u_long ErrMsgNum; // 端口错误信息计数 + u_long RecvCharNum; // 端口在线时间统计 + u_long SendCharNum; // 端口离线时间统计 + u_long LineCommCnt; // 端口是否在线计数 + + //****************** 串行端口信息 ************************** + SIO_PARAM_SERIAL_DEF *m_psSerial; + //********************************************************** + + //******************* 保护信息 ***************************** + SIO_PARAM_BAOHU_DEF *m_psBaoHu; + //********************************************************** + + //******************** 用户扩展结构 ************************ + void *ExtInfo; + //********************************************************** +} SIO_PARAM_DEF; + +typedef struct +{ + u_long AllIpAddr[MAX_NET_NUM]; + u_long NetMaskIpAddr[MAX_NET_NUM]; + u_long BroadCastIpAddr[MAX_NET_NUM]; + u_long MainIpAddr[MAX_NET_NUM]; +} HOST_IP_ADDR; + +typedef struct +{ + WORD PortNumber; + SOCKET Socket; + + struct sockaddr_in Addr; + + u_char WaitFalg; +} UDP_SET_DEF; + +typedef struct +{ + int LineCnt; + int Front; + int Rear; + char Line[MAX_DISP_LINE][128]; +} DISP_LINE_BUF; + +typedef struct +{ + u_long IpAddr[MAX_NET_NUM]; + u_char NetNum; + u_long CurCommIp; + u_char IpAddrChangeFlag; + u_char NetCardMacCode[MAX_NET_NUM][NET_MAC_LEN]; + u_char ReadMacCodeFlag; + + u_char PortNum; + u_char SerialPortNum; + u_char NetPortNum; + + DISP_LINE_BUF WatchDispLine; +} DEV_DEF; + +// wen 2005.05.27 保护数据(保护模拟量、保护开关量、保护定值的存储结构) +/*! + \struct GROUPDATADEF + \brief 通用分类数据定义 + + \par 快速参考 + common.h + */ +typedef struct +{ + /*! + \var GROUPDATADEF::m_szName + \brief 信息点名称描述 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为64]\n + */ + char m_szName[66]; + + /*! + \var GROUPDATADEF::m_u32DataID + \brief 数据类型 + + \note + 取值范围:[DATAID_NO(0)---DATAID_SINGLE(10)]\n + 如果为DATAID_NO,则数据返回浮点数 + */ + u_32 m_u32DataID; + + /*! + \var GROUPDATADEF::m_fValue + \brief 信息点值 + + \note + 取值范围:浮点数取值范围\n + */ + float m_fValue; + + /*! + \var GROUPDATADEF::m_fMaxValue + \brief 信息点最大值 + + \note + 取值范围:浮点数取值范围\n + */ + float m_fMaxValue; + + /*! + \var GROUPDATADEF::m_fMinValue + \brief 信息点最小值 + + \note + 取值范围:浮点数取值范围\n + */ + float m_fMinValue; + + /*! + \var GROUPDATADEF::m_fStepValue + \brief 信息点步长值 + + \note + 取值范围:浮点数取值范围\n + */ + float m_fStepValue; + + /*! + \var GROUPDATADEF::m_szUnit + \brief 信息点量纲 + + \note + 取值范围:[有效的ASCII码字符串,最大长度为16]\n + */ + char m_szUnit[18]; + /*! + \var GROUPDATADEF::iFixDataType + \brief 信息点上送到protect的显示类型 + + \note + 取值范围:[0-255](类型(AI=1, DI=2))\n + */ + u_char iFixDataType; + +}GROUPDATADEF; + +/*! + \struct GROUPEVENTDEF + \brief 保护事件定义 + + \par 快速参考 + common.h + */ +typedef struct{ + /*! + \var GROUPEVENTDEF::m_iNewEventNo + \brief 最新事件序号 + + \note + 取值范围:[0--(BUF_EVENT_NUM-1)=15]\n + */ + i_32 m_iNewEventNo; + /*! + \var GROUPEVENTDEF::m_iNewEvents + \brief 最新事件数量 + + \note + 取值范围:[0--16]\n + */ + i_32 m_iNewEvents; + /*! + \var GROUPEVENTDEF::m_iAllEvents + \brief 缓冲事件数量 + + \note + 取值范围:[0--16]\n + */ + i_32 m_iAllEvents; + /*! + \var GROUPEVENTDEF::m_sTm[] + \brief 事件发生时间 + */ + //SYSTEMTIME m_sTm[BUF_EVENT_NUM]; + /*! + \var GROUPEVENTDEF::m_u8INF[] + \brief 事件信息序号 + */ +// BYTE m_u8INF[BUF_EVENT_NUM]; +}GROUPEVENTDEF; + +/*! + \struct GROUPDEF + \brief 通用分类数据组定义 + \note + 保护模拟量、保护开关量、保护定值通用存储结构 + + \par 快速参考 + common.h + */ +typedef struct{ + /*! + \var GROUPDEF::m_iGroupNo + \brief 通用分类数据组号 + + \note + 取值范围:[0--255]\n + */ + i_32 m_iGroupNo; + + /*! + \var GROUPDEF::m_iStartItemNo + \brief 通用分类数据起始条目号 + + \note + 取值范围:[0--255]\n + */ + i_32 m_iStartItemNo; + + /*! + \var GROUPDEF::m_iDataType + \brief 该组号数据对应的数据类型 + + \note + 取值范围:AI_PNT_TYPE(模拟量)\n + DI_PNT_TYPE(开关量)\n + PI_PNT_TYPE(电度量)\n + PROTECT_AI_PNT_TYPE(保护模拟量)\n + PROTECT_DI_PNT_TYPE(保护开关量)\n + PROTECT_FIX_PNT_TYPE(保护定 值)\n + PROTECT_EVENT_PNT_TYPE(保护事 件)\n + */ + i_32 m_iDataType; + + /*! + \var GROUPDEF::m_iStationNo + \brief 写入数据库中的厂站号 + + \note + 取值范围:[0--MAX_PORT_NUM,0为无效(缺省值)]\n + */ + i_32 m_iStationNo; + + /*! + \var GROUPDEF::m_iStartPntNo + \brief 写入数据库中的起始点号 + + \note + 取值范围:[0--(该类型点的最大点号-1)]\n + */ + i_32 m_iStartPntNo; + + /*! + \var GROUPDEF::m_u8NGD + \brief 组数据的NGD + + \note + 取值范围:[0--(该类型点的最大点号-1)]\n + */ + BYTE m_u8NGD; + + /*! + \var GROUPDEF::m_pu8DataType + \brief 保护定值数据类型指针 + + \note + 取值范围:无\n + */ + BYTE *m_pu8DataType; + + /*! + \var GROUPDEF::m_pu8DataLen + \brief 保护定值数据长度指针 + + \note + 取值范围:无\n + */ + BYTE *m_pu8DataLen; + + /*! + \var GROUPDEF::m_pu8GIN + \brief 保护定值数据条目号 + + \note + 取值范围:无\n + */ + BYTE *m_pu8GIN; + + /*! + \var GROUPDEF::m_u32CurPntNo + \brief 当前数据点号 + + \note + 取值范围:[1--255]\n + \note + 用于处理多帧通用分类数据时,确定该帧的数据起始点号 + */ + u_32 m_u32CurPntNo; + + /*! + \var GROUPDEF::m_iPntNum + \brief 数量 + + \note + 取值范围:无\n + \note + 用于遥控点和保护定值数据 + */ + i_32 m_iPntNum; + + /*! + \var GROUPDEF::m_bInit + \brief 保护定值数据长度 + + \note + 取值范围:无\n + */ + BOOL m_bInit; + + /*! + \var GROUPDEF::m_psDataInfo + \brief 组数据信息指针 + + \note + 取值范围:无\n + */ + GROUPDATADEF *m_psDataInfo; + + /*! + \var GROUPDEF::m_psEventInfo + \brief 组事件信息缓冲区指针 + + \note + 取值范围:非事件记录组,该指针为NULL\n + */ + GROUPEVENTDEF *m_psEventInfo; +}GROUPDEF; + +/*! + \struct DBINFO + \brief 测量值数据信息定义 + + \par 快速参考 + common.h + */ +typedef struct{ + /*! + \var DBINFO::m_u8Asdu + \brief 基本测量值的数据类型 + \note + 取值范围:[0--255)]\n + */ + u_char m_u8Asdu; // 数据类型 + + // wen 2006.05.20 修改为16位 + /*! + \var DBINFO::m_u8Fun + \brief 基本测量值的功能类型 + \note + 取值范围:[0--255)]\n + */ + WORD m_u8Fun; // 功能类型 + /*! + \var DBINFO::m_u8Inf + \brief 基本测量值的信息序号 + \note + 取值范围:[0--255]\n + */ + WORD m_u8Inf; // 信息序号 + + // 以下参数用作转发 + /*! + \var DBINFO::m_u8ProvFun + \brief 基本测量值的功能类型 + \note + 取值范围:[0--255)]\n + */ + BYTE m_u8ProvFun; + /*! + \var DBINFO::m_u8ProvInf + \brief 基本测量值的信息序号 + \note + 取值范围:[0--255]\n + */ + BYTE m_u8ProvInf; + /*! + \var DBINFO::m_u8LoopData + \brief 是否总召唤数据 + \note + 取值范围:[0--1]\n + */ + BYTE m_u8LoopData; +}DBINFO, *pDBINFO; + +/*! + \struct DBORIENTATION + \brief 测量值数据库定位结构 + + \par 快速参考 + common.h + */ +typedef struct +{ + /*! + \var DBORIENTATION::m_iStnNo + \brief 基本测量值在数据库中写入站号 + \note + 取值范围:[1--最大厂站号)]\n + */ + i_32 m_iStnNo; // 写入数据库站号 + + /*! + \var DBORIENTATION::m_iStartPntNo + \brief 基本测量值在数据库中起始点号 + \note + 数据类型为规约本身提供的测量值 + \note + 取值范围:[0--(最大遥测点号-1)]\n + */ + i_32 m_iStartPntNo; // 写入数据库起始点号 + + /*! + \var DBORIENTATION::m_iPntNum + \brief 基本测量值的数量 + \note + 取值范围:[0--255]\n + */ + i_32 m_iPntNum; // 数量 + + /*! + \var DBORIENTATION::m_psDataInfo + \brief 测量值数据信息指针 + */ + pDBINFO m_psDataInfo; +}DBORIENTATION; + +typedef struct tagDEVADDRPARAM +{ + /*! + \var DEVADDRPARAM::m_uchLinkAddr + \brief 链路地址 + */ + BYTE m_uchLinkAddr; + /*! + \var DEVADDRPARAM::m_uchCommAddr + \brief 公共地址 + */ + BYTE m_uchCommAddr; + /*! + \var DEVADDRPARAM::m_iLinkIdx + \brief 链路索引号 + */ + int m_iLinkIdx; + /*! + \var DEVADDRPARAM::m_iDevIdx + \brief 装置索引号 + */ + int m_iDevIdx; +}DEVADDRPARAM, *pDEVADDRPARAM; + +typedef struct tagCMDPARAM +{ + /*! + \var CMDPARAM::m_uchFun + \brief 指令参数功能号 + */ + BYTE m_uchFun; + /*! + \var CMDPARAM::m_uchInf + \brief 指令参数信息号 + */ + BYTE m_uchInf; + /*! + \var CMDPARAM::m_uchRII + \brief 返回值 + */ + BYTE m_uchRII; + /*! + \var CMDPARAM::m_sDevAddr + \brief 指令参数地址信息 + */ + DEVADDRPARAM m_sDevAddr; +}CMDPARAM, *pCMDPARAM; + +typedef struct tagBAOHUPROVPARAM +{ + /*! + \var BAOHUPROVPARAM::m_sProvStartTime + \brief 调度转发指令下发时间 + */ + DAY_TIME m_sBaoHuCmdStartTime; + /*! + \var BAOHUPROVPARAM::m_iBaoHuCommid + \brief 调度转发指令端口 + \note <0, 没有调度转发命令 + */ + int m_iBaoHuCommid; + /*! + \var BAOHUPROVPARAM::m_iBaoHuMsgType + \brief 调度指令类型 + \note <0, 没有调度转发命令 + */ + int m_iBaoHuMsgType; + /*! + \var BAOHUPROVPARAM::m_sProvRealAddrParam + \brief 调度转发指令时,实际装置的参数 + */ + DEVADDRPARAM m_sRealAddrParam; +}BAOHUPROVPARAM, *pBAOHUPROVPARAM; + +#define PROV_SOE_MAX 10 +/*! + \struct DEVPROVSOE + \brief 转发SOE数据结构 + + \par 快速参考 + common.h + */ +typedef struct +{ + /*! + \var DEVPROVSOE::m_sSoeData + \brief 转发SOE数据参数 + + \note + 用于转发事件 + */ + SOE_DEF m_sSoeData[PROV_SOE_MAX]; + + /*! + \var DEVPROVSOE::m_shSoeNum + \brief 转发SOE数据数目 + + \note + 用于转发事件 + */ + short m_shSoeNum; + + /*! + \var DEVPROVSOE::m_shFront + \brief 转发SOE数据头索引 + + \note + 用于转发事件 + */ + short m_shFront; + + /*! + \var DEVPROVSOE::m_shRear + \brief 转发SOE数据尾索引 + + \note + 用于转发事件 + */ + short m_shRear; +}DEVPROVSOE; + +// 所有规约的通用函数接口指针 +typedef const struct +{ + char *ProtocolName; // 规约名称 + char *Account; // 规约说明 + char **ProtocolInfo; // 规约信息指针 + void (*ReadConfig)( int ); // 初始化处理 + void (*RecvData)( int, u_char *, int ); // 规约读数据处理 + void (*Timer)( int ); // 定时器处理 + void (*YkYtProcess)( int, u_char *, int ); // 遥控遥调处理 + void (*SendSystemTime)( int ); // 系统对时 + void (*ProtocolExit)( int ); // 规约退出时处理 + // 以下函数指针仅仅针对保护规约有效 + void (*BaoHuCmdProcess)(int, RTUMSG *, BOOL); // 保护数据处理 + int (*GetBaohuDataBase)(int, int, GROUPDEF **); // 获取保护数据库 +}FUNCTION_CALL; + +#ifdef OS_WINDOWS + #pragma pack (pop) +#else// OS_UNIX + #pragma pack (0) +#endif //OS_UNIX +#endif \ No newline at end of file diff --git a/commport.cpp b/commport.cpp new file mode 100644 index 0000000..c58aa6d --- /dev/null +++ b/commport.cpp @@ -0,0 +1,4286 @@ +/***************************************************************************** + * FileName : commport.c * + * Programmer : Li Liangchu * + * Writen at : 2004.07.22 * + * Version : * + * Description: * + * Last modify: 2002.11.6 * + *****************************************************************************/ + +//#include "stdafx.h" +//#include "resource.h" +#include "commport.h" +#include "udpcomm.h" +#include "udpping.h" +#include "tcphost.h" +#include "netport.h" +#include +//#include "..\confrwlib\confrw.h" + +#define MAX_STRING_LEN 512 + +extern int CurPort; +extern int RealDataDispFlag; + +extern int iCurDevIdx; +extern DEV_DEF DevParam[]; + +extern UDP_SET_DEF UdpParam; +extern int RealDataDispFlag; + +FUNCTION_CALL *FunCallPtr; + +SIO_PARAM_DEF SioParam[DEFAULT_MAX_PORT_NUM]; + +int ProvPortCnt = 0; + +u_short UdpCommPort; + +u_short MaxSerialPortNum; +u_short MaxNetPortNum; +u_short MaxPortNum; + +void * pvconf_handle = NULL; +void * pvportconf_handle = NULL; +void * pvdataconf_handle = NULL; +char pvDataFileName[256]; + +char DeviceName[256]; +char Version[256]; +char VersionDate[256]; +char Manufacturer[256]; +char IniFilePath[256]; + +DAY_TIME DayTime; + +u_long GetPrivateProString(const char *section, const char *entry, const char *defaultstr, char *result, int len, char *inifile) +{ + int ret = SUCCESS; + char szConfig[256], szPortConfig[256]; + + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szConfig, "%s/config.ini", IniFilePath); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + + //GetPrivateProfileString(section, entry, defaultstr, result, len, inifile); + if( (strcmp(inifile, szConfig) == 0) && (pvconf_handle != NULL) ) //config.ini + { + ret = conf_read_key ( pvconf_handle, + section, + entry, + defaultstr, + result, + len); + } + else if( (strcmp(inifile, szPortConfig) == 0) && (pvportconf_handle != NULL) ) //portconfig.ini + { + ret = conf_read_key ( pvportconf_handle, + section, + entry, + defaultstr, + result, + len); + } + else //其它情况使用老办法读配置 + { + GetPrivateProfileString((LPWSTR)section, (LPWSTR)entry, (LPWSTR)defaultstr, (LPWSTR)result, len, (LPWSTR)inifile); + printf("\nTIP_(%04d): GetPrivateProString used GetPrivateProfileString(inifile=%s,section=%s, item=%s,result=%s)\n", inifile, section, entry, result); + result[0] = 0; + } + if( SUCCESS == ret ) + StringCutSpace(result); + else + result[0] = 0; + + return (u_long)strlen(result); +} + +int GetPrivateProInt(const char *section, const char *entry, int idefault, char *inifile) +{ + int i, ilen, iRetVal; + char szResult[128]; + + memset(szResult, 0, sizeof(szResult)); + ilen = GetPrivateProString(section, entry, "", szResult, sizeof(szResult)-1, inifile); + if(ilen <= 0) + { + iRetVal = idefault; + } + else + { + if(ilen > 2) + { + if((szResult[0]=='0') && ((szResult[1]=='x') || (szResult[1]=='X'))) + { + iRetVal = 0; + for(i=2; i rlen) + { + memcpy(retstr, defaultstr, rlen-1); + retstr[rlen] = 0; + } + else + { + strcpy(retstr, defaultstr); + } + } + + // 首先将返回值赋值为缺省值,有且仅有在此赋值缺省值 + strcpy(result, retstr); + + if(NULL == hFile) + { + goto ExitFlag2; + } + + sprintf(istring, "[%s]", section); + + // 清除当前文件数据读取计数 + DSfseek(hFile, 0, SEEK_CLR_RCNT); + SectionOk = DSHaveSection(istring, hFile); + if(DS_SECTION_SEARCH == SectionOk) + { + while(1) + { + ilinelen = DSfgetreadcount(hFile); + if(DSfgets(fstring, sizeof(fstring)-1, hFile) == NULL) + { + if(DSfeob(hFile) == 0) + { + break; + } + else + { + DSfseek(hFile, 0, SEEK_SET); + continue; + } + } + + if(StringCutSpace(fstring) > 0) + { + fstring[strlen(istring)] = 0; + + // if remark + if(IsRemarkLine(fstring) == TRUE) + { + continue; + } + + //if find the section + if(strstr(istring, fstring) != NULL) + { + SectionOk = DS_SECTION_EXIST; + DSSaveSectionOffset(hFile); + break; + } + } + } + } + + if(DS_SECTION_SEARCH == SectionOk) + { + DSRestoreSectionOffset(hFile); + SectionOk = DS_SECTION_NOEXIST; + } + + if(SectionOk <= DS_SECTION_NOEXIST) + { + goto ExitFlag2; + } + + iReadLines = 0; + //after find the section, continue find the entry + sprintf(istring, "%s=", entry); + while(1) + { + if(DSSectionisOver(iReadLines, hFile)) + { + break; + } + + if(DSfgets(fstring, sizeof(fstring)-1, hFile) == NULL) + { + // 最后一个配置段,不存在[]的边界 + if(DSfeob(hFile) == 0) + { + break; + } + else + { + DSSetSectionLinesAddFlag(0, hFile); + if(DSSectionisOver(iReadLines, hFile)) + { + //goto ExitFlag2; + break; + } + else + { + DSRestoreSectionOffset(hFile); + continue; + } + } + } + iReadLines++; + DSAddSectionLines(1, hFile); + + if(StringCutSpace(fstring) == 0) + { + continue; + } + + //just look for the string in current section + if((fstring[0] == '[') && (strstr(fstring,"]") != NULL)) + { + iReadLines--; + DSSubSectionLines(1, hFile); + + DSSetSectionLinesAddFlag(0, hFile); + if(DSSectionisOver(iReadLines, hFile)) + { + break; + } + else + { + DSRestoreSectionOffset(hFile); + continue; + } + } + + // if remark + if(IsRemarkLine(fstring) == TRUE) + { + continue; + } + + strcpy(tmp, fstring); + tmp[strlen(istring)+1] = 0; + if(strstr(tmp, istring) != 0) + { + ptr = strstr(fstring, "="); + strcpy(retstr, ptr + 1); + + end = strlen(retstr) - 1; + if(retstr[end] == '\\') + { + retstr[end] = 0; + for(; ;) + { + if(DSfgets(fstring, sizeof(fstring)-1, hFile) == NULL) + { + break; + } + iReadLines++; + DSAddSectionLines(1, hFile); + + if(StringCutSpace(fstring) == 0) + { + break; + } + + if((fstring[0] == '[') && (strstr(fstring,"]") != NULL)) + { + iReadLines--; + DSSubSectionLines(1, hFile); + DSSetSectionLinesAddFlag(0, hFile); + if(!DSSectionisOver(iReadLines, hFile)) + { + DSRestoreSectionOffset(hFile); + } + break; + } + + end = strlen(fstring) - 1; + if(fstring[end] != '\\') + { + if((strlen(retstr)+strlen(fstring)) < sizeof(retstr)) + { + strcat(retstr, fstring); + } + break; + } + else + { + fstring[end] = 0; + if((strlen(retstr)+strlen(fstring)) < sizeof(retstr)) + { + strcat(retstr, fstring); + } + else + { + break; + } + } + + if((int)strlen(retstr) >= rlen) + { + break; + } + } + } + + // 找到合适的匹配项,直接退出 + retstr[rlen] = 0; + strcpy(result, retstr); + goto ExitFlag2; + } + } + + // 没有找到合适的项目,使用缺省值 + +ExitFlag2: +#if 0 + fp = fopen(szfilename, "ab"); + if(fp) + { + fwrite("#####end#####\r\n", 1, strlen("#####end#####\r\n"), fp); + fclose(fp); + } +#endif + return strlen(result); +} + +int GetPrivateProInt2(const char *section, const char *entry, int idefault, HDSFILE hFile) +{ + int i, ilen, iRetVal; + char szResult[128]; + + memset(szResult, 0, sizeof(szResult)); + ilen = GetPrivateProString2(section, entry, "", szResult, sizeof(szResult)-1, hFile); + if(ilen <= 0) + { + iRetVal = idefault; + } + else + { + if(ilen > 2) + { + if((szResult[0]=='0') && ((szResult[1]=='x') || (szResult[1]=='X'))) + { + iRetVal = 0; + for(i=2; iBufSize - buf->MsgCnt) < len) + return 0; + + if (buf->MsgCnt == 0) + { + buf->Front = 0; + buf->Rear = 0; + } + + j = buf->BufSize - buf->Rear; + if (j >= len) + { + memmove((char*)&buf->MsgData[buf->Rear], msg, len); + buf->Rear += len; + } + else + { + memmove((char*)&buf->MsgData[buf->Rear], msg, j); + buf->Rear = (buf->Rear + j) % buf->BufSize; + memmove((char*)&buf->MsgData[buf->Rear], (char*)&msg[j], len - j); + buf->Rear = (buf->Rear + len - j) % buf->BufSize; + } + buf->MsgCnt += len; + + return len; +} + +int GetDataFormBuf(DATA_BUF *databuf, u_char *buf, int len, int clrflag) +{ + int tmp, rdcnt; + + buf[0] = 0; + if (databuf->MsgCnt == 0) + return 0; + + rdcnt = min(databuf->MsgCnt, len); + if((databuf->BufSize - databuf->Front) >= rdcnt) + { + memmove((char *)buf, (char *)&databuf->MsgData[databuf->Front], rdcnt); + } + else + { + tmp = databuf->BufSize - databuf->Front; + memmove((char *)buf, (char *)&databuf->MsgData[databuf->Front], tmp); + memmove((char *)&buf[tmp], (char *)&databuf->MsgData[0], rdcnt - tmp); + } + + if (clrflag) + { + databuf->Front = (databuf->Front + rdcnt) % databuf->BufSize; + databuf->MsgCnt -= rdcnt; + } + + return rdcnt; +} + +void GetCommMode(int port, u_char *str) +{ + char *ptr; + + StringCutSpace((char*)str); + if (strlen((char*)str) == 0) + return; + + SioParam[port].m_psSerial->Baud = atoi((char*)str); + + ptr = strstr((char*)str, ","); + ptr++; + switch(*ptr) + { + case 'o': + case 'O': // 奇校验 + SioParam[port].m_psSerial->CommMode &= ~PARITYMASK; + SioParam[port].m_psSerial->CommMode |= PARITYODD; + break; + case 'e': + case 'E': // 奇校验 + SioParam[port].m_psSerial->CommMode &= ~PARITYMASK; + SioParam[port].m_psSerial->CommMode |= PARITYEVE; + break; + default: // 无校验 + SioParam[port].m_psSerial->CommMode &= ~PARITYMASK; + SioParam[port].m_psSerial->CommMode |= PARITYNONE; + break; + } + + ptr = strstr(ptr, ","); + ptr++; + switch(*ptr) + { + case '5': + SioParam[port].m_psSerial->CommMode &= ~BITMASK; + SioParam[port].m_psSerial->CommMode |= BIT5; + break; + case '6': + SioParam[port].m_psSerial->CommMode &= ~BITMASK; + SioParam[port].m_psSerial->CommMode |= BIT6; + break; + case '7': + SioParam[port].m_psSerial->CommMode &= ~BITMASK; + SioParam[port].m_psSerial->CommMode |= BIT7; + break; + default: + SioParam[port].m_psSerial->CommMode &= ~BITMASK; + SioParam[port].m_psSerial->CommMode |= BIT8; + break; + } + + switch(str[strlen((char*)str)-1]) + { + case '1': + SioParam[port].m_psSerial->CommMode &= ~STOPMASK; + SioParam[port].m_psSerial->CommMode |= STOP1; + break; + case '5': + SioParam[port].m_psSerial->CommMode &= ~STOPMASK; + SioParam[port].m_psSerial->CommMode |= STOP15; + break; + case '2': + SioParam[port].m_psSerial->CommMode &= ~STOPMASK; + SioParam[port].m_psSerial->CommMode |= STOP2; + break; + } +} + +int GetPortProtocolIdx(char *name) +{ + int i; + + for (i = 0; ; i++) + { + if (FunCallPtr[i].ProtocolName == 0) + break; + + if (CmpString((u_char*)FunCallPtr[i].ProtocolName, (u_char*)name)) + { + return i; + } + } + + return 0; +} + +char *GetPortProtocolName(int Idx) +{ + int i; + + for(i=0; i<=Idx; i++) + { + if(FunCallPtr[i].ProtocolName == 0) + break; + + if(i == Idx) + { + break; + } + } + + if(FunCallPtr[i].ProtocolName == 0) + { + return NULL; + } + + return FunCallPtr[i].ProtocolName; +} + +void ReadPortConfigInfo(u_short netport) +{ + int i, j; + char *ptr; + + char entry[256], szbuf[128]; + + MaxSerialPortNum = DEFAULT_MAX_SERIAL_PORT_NUM; + MaxNetPortNum = netport; + if (MaxNetPortNum > DEFAULT_MAX_NET_PORT_NUM) + MaxNetPortNum = DEFAULT_MAX_NET_PORT_NUM; + + MaxPortNum = MaxSerialPortNum + MaxNetPortNum; + + char szConfig[256], szPortConfig[256]; + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szConfig, "%s/config.ini", IniFilePath); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + //GetPrivateProString("NetCommPort", "UdpCommPort", "", szbuf, 120, "./config.ini"); + GetPrivateProString("NetCommPort", "UdpCommPort", "", szbuf, 120, szConfig); + + if (strlen(szbuf)) + UdpCommPort = (u_short)atoul(szbuf); + else + UdpCommPort = DEFAULT_UDP_COMM_PORT; + +#ifdef _OS_WINDOWS_DEBUG_ + SYSTEMTIME sm; + GetLocalTime(&sm); +#endif + + memset((char*)SioParam, 0, sizeof(SIO_PARAM_DEF)*MaxPortNum); + // 读端口信息 + for (i = 0; i < MaxPortNum; i++) + { + // wen test debug +#ifdef _OS_WINDOWS_DEBUG_ + //sprintf(szbuf, "初始化端口%d... ...\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d... ...\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d... ...\n", i+1); +#endif + + SioParam[i].m_psBaoHu = (SIO_PARAM_BAOHU_DEF *)malloc(sizeof(SIO_PARAM_BAOHU_DEF)); + memset((void *)SioParam[i].m_psBaoHu, 0, sizeof(SIO_PARAM_BAOHU_DEF)); + + SioParam[i].m_psSerial = (SIO_PARAM_SERIAL_DEF *)malloc(sizeof(SIO_PARAM_SERIAL_DEF)); + memset((void *)SioParam[i].m_psSerial, 0, sizeof(SIO_PARAM_SERIAL_DEF)); + + SioParam[i].RecvBuf.BufSize = MAX_MSG_BUF_SIZE; + for (j = 0; j < POLL_CMD_TYPE_NUM; j++) + SioParam[i].m_psBaoHu->PollCmd[j].BufSize = MAX_MSG_BUF_SIZE; + + sprintf(entry, "Port%d", i+1); + GetPrivateProString(entry, "Protocol", "", szbuf, 120, szPortConfig); + SioParam[i].ProtocolIdx = GetPortProtocolIdx(szbuf); + + StringToUpper(szbuf); + SioParam[i].ByPassFlag = CmpString((u_char*)szbuf, (u_char*)"bypass"); + + // 串行端口 + if (i < MaxSerialPortNum) + { + SioParam[i].m_psSerial->Baud = DEFAULT_BAUD; + SioParam[i].m_psSerial->CommMode = BIT8 | STOP1 | PARITYNONE; + SioParam[i].m_psSerial->WorkMode = RS232_COMM_MODE; + SioParam[i].m_psSerial->HandshakeMode = NO_HANDSHAKE_MODE; + + SioParam[i].m_psSerial->ChSelect = 0; + SioParam[i].m_psSerial->FreqSelect = 0; + SioParam[i].m_psSerial->ChipCheckOk = 1; + + GetPrivateProString("PortConfig", entry, "", szbuf, 16, szConfig); + if (strlen(szbuf)) + { + SioParam[i].m_psSerial->ChSelect = atoi(szbuf); + ptr = strstr(szbuf, ","); + if (ptr) + { + ptr++; + SioParam[i].m_psSerial->FreqSelect = atoi(ptr); + } + } + + GetPrivateProString(entry, "CommMode", "", szbuf, 120, szPortConfig); + GetCommMode(i, (u_char*)szbuf); + + GetPrivateProString(entry, "WorkMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + if (strstr(szbuf, "422")) + SioParam[i].m_psSerial->WorkMode = RS422_COMM_MODE; + if (strstr(szbuf, "485")) + SioParam[i].m_psSerial->WorkMode = RS485_COMM_MODE; + + GetPrivateProString(entry, "HandshakeMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + StringToLower(szbuf); + if (strstr(szbuf, "HARDWARE")) + SioParam[i].m_psSerial->HandshakeMode = HARDWARE_MODE; + if (strstr(szbuf, "SOFTWARE")) + SioParam[i].m_psSerial->HandshakeMode = SOFTWARE_MODE; + + GetPrivateProString(entry, "XonXoff", "",szbuf, 120, szPortConfig); + SioParam[i].m_psSerial->XonChar1 = HexCharToInt(szbuf[0]) * 16 + HexCharToInt(szbuf[1]); + SioParam[i].m_psSerial->XoffChar1 = HexCharToInt(szbuf[2]) * 16 + HexCharToInt(szbuf[3]); + SioParam[i].m_psSerial->XonChar2 = SioParam[i].m_psSerial->XonChar1; + SioParam[i].m_psSerial->XoffChar2 = SioParam[i].m_psSerial->XoffChar1; + + // 在嵌入式系统中,读、写、数据处理是分离的进程,但是数据处理时会 + // 用到波特率,而波特率只有在串口通讯中存在,数据处理进程不含有串 + // 口通讯指针信息,所以需要在此重新赋值一次。 + SioParam[i].m_psBaoHu->Baud = SioParam[i].m_psSerial->Baud; + } + else + { + SioParam[i].NetType = NO_COMM; + SioParam[i].m_psBaoHu->Baud = DEFAULT_BAUD; + + GetPrivateProString(entry, "NetPort", "", szbuf, 120, szPortConfig); + StringToLower(szbuf); + if ((szbuf[0] == '0') && (szbuf[1] == 'X')) + { + SioParam[i].NetPort = (HexCharToInt(szbuf[2]) << 12) + | (HexCharToInt(szbuf[3]) << 8) + | (HexCharToInt(szbuf[4]) << 4) + | HexCharToInt(szbuf[5]); + } + else + { + SioParam[i].NetPort = atoi(szbuf); + } + if (SioParam[i].NetPort == 0) + continue; + + GetPrivateProString(entry, "NetCommAddr", "", szbuf, 120, szPortConfig); + SioParam[i].NetCommIpAddr = inet_addr(szbuf); + + if ((SioParam[i].NetPort == 0) || (SioParam[i].NetCommIpAddr == 0)) + { + SioParam[i].NetPort = 0; + SioParam[i].NetCommIpAddr = 0; + continue; + } + + GetPrivateProString(entry, "NetCommMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + if (strlen(szbuf) == 0) + continue; + + StringToLower(szbuf); + if (strstr(szbuf, "UDP")) + SioParam[i].NetType = UDP_COMM; + + if (strstr(szbuf, "TCP,SERVER")) + SioParam[i].NetType = TCP_S_COMM; + + if (strstr(szbuf, "TCP,CLIENT")) + SioParam[i].NetType = TCP_C_COMM; + } + + // 读端口测点数量 + GetPrivateProString(entry, "AiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->AiNum = atoi(szbuf); + GetPrivateProString(entry, "DiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->DiNum = atoi(szbuf); + GetPrivateProString(entry, "PiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->PiNum = atoi(szbuf); + + // 读 Poll Command 时间常数 + GetPrivateProString(entry, "Retry", "", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->Retry = (u_long)atoi(szbuf); + GetPrivateProString(entry, "RetryTime", "3", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->RetryTime = (u_long)((atof(szbuf) * 1000) / TIMER_CNT); + GetPrivateProString(entry, "WaitTime", "", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->WaitTime = (u_long)((atof(szbuf) * 1000) / TIMER_CNT); + + // wen 2004.10.26 增加数据点的内存分配(先分配成接收规约内存区) + //PortMemoryMalloc(i, RECV_PROTOCOL); + GetPrivateProString(entry, "PortType", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->PortType = (u_char)atoi(szbuf); + GetPrivateProString(entry, "CheckTime", "no", szbuf, 120, szPortConfig); + if(_stricmp(szbuf, "up") == 0) + SioParam[i].m_psBaoHu->CheckTime = 1; + else if(_stricmp(szbuf, "down") == 0) + SioParam[i].m_psBaoHu->CheckTime = 2; + else + SioParam[i].m_psBaoHu->CheckTime = 0; + + // wen 2005.03.01 增加遥控遥调转发处理 + //"ProvYkYtTimeOut"="转发遥控超时时间" + GetPrivateProfileString((LPWSTR)entry, (LPWSTR)"ProvYkYtTimeOut", (LPWSTR)"10", (LPWSTR)szbuf, 120, (LPWSTR)szPortConfig); + SioParam[i].m_psBaoHu->ProvYkYtMsg.m_iTimeOut = atoi(szbuf); + +#ifdef _OS_WINDOWS_DEBUG_ + GetLocalTime(&sm); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 内存分配%d开始\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); +#endif + // 数据库点内存分配 + PortMemoryMalloc(i, SioParam[i].m_psBaoHu->PortType, SioParam[i].m_psBaoHu); + + // 读规约配置 + if (FunCallPtr[SioParam[i].ProtocolIdx].ReadConfig) + { + FunCallPtr[SioParam[i].ProtocolIdx].ReadConfig(i); + } + +#ifdef _OS_WINDOWS_DEBUG_ + GetLocalTime(&sm); + // wen test debug + //sprintf(szbuf, "初始化端口%d成功\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d成功\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); + OutputDebugString((LPCWSTR)"\n"); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d成功\n", i+1); +#endif + } +} + +void ReadPortConfigInfoEx(u_short netport) +{ + int i, j; + char *ptr; + + char entry[256], szbuf[128]; + + MaxSerialPortNum = DEFAULT_MAX_SERIAL_PORT_NUM; + MaxNetPortNum = netport; + if (MaxNetPortNum > DEFAULT_MAX_NET_PORT_NUM) + MaxNetPortNum = DEFAULT_MAX_NET_PORT_NUM; + + MaxPortNum = MaxSerialPortNum + MaxNetPortNum; + + char szConfig[256], szPortConfig[256]; + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szConfig, "%s/config.ini", IniFilePath); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + //GetPrivateProString("NetCommPort", "UdpCommPort", "", szbuf, 120, "./config.ini"); + GetPrivateProString("NetCommPort", "UdpCommPort", "", szbuf, 120, szConfig); + + if (strlen(szbuf)) + UdpCommPort = (u_short)atoul(szbuf); + else + UdpCommPort = DEFAULT_UDP_COMM_PORT; + +#ifdef _OS_WINDOWS_DEBUG_ + SYSTEMTIME sm; + GetLocalTime(&sm); +#endif + + memset((char*)SioParam, 0, sizeof(SIO_PARAM_DEF)*MaxPortNum); + // 读端口信息 + for (i = 0; i < MaxPortNum; i++) + { + // wen test debug +#ifdef _OS_WINDOWS_DEBUG_ + //sprintf(szbuf, "初始化端口%d... ...\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d... ...\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d... ...\n", i+1); +#endif + + SioParam[i].m_psBaoHu = (SIO_PARAM_BAOHU_DEF *)malloc(sizeof(SIO_PARAM_BAOHU_DEF)); + memset((void *)SioParam[i].m_psBaoHu, 0, sizeof(SIO_PARAM_BAOHU_DEF)); + + SioParam[i].m_psSerial = (SIO_PARAM_SERIAL_DEF *)malloc(sizeof(SIO_PARAM_SERIAL_DEF)); + memset((void *)SioParam[i].m_psSerial, 0, sizeof(SIO_PARAM_SERIAL_DEF)); + + SioParam[i].RecvBuf.BufSize = MAX_MSG_BUF_SIZE; + for (j = 0; j < POLL_CMD_TYPE_NUM; j++) + SioParam[i].m_psBaoHu->PollCmd[j].BufSize = MAX_MSG_BUF_SIZE; + + sprintf(entry, "Port%d", i+1); + GetPrivateProString(entry, "Protocol", "", szbuf, 120, szPortConfig); + SioParam[i].ProtocolIdx = GetPortProtocolIdx(szbuf); + + StringToUpper(szbuf); + SioParam[i].ByPassFlag = CmpString((u_char*)szbuf, (u_char*)"bypass"); + + // 串行端口 + if (i < MaxSerialPortNum) + { + SioParam[i].m_psSerial->Baud = DEFAULT_BAUD; + SioParam[i].m_psSerial->CommMode = BIT8 | STOP1 | PARITYNONE; + SioParam[i].m_psSerial->WorkMode = RS232_COMM_MODE; + SioParam[i].m_psSerial->HandshakeMode = NO_HANDSHAKE_MODE; + + SioParam[i].m_psSerial->ChSelect = 0; + SioParam[i].m_psSerial->FreqSelect = 0; + SioParam[i].m_psSerial->ChipCheckOk = 1; + + GetPrivateProString("PortConfig", entry, "", szbuf, 16, szConfig); + if (strlen(szbuf)) + { + SioParam[i].m_psSerial->ChSelect = atoi(szbuf); + ptr = strstr(szbuf, ","); + if (ptr) + { + ptr++; + SioParam[i].m_psSerial->FreqSelect = atoi(ptr); + } + } + + GetPrivateProString(entry, "CommMode", "", szbuf, 120, szPortConfig); + GetCommMode(i, (u_char*)szbuf); + + GetPrivateProString(entry, "WorkMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + if (strstr(szbuf, "422")) + SioParam[i].m_psSerial->WorkMode = RS422_COMM_MODE; + if (strstr(szbuf, "485")) + SioParam[i].m_psSerial->WorkMode = RS485_COMM_MODE; + + GetPrivateProString(entry, "HandshakeMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + StringToLower(szbuf); + if (strstr(szbuf, "HARDWARE")) + SioParam[i].m_psSerial->HandshakeMode = HARDWARE_MODE; + if (strstr(szbuf, "SOFTWARE")) + SioParam[i].m_psSerial->HandshakeMode = SOFTWARE_MODE; + + GetPrivateProString(entry, "XonXoff", "",szbuf, 120, szPortConfig); + SioParam[i].m_psSerial->XonChar1 = HexCharToInt(szbuf[0]) * 16 + HexCharToInt(szbuf[1]); + SioParam[i].m_psSerial->XoffChar1 = HexCharToInt(szbuf[2]) * 16 + HexCharToInt(szbuf[3]); + SioParam[i].m_psSerial->XonChar2 = SioParam[i].m_psSerial->XonChar1; + SioParam[i].m_psSerial->XoffChar2 = SioParam[i].m_psSerial->XoffChar1; + + // 在嵌入式系统中,读、写、数据处理是分离的进程,但是数据处理时会 + // 用到波特率,而波特率只有在串口通讯中存在,数据处理进程不含有串 + // 口通讯指针信息,所以需要在此重新赋值一次。 + SioParam[i].m_psBaoHu->Baud = SioParam[i].m_psSerial->Baud; + } + else + { + SioParam[i].NetType = NO_COMM; + SioParam[i].m_psBaoHu->Baud = DEFAULT_BAUD; + SioParam[i].CommSock = -1; + SioParam[i].LiSock = -1; + + GetPrivateProString(entry, "NetPort", "", szbuf, 120, szPortConfig); + StringToLower(szbuf); + if ((szbuf[0] == '0') && (szbuf[1] == 'X')) + { + SioParam[i].NetPort = (HexCharToInt(szbuf[2]) << 12) + | (HexCharToInt(szbuf[3]) << 8) + | (HexCharToInt(szbuf[4]) << 4) + | HexCharToInt(szbuf[5]); + } + else + { + SioParam[i].NetPort = atoi(szbuf); + } + if (SioParam[i].NetPort == 0) + { + //continue; + goto mallocdbflag; + } + + GetPrivateProString(entry, "NetCommAddr", "", szbuf, 120, szPortConfig); + SioParam[i].NetCommIpAddr = inet_addr(szbuf); + + if ((SioParam[i].NetPort == 0) || (SioParam[i].NetCommIpAddr == 0)) + { + SioParam[i].NetPort = 0; + SioParam[i].NetCommIpAddr = 0; + //continue; + goto mallocdbflag; + } + + GetPrivateProString(entry, "NetCommMode", "", szbuf, 120, szPortConfig); + StringCutSpace(szbuf); + if(strlen(szbuf) == 0) + { + //continue; + goto mallocdbflag; + } + + StringToUpper(szbuf); + if (strstr(szbuf, "UDP")) + SioParam[i].NetType = UDP_COMM; + + if (strstr(szbuf, "TCP,SERVER")) + SioParam[i].NetType = TCP_S_COMM; + + if (strstr(szbuf, "TCP,CLIENT")) + SioParam[i].NetType = TCP_C_COMM; + } + +mallocdbflag: + + // 读端口测点数量 + GetPrivateProString(entry, "AiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->AiNum = atoi(szbuf); + GetPrivateProString(entry, "DiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->DiNum = atoi(szbuf); + GetPrivateProString(entry, "PiNum", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->PiNum = atoi(szbuf); + + // 读 Poll Command 时间常数 + GetPrivateProString(entry, "Retry", "", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->Retry = (u_long)atoi(szbuf); + GetPrivateProString(entry, "RetryTime", "3", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->RetryTime = (u_long)((atof(szbuf) * 1000) / TIMER_CNT); + GetPrivateProString(entry, "WaitTime", "", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->WaitTime = (u_long)((atof(szbuf) * 1000) / TIMER_CNT); + + // wen 2004.10.26 增加数据点的内存分配(先分配成接收规约内存区) + //PortMemoryMalloc(i, RECV_PROTOCOL); + GetPrivateProString(entry, "PortType", "0", szbuf, 120, szPortConfig); + SioParam[i].m_psBaoHu->PortType = (u_char)atoi(szbuf); + GetPrivateProString(entry, "CheckTime", "no", szbuf, 120, szPortConfig); + if(_stricmp(szbuf, "up") == 0) + SioParam[i].m_psBaoHu->CheckTime = 1; + else if(_stricmp((const char*)szbuf, "down") == 0) + SioParam[i].m_psBaoHu->CheckTime = 2; + else + SioParam[i].m_psBaoHu->CheckTime = 0; + + // wen 2005.03.01 增加遥控遥调转发处理 + //"ProvYkYtTimeOut"="转发遥控超时时间" + GetPrivateProfileString((LPWSTR)entry, (LPWSTR)"ProvYkYtTimeOut", (LPWSTR)"10", (LPWSTR)szbuf, 120, (LPWSTR)szPortConfig); + SioParam[i].m_psBaoHu->ProvYkYtMsg.m_iTimeOut = atoi(szbuf); + +#ifdef _OS_WINDOWS_DEBUG_ + GetLocalTime(&sm); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 内存分配%d开始\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); +#endif + // 数据库点内存分配 + PortMemoryMallocEx(i, SioParam[i].m_psBaoHu->PortType, SioParam[i].m_psBaoHu); + + // 读规约配置 + if (FunCallPtr[SioParam[i].ProtocolIdx].ReadConfig) + { + FunCallPtr[SioParam[i].ProtocolIdx].ReadConfig(i); + } + +#ifdef _OS_WINDOWS_DEBUG_ + GetLocalTime(&sm); + // wen test debug + //sprintf(szbuf, "初始化端口%d成功\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d成功\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); + OutputDebugString((LPCWSTR)"\n"); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d成功\n", i+1); +#endif + } + + + for(i = 0; i < MaxPortNum; i++) + { +#ifdef _OS_WINDOWS_DEBUG_ + //sprintf(szbuf, "初始化端口%d... ...\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d数据库... ...\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d数据库... ...\n", i+1); +#endif + PortDataPntInit(i, SioParam[i].m_psBaoHu->PortType, SioParam[i].m_psBaoHu); + +#ifdef _OS_WINDOWS_DEBUG_ + GetLocalTime(&sm); + // wen test debug + //sprintf(szbuf, "初始化端口%d成功\n", i+1); + sprintf(szbuf, "%02d_%02d:%02d:%02d.%03d 初始化端口%d数据库成功\n", sm.wDay, sm.wHour, + sm.wMinute, sm.wSecond, sm.wMilliseconds, i+1); + OutputDebugString((LPCWSTR)szbuf); + OutputDebugString((LPCWSTR)"\n"); +#elif _OS_WINDOWS_DEBUG_ + printf("初始化端口%d数据库成功\n", i+1); +#endif + } +} + +/*void OpenAllPort(void) +{ + int i; + + for (i = 0; i < MaxPortNum; i++) + { + //if (SioParam[i].OpenFlag) + if(ShmGetPortFlag(i, FLAG_OPEN)) + continue; + + if (SioParam[i].ProtocolIdx == 0) + continue; + + SioParam[i].OpenFlag = 1; + } +} +*/ +void OpenAllPort(void) +{ + int i; + + // 只打开有效使用的端口,规约为"none"的视为无效端口 + for (i = 0; i < MaxPortNum; i++) + { + //commid = ValidPort[i]; + if (ShmGetPortFlag(i, FLAG_OPEN)) + continue; + /*if (OPEN_PORT == SioParam[commid].OpenFlag) + { + SioParam[commid].iCreateFailCnt = 0; + continue; + }*/ + if (SioParam[i].ProtocolIdx == 0) + continue; + + if (i < MaxSerialPortNum) + { + //OpenAllSerialPort(commid); + continue; + } + + // 增加端口连续10次连接不上的处理方式,如果10次没有连接上则等两分钟之后重新连接 + /*if ((SioParam[commid].iCreateFailCnt > 10) && (SioParam[commid].iCreateFailCnt < 120)) + { + SioParam[commid].iCreateFailCnt++; + continue; + } + if (SioParam[commid].iCreateFailCnt >= 120) + SioParam[commid].iCreateFailCnt = 0;*/ + OpenNetPort(i); + //SioParam[commid].iCreateFailCnt++; + } +} + +void CloseOnePort(int commid) +{ + SioParam[commid].OpenFlag = 0; + + // wen 2004.10.26 删除分配的内存空间 + //PortMemoryFree(commid); + PortMemoryFree(commid, &SioParam[commid]); +} + +void CloseAllPort(void) +{ + int i; + + for (i = 0; i < MaxPortNum; i++) + CloseOnePort(i); +} + +//******************************************************************* +// 通讯程序 * +//******************************************************************* + +int SetPntMsg(int port, int point, void *pntmsg, BYTE type, BYTE attr) +{ + int i, j, k; + AI_DEF *aiptr, *aipntmsg; + DI_DEF *diptr, *dipntmsg; + PI_DEF *piptr, *pipntmsg; + PROV_AI_PNT *aiprovptr; + PROV_DI_PNT *diprovptr; + PROV_PI_PNT *piprovptr; + SOE_DEF SoeData, *pSoeMsg; + BOOL bRetVal; + + bRetVal = false; + if ((port < 0) || (port >= MaxPortNum)) + return bRetVal; + + if (!IsBaoHuPtr(port)) + return bRetVal; + + if (RECV_PROTOCOL != SioParam[port].m_psBaoHu->PortType ) + return bRetVal; + + switch (type) + { + case AI_PNT_TYPE: + if(!SioParam[port].m_psBaoHu->AiPtr) + { + break; + } + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->AiNum)) + { + break; + } + + aipntmsg = (AI_DEF*)pntmsg; + aiptr = (AI_DEF*)SioParam[port].m_psBaoHu->AiPtr; + + switch (attr) + { + case PNT_ENABLE: + aiptr[point].Enable = aipntmsg->Enable; + bRetVal = true; + break; + + case PNT_STATE: + aiptr[point].State = aipntmsg->State; + bRetVal = true; + break; + + case PNT_POLAR: + aiptr[point].Polar = aipntmsg->Polar; + bRetVal = true; + break; + + case PNT_RAWVALUE: + //SioParam[port].Status = TRUE; + + if (abs((long)(aiptr[point].RawValue - aipntmsg->RawValue)) >= 1) + { + aiptr[point].RawValue = aipntmsg->RawValue; + aiptr[point].State = 1; +// 定义前置机功能 +#ifdef FUNCTION_FEND + WriteChangeData(port, point, aipntmsg, AI_PNT_TYPE); +#endif + + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (aiptr[point].Prov[i].Enable == 0) + continue; + + j = aiptr[point].Prov[i].PortNo; + k = aiptr[point].Prov[i].PntNo; + if((PROV_PROTOCOL == SioParam[j].m_psBaoHu->PortType) + && SioParam[j].m_psBaoHu) + { + if(SioParam[j].m_psBaoHu->AiPtr) + { + aiprovptr = (PROV_AI_PNT*)SioParam[j].m_psBaoHu->AiPtr; + aiprovptr[k].ChangeFlag = 1; + // wen 2004.11.19 增加遥测变化数据的处理 + SioParam[j].m_psBaoHu->AiChange = TRUE; + } + } + } + + // wen 2004.11.19 增加遥测变化数据的处理 + SioParam[port].m_psBaoHu->AiChange = TRUE; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.12.15 增加设置点数据值时,可以激活端口状态 + SioParam[port].LineCommCnt = 0; + SioParam[port].Status = TRUE; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + bRetVal = true; + break; + + case PNT_PROV_MSG: + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (aiptr[point].Prov[i].Enable == 0) + continue; + + if (aiptr[point].Prov[i].PortNo == aipntmsg->Prov[0].PortNo) + { + aiptr[point].Prov[i].PntNo = aipntmsg->Prov[0].PntNo; + aiptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + } + + if(bRetVal) + { + break; + } + + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (aiptr[point].Prov[i].Enable) + continue; + + aiptr[point].Prov[i].PortNo = aipntmsg->Prov[0].PortNo; + aiptr[point].Prov[i].PntNo = aipntmsg->Prov[0].PntNo; + aiptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + + break; + } + break; + + case DI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->DiPtr) + break; + + // wen 2005.09.19 + if((point < 0) || (point >= SioParam[port].m_psBaoHu->DiNum)) + { + break; + } + + dipntmsg = (DI_DEF*)pntmsg; + diptr = (DI_DEF*)SioParam[port].m_psBaoHu->DiPtr; + + switch (attr) + { + case PNT_ENABLE: + diptr[point].Enable = dipntmsg->Enable; + bRetVal = true; + break; + + case PNT_STATE: + diptr[point].State = dipntmsg->State; + bRetVal = true; + break; + + case PNT_SOE_TIME: + memmove((char*)&diptr[point].SoeTime, (char*)&dipntmsg->SoeTime, + sizeof(DAY_TIME)); + // wen 2004.11.16 增加soe数据的转发存储(是否增加soe点的配置???) + memset((void *)&SoeData, 0, sizeof(SOE_DEF)); + memcpy((void *)&SoeData.SoeTime, (void*)&dipntmsg->SoeTime, + sizeof(DAY_TIME)); + SoeData.bStatus = dipntmsg->Status; + // 一般为ASDU1, 即扩展字节无意义 + SoeData.u8Type = 1; + for(i=0; iSoeTime.Hour == 6) + { + pSoeMsg->SoeTime.Hour = 6; + } + + memmove((char *)&diptr[point].SoeTime, (char *)&pSoeMsg->SoeTime, + sizeof(DAY_TIME)); + + memcpy((void *)&SoeData, (void*)pSoeMsg, sizeof(SOE_DEF)); + for(i=0; iStatus &= 0x01; + + if (diptr[point].Status != dipntmsg->Status) + { + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (diptr[point].Prov[i].Enable == 0) + continue; + + j = diptr[point].Prov[i].PortNo; + k = diptr[point].Prov[i].PntNo; + if((SioParam[j].m_psBaoHu->PortType == PROV_PROTOCOL) + && SioParam[j].m_psBaoHu) + { + if(SioParam[j].m_psBaoHu->DiPtr) + { + diprovptr = (PROV_DI_PNT*)SioParam[j].m_psBaoHu->DiPtr; + diprovptr[k].ChangeFlag = 1; + + // wen 2004.11.19 增加遥信变化数据的处理 + SioParam[j].m_psBaoHu->DiChange = TRUE; + } + } + } + + // wen 2004.11.19 增加遥信变化数据的处理 + SioParam[port].m_psBaoHu->DiChange = TRUE; + +// 定义前置机功能 +#ifdef FUNCTION_FEND + WriteChangeData(port, point, dipntmsg, DI_PNT_TYPE); +#endif + } + diptr[point].Status = dipntmsg->Status; + diptr[point].State = 1; + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.12.15 增加设置点数据值时,可以激活端口状态 + SioParam[port].LineCommCnt = 0; + SioParam[port].Status = TRUE; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + bRetVal = true; + break; + + case PNT_CTRL_NO: + diptr[point].ControlNo = dipntmsg->ControlNo; + diptr[point].CtrlEnable = true; + bRetVal = true; + break; + + case PNT_PROV_MSG: + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (diptr[point].Prov[i].Enable == 0) + continue; + + if (diptr[point].Prov[i].PortNo == dipntmsg->Prov[0].PortNo) + { + diptr[point].Prov[i].PntNo = dipntmsg->Prov[0].PntNo; + diptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + } + if(bRetVal) + { + break; + } + + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (diptr[point].Prov[i].Enable) + continue; + + diptr[point].Prov[i].PortNo = dipntmsg->Prov[0].PortNo; + diptr[point].Prov[i].PntNo = dipntmsg->Prov[0].PntNo; + diptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + break; + } + break; + + case PI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->PiPtr) + break; + + // wen 2005.09.19 + if((point < 0) || (point >= SioParam[port].m_psBaoHu->PiNum)) + { + break; + } + + pipntmsg = (PI_DEF*)pntmsg; + piptr = (PI_DEF*)SioParam[port].m_psBaoHu->PiPtr; + + switch (attr) + { + case PNT_ENABLE: + piptr[point].Enable = pipntmsg->Enable; + bRetVal = true; + break; + + case PNT_STATE: + piptr[point].State = pipntmsg->State; + bRetVal = true; + break; + + case PNT_RAWVALUE: + //SioParam[port].Status = TRUE; + + if (abs((long)(piptr[point].RawValue - pipntmsg->RawValue)) > 2) + { + piptr[point].RawValue = pipntmsg->RawValue; + piptr[point].State = 1; + + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (piptr[point].Prov[i].Enable == 0) + continue; + + j = piptr[point].Prov[i].PortNo; + k = piptr[point].Prov[i].PntNo; + if(SioParam[j].m_psBaoHu) + { + if((PROV_PROTOCOL == SioParam[j].m_psBaoHu->PortType) + && SioParam[j].m_psBaoHu->PiPtr) + { + piprovptr = (PROV_PI_PNT*)SioParam[j].m_psBaoHu->PiPtr; + piprovptr[k].ChangeFlag = 1; + + // wen 2004.11.19 增加电度变化数据的处理 + // SioParam[j].m_psBaoHu->PiChange = TRUE; + } + } + } + +// 定义前置机功能 +#ifdef FUNCTION_FEND + WriteChangeData(port, point, pipntmsg, PI_PNT_TYPE); +#endif + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.12.15 增加设置点数据值时,可以激活端口状态 + SioParam[port].LineCommCnt = 0; + SioParam[port].Status = TRUE; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + bRetVal = true; + break; + + case PNT_PROV_MSG: + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (piptr[point].Prov[i].Enable == 0) + continue; + + if (piptr[point].Prov[i].PortNo == pipntmsg->Prov[0].PortNo) + { + piptr[point].Prov[i].PntNo = pipntmsg->Prov[0].PntNo; + piptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + } + if(bRetVal) + { + break; + } + + for (i = 0; i < MAX_PROV_PORT_NUM; i++) + { + if (piptr[point].Prov[i].Enable) + continue; + + piptr[point].Prov[i].PortNo = pipntmsg->Prov[0].PortNo; + piptr[point].Prov[i].PntNo = pipntmsg->Prov[0].PntNo; + piptr[point].Prov[i].Enable = 1; + bRetVal = true; + break; + } + break; + } + break; + } + + return bRetVal; +} + +int GetPntMsg(int port, int point, void *pntmsg, BYTE type, BYTE attr) +{ + AI_DEF *aiptr, *aipntmsg; + DI_DEF *diptr, *dipntmsg; + PI_DEF *piptr, *pipntmsg; + BOOL bRetVal; + + bRetVal = false; + if ((port < 0) || (port >= MaxPortNum)) + return bRetVal; + + if (!IsBaoHuPtr(port)) + return bRetVal; + + if (RECV_PROTOCOL != SioParam[port].m_psBaoHu->PortType) + return bRetVal; + + switch (type) + { + case AI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->AiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->AiNum)) + break; + + aipntmsg = (AI_DEF*)pntmsg; + aiptr = (AI_DEF*)SioParam[port].m_psBaoHu->AiPtr; + + bRetVal = true; + switch (attr) + { + case PNT_ENABLE: + aipntmsg->Enable = aiptr[point].Enable; + break; + + case PNT_STATE: + aipntmsg->State = aiptr[point].State; + break; + + case PNT_POLAR: + aipntmsg->Polar = aiptr[point].Polar; + break; + + case PNT_RAWVALUE: + aipntmsg->RawValue = aiptr[point].RawValue; + break; + + case PNT_PROV_MSG: + memmove((char*)&aipntmsg->Prov[0], + (char*)&aiptr[point].Prov[0], + sizeof(PROV_PNT)*MAX_PROV_PORT_NUM); + break; + + case PNT_ALL_MSG: + memmove((char*)aipntmsg, (char*)&aiptr[point], sizeof(AI_DEF)); + break; + + default: + bRetVal = false; + break; + } + break; + + case DI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->DiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->DiNum)) + break; + + dipntmsg = (DI_DEF*)pntmsg; + diptr = (DI_DEF*)SioParam[port].m_psBaoHu->DiPtr; + + bRetVal = true; + switch (attr) + { + case PNT_ENABLE: + dipntmsg->Enable = diptr[point].Enable; + break; + + case PNT_STATE: + dipntmsg->State = diptr[point].State; + break; + + case PNT_SOE_TIME: + memmove((char*)&dipntmsg->SoeTime, + (char*)&diptr[point].SoeTime, + sizeof(DAY_TIME)); + break; + + case PNT_STATUS: + dipntmsg->Status = diptr[point].Status; + break; + + case PNT_CTRL_NO: + dipntmsg->ControlNo = diptr[point].ControlNo; + dipntmsg->CtrlEnable = diptr[point].CtrlEnable; + break; + + case PNT_PROV_MSG: + memmove((char*)&dipntmsg->Prov[0], + (char*)&diptr[point].Prov[0], + sizeof(PROV_PNT)*MAX_PROV_PORT_NUM); + break; + + case PNT_ALL_MSG: + memmove((char*)dipntmsg, (char*)&diptr[point], sizeof(DI_DEF)); + break; + + default: + bRetVal = false; + break; + } + break; + + case PI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->PiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->PiNum)) + break; + + + pipntmsg = (PI_DEF*)pntmsg; + piptr = (PI_DEF*)SioParam[port].m_psBaoHu->PiPtr; + + bRetVal = true; + switch (attr) + { + case PNT_ENABLE: + pipntmsg->Enable = piptr[point].Enable; + break; + + case PNT_STATE: + pipntmsg->State = piptr[point].State; + break; + + case PNT_RAWVALUE: + pipntmsg->RawValue = piptr[point].RawValue; + break; + + case PNT_PROV_MSG: + memmove((char*)&pipntmsg->Prov[0], + (char*)&piptr[point].Prov[0], + sizeof(PROV_PNT)*MAX_PROV_PORT_NUM); + break; + + case PNT_ALL_MSG: + memmove((char*)pipntmsg, (char*)&piptr[point], sizeof(PI_DEF)); + break; + + default: + bRetVal = false; + } + break; + } + + return bRetVal; +} + +int SetPorvPntMsg(int port, int point, void *pntmsg, BYTE type, BYTE attr) +{ + AI_DEF aipnt; + DI_DEF dipnt; + PI_DEF pipnt; + PROV_AI_PNT *aiprovptr, *aipptr; + PROV_DI_PNT *diprovptr, *dipptr; + PROV_PI_PNT *piprovptr, *pipptr; + BOOL bRetVal; + + bRetVal = false; + + if((port < 0) || (port >= MaxPortNum)) + return bRetVal; + + if(!IsBaoHuPtr(port)) + return bRetVal; + + if(PROTOCOL_SLAVE != SioParam[port].m_psBaoHu->PortType) + return bRetVal; + + switch (type) + { + case AI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->AiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->AiNum)) + break; + + aiprovptr = (PROV_AI_PNT*)SioParam[port].m_psBaoHu->AiPtr; + aipptr = (PROV_AI_PNT*)pntmsg; + + aiprovptr[point].PortNo = aipptr->PortNo; + aiprovptr[point].PntNo = aipptr->PntNo; + aiprovptr[point].fFactor = aipptr->fFactor; + aiprovptr[point].Enable = 1; + aiprovptr[point].ChangeFlag = 0; + + aipnt.Prov[0].PortNo = port; + aipnt.Prov[0].PntNo = point; + SetPntMsg(aipptr->PortNo, aipptr->PntNo, + (void*)&aipnt, AI_PNT_TYPE, PNT_PROV_MSG); + bRetVal = true; + break; + + case DI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->DiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->DiNum)) + break; + + diprovptr = (PROV_DI_PNT*)SioParam[port].m_psBaoHu->DiPtr; + dipptr = (PROV_DI_PNT*)pntmsg; + + switch(attr) + { + case PNT_PROV_MSG: + diprovptr[point].PortNo = dipptr->PortNo; + diprovptr[point].PntNo = dipptr->PntNo; + diprovptr[point].Enable = 1; + diprovptr[point].ChangeFlag = 0; + + dipnt.Prov[0].PortNo = port; + dipnt.Prov[0].PntNo = point; + SetPntMsg(dipptr->PortNo, dipptr->PntNo, + (void*)&dipnt, DI_PNT_TYPE, PNT_PROV_MSG); + bRetVal = true; + break; + + case PNT_CTRL_NO: + diprovptr[point].ControlNo = dipptr->ControlNo; + diprovptr[point].CtrlEnable = true; + bRetVal = true; + break; + } + break; + + case PI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->PiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->PiNum)) + break; + + piprovptr = (PROV_PI_PNT*)SioParam[port].m_psBaoHu->PiPtr; + pipptr = (PROV_PI_PNT*)pntmsg; + + piprovptr[point].PortNo = pipptr->PortNo; + piprovptr[point].PntNo = pipptr->PntNo; + piprovptr[point].fFactor = pipptr->fFactor; + piprovptr[point].Enable = 1; + piprovptr[point].ChangeFlag = 0; + + pipnt.Prov[0].PortNo = port; + pipnt.Prov[0].PntNo = point; + SetPntMsg(pipptr->PortNo, pipptr->PntNo, + (void*)&pipnt, PI_PNT_TYPE, PNT_PROV_MSG); + bRetVal = true; + break; + } + + return bRetVal; +} + +int GetPorvPntMsg(int port, int point, void *pntmsg, BYTE type) +{ + PROV_AI_PNT *aiprovptr; + PROV_DI_PNT *diprovptr; + PROV_PI_PNT *piprovptr; + BOOL bRetVal; + + bRetVal = false; + if ((port < 0) || (port >= MaxPortNum)) + return bRetVal; + + if (!IsBaoHuPtr(port)) + return bRetVal; + + if (RECV_PROTOCOL != SioParam[port].m_psBaoHu->PortType) + return bRetVal; + + switch (type) + { + case AI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->AiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->AiNum)) + break; + + aiprovptr = (PROV_AI_PNT*)SioParam[port].m_psBaoHu->AiPtr; + memmove((char*)pntmsg, (char*)&aiprovptr[point], sizeof(PROV_AI_PNT)); + bRetVal = true; + break; + + case DI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->DiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->DiNum)) + break; + + diprovptr = (PROV_DI_PNT*)SioParam[port].m_psBaoHu->DiPtr; + memmove((char*)pntmsg, (char*)&diprovptr[point], sizeof(PROV_DI_PNT)); + bRetVal = true; + break; + + case PI_PNT_TYPE: + if (!SioParam[port].m_psBaoHu->PiPtr) + break; + + if ((point < 0) || (point >= SioParam[port].m_psBaoHu->PiNum)) + break; + + piprovptr = (PROV_PI_PNT*)SioParam[port].m_psBaoHu->PiPtr; + memmove((char*)pntmsg, (char*)&piprovptr[point], sizeof(PROV_PI_PNT)); + bRetVal = true; + break; + } + + return bRetVal; +} + +//******************************************************************* +//* Poll Cmd * +//******************************************************************* + +int CheckPollCmdBufEmpty(int port) +{ + int i, j; + + if ((port < 0) || (port >= MaxPortNum)) + return 0; + + if (!IsBaoHuPtr(port)) + return 0; + + j = 0; + for (i = 0; i < POLL_CMD_TYPE_NUM; i++) + { + j += SioParam[port].m_psBaoHu->PollCmd[i].MsgCnt ? 1 : 0; + } + + return (j ? 0 : 1); +} + +int PutPollCmdToBuf(int port, int type, WORD wait, char *buf, int len) +{ + int ret; + u_char szbuf[MAX_MSG_BUF_SIZE]; + + if ((port < 0) || (port >= MaxPortNum)) + return 0; + + if (len == 0) + return 0; + + // wen 2004.10.25 如果端口未打开,则返回0 + //if(!SioParam[port].OpenFlag) + if(!ShmGetPortFlag(port, FLAG_OPEN)) + return 0; + + if (!IsBaoHuPtr(port)) + return false; + + szbuf[0] = HIBYTE(len+2); + szbuf[1] = LOBYTE(len+2); + + // 将等待时间作为命令的一部分存储 + szbuf[2] = HIBYTE(wait); + szbuf[3] = LOBYTE(wait); + memmove((char*)&szbuf[4], buf, len); + + ret = PutDataToBuf(&SioParam[port].m_psBaoHu->PollCmd[type], szbuf, len+4); + if (ret == (len + 4)) + return true; + + return false; +} + +// wen 2005.09.08 清空指令缓冲区中的所有指令 +void ClearAllCmdFromPollCmdBuf(int port) +{ + int i; + + if ((port < 0) || (port >= MaxPortNum)) + return; + + if (!IsBaoHuPtr(port)) + return; + + for(i = 0; i < POLL_CMD_TYPE_NUM; i++) + { + SioParam[port].m_psBaoHu->PollCmd[i].MsgCnt=0; + } + + ClearCmdAllFlag(port); +} + +void ClearCmdFormPollCmdBuf(int port) +{ + int len, idx; + u_char szbuf[MAX_MSG_BUF_SIZE]; + + if ((port < 0) || (port >= MaxPortNum)) + return; + + if (!IsBaoHuPtr(port)) + return; + + idx = SioParam[port].m_psBaoHu->LastGetCmdBuf; + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], szbuf, 2, true); + len = BYTE1(szbuf[0]) + BYTE0(szbuf[1]); + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], szbuf, len, true); + + // wen 2005.09.20 修改清除指令下发标识 + ClearCmdAllFlag(port); +} + +void ClearCmdFormPollCmdBufEx( int port, char *file, int line ) +{ + int len, idx; + char szbuf[MAX_MSG_BUF_SIZE]; + + ClearCmdFormPollCmdBuf(port); + return; + + if ((port < 0) || (port >= MaxPortNum)) + return; + + if (!IsBaoHuPtr(port)) + return; + + sprintf(szbuf, "commid=%d %s<%d>, Clear Cmd", port + 1, file, line); + DebugPrint(szbuf); + + idx = SioParam[port].m_psBaoHu->LastGetCmdBuf; + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], (u_char *)szbuf, 2, true); + len = BYTE1(szbuf[0]) + BYTE0(szbuf[1]); + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], (u_char *)szbuf, len, true); + + // wen 2005.09.20 修改清除指令下发标识 + ClearCmdAllFlag(port); +} + +void ClearCmdAllFlag(int port) +{ + if (!IsBaoHuPtr(port)) + return; + + SioParam[port].m_psBaoHu->RetryCnt = 0; + SioParam[port].m_psBaoHu->RetryTimeCnt = 0; + SioParam[port].m_psBaoHu->WaitTimeCnt = 0; + + SioParam[port].m_psBaoHu->ForceWaitFlag = 0; + SioParam[port].m_psBaoHu->ForceWaitCnt = 0; + + SioParam[port].m_psBaoHu->SendCmdFlag = 0; + SioParam[port].m_psBaoHu->RevCmdFlag = 0; + + SioParam[port].m_psBaoHu->ReSendCmdFlag = 0; + SioParam[port].m_psBaoHu->LastGetCmdBuf = 0; +} + +int GetCmdFormPollCmdBuf(int port, u_char *buf, int len) +{ + int i, tmp; + u_char szbuf[MAX_MSG_BUF_SIZE]; + + if ((port < 0) || (port >= MaxPortNum)) + return 0; + + if (!IsBaoHuPtr(port)) + return 0; + + for (i = POLL_CMD_TYPE_NUM - 1; i >= 0; i--) + { + if (SioParam[port].m_psBaoHu->PollCmd[i].MsgCnt < 4) + { + SioParam[port].m_psBaoHu->PollCmd[i].MsgCnt = 0; + continue; + } + + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[i], szbuf, 2, false); + tmp = BYTE1(szbuf[0]) + BYTE0(szbuf[1]); + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[i], szbuf, tmp + 2, false); + + memmove((char*)buf, (char*)&szbuf[2], tmp); + + SioParam[port].m_psBaoHu->LastGetCmdBuf = i; + return tmp; + } + + return 0; +} + +int ReGetCmdFormPollCmdBuf(int port, u_char *buf, int len) +{ + int idx, ret, tmp; + u_char szbuf[MAX_MSG_BUF_SIZE]; + + if ((port < 0) || (port >= MaxPortNum)) + return 0; + + if (!IsBaoHuPtr(port)) + return false; + + SioParam[port].LostSyncCnt++; + + idx = SioParam[port].m_psBaoHu->LastGetCmdBuf; + + if (SioParam[port].m_psBaoHu->PollCmd[idx].MsgCnt < 4) + { + SioParam[port].m_psBaoHu->PollCmd[idx].MsgCnt = 0; + return 0; + } + + GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], szbuf, 2, false); + tmp = BYTE1(szbuf[0]) + BYTE0(szbuf[1]); + ret = GetDataFormBuf(&SioParam[port].m_psBaoHu->PollCmd[idx], szbuf, tmp + 2, false); + + memmove((char*)buf, (char*)&szbuf[2], tmp); + + return tmp; +} + +void SendCmdFormPollCmdBuf(int port) +{ + int len; + u_char buf[MAX_MSG_BUF_SIZE]; + + if ((port < 0) || (port >= MaxPortNum)) + return; + + //if (SioParam[port].OpenFlag == 0) + if(!ShmGetPortFlag(port, FLAG_OPEN)) + return; + + if (!IsBaoHuPtr(port)) + return; + + if (SioParam[port].m_psBaoHu->ForceWaitFlag + && SioParam[port].m_psBaoHu->ForceWaitCnt) + { + SioParam[port].m_psBaoHu->ForceWaitCnt--; + if (SioParam[port].m_psBaoHu->ForceWaitCnt == 0) + { + ClearCmdFormPollCmdBuf(port); // 清除当前命令 + //ClearCmdAllFlag(port); + } + } + + if (SioParam[port].m_psBaoHu->SendCmdFlag + && (SioParam[port].m_psBaoHu->RevCmdFlag == 0)) + { + SioParam[port].m_psBaoHu->RetryTimeCnt++; + if (SioParam[port].m_psBaoHu->RetryTimeCnt + < SioParam[port].m_psBaoHu->RetryTime) + return; + SioParam[port].m_psBaoHu->RetryTimeCnt = 0; + + SioParam[port].m_psBaoHu->RetryCnt++; + if (SioParam[port].m_psBaoHu->RetryCnt + > SioParam[port].m_psBaoHu->Retry) + { + SioParam[port].m_psBaoHu->RevCmdFlag = 1; + } + else + { + SioParam[port].m_psBaoHu->SendCmdFlag = 0; + SioParam[port].m_psBaoHu->RevCmdFlag = 0; + + SioParam[port].m_psBaoHu->ReSendCmdFlag = 1; + } + } + + if (SioParam[port].m_psBaoHu->SendCmdFlag + && SioParam[port].m_psBaoHu->RevCmdFlag) + { + ClearCmdFormPollCmdBuf(port); // 清除当前命令 + //ClearCmdAllFlag(port); + } + + if (SioParam[port].m_psBaoHu->WaitTime) + { + SioParam[port].m_psBaoHu->WaitTimeCnt++; + if (SioParam[port].m_psBaoHu->WaitTimeCnt + < SioParam[port].m_psBaoHu->WaitTime) + return; + } + SioParam[port].m_psBaoHu->WaitTimeCnt = 0; + + if (SioParam[port].m_psBaoHu->ReSendCmdFlag) + { + len = ReGetCmdFormPollCmdBuf(port, buf, MAX_MSG_BUF_SIZE); + } + else + { + len = GetCmdFormPollCmdBuf(port, buf, MAX_MSG_BUF_SIZE); + } + + if (len < 3) + return; + + if (UdpParam.Socket) + { + FillAndSendCmd(0, port, SDS_SIO_SEND_DATA, + (u_char*)&buf[2], len - 2); + SioParam[port].SendCharNum += (len - 2); + + SioParam[port].m_psBaoHu->SendCmdFlag = 1; + SioParam[port].m_psBaoHu->ReSendCmdFlag = 0; + SioParam[port].m_psBaoHu->RevCmdFlag = 0; + } + + if ((FAST_CMD_TYPE == SioParam[port].m_psBaoHu->LastGetCmdBuf) + || (UdpParam.Socket == 0)) + { + SioParam[port].m_psBaoHu->ForceWaitCnt + = BYTE1(buf[0]) + BYTE0(buf[1]) + TIMER_CNT - 1; + SioParam[port].m_psBaoHu->ForceWaitCnt /= TIMER_CNT; + if (SioParam[port].m_psBaoHu->ForceWaitCnt) + SioParam[port].m_psBaoHu->ForceWaitFlag = 1; + else + { + ClearCmdFormPollCmdBuf(port); // 清除当前命令 + //ClearCmdAllFlag(port); // 清除当前命令 + } + } +} + +void TimerProc(void) +{ + int i; + + for (i = 0; i < MaxPortNum; i++) + { + //if (SioParam[i].OpenFlag == 0) + if(!ShmGetPortFlag(i, FLAG_OPEN)) + { + ClearCmdFormPollCmdBuf(i); + continue; + } + + // wen 2004.10.25 以便规约模块控制发送时序 + if (FunCallPtr[SioParam[i].ProtocolIdx].Timer) + FunCallPtr[SioParam[i].ProtocolIdx].Timer(i); + else + SendCmdFormPollCmdBuf(i); + } +} + +void YkYtCommandProcess(int port, u_char *buf, int len) +{ + //if (SioParam[port].OpenFlag == 0) + if(!ShmGetPortFlag(port, FLAG_OPEN)) + return; + + if (SioParam[port].ProtocolIdx < 1) + return; + + if (FunCallPtr[SioParam[port].ProtocolIdx].YkYtProcess) + { + FunCallPtr[SioParam[port].ProtocolIdx].YkYtProcess(port, buf, len); + } +} + +void SystemRtuTime(void) +{ + int i; + + for (i = 0; i < MaxPortNum; i++) + { + //if (SioParam[i].OpenFlag == 0) + if(!ShmGetPortFlag(i, FLAG_OPEN)) + continue; + + if (!IsBaoHuPtr(i)) + continue; + + if (!FunCallPtr[SioParam[i].ProtocolIdx].SendSystemTime) + continue; + + // 下对时 + if(SioParam[i].m_psBaoHu->CheckTime == 2) + FunCallPtr[SioParam[i].ProtocolIdx].SendSystemTime(i); + } +} + +int InitBaohuLibMainFlag = 0; + +void PortRecvDataProcess(void) +{ + int i; + + for (i = 0; i < MaxPortNum; i++) + { + //if(SioParam[i].OpenFlag && (SioParam[i].RecvBuf.MsgCnt > 0)) + if (!SioParam[i].m_psBaoHu) + continue; + + if (FLAG_OPEN == SioParam[i].OpenFlag && (SioParam[i].RecvBuf.MsgCnt > 0)) + { + // 严格判断缓冲区长度 + if (SioParam[i].RecvBuf.MsgCnt > sizeof(SioParam[i].RecvBuf.MsgData)) + { + printf("WARN(%04d): RecvBuf is confusional(MsgCnt=%d, MaxLen=%d).\n", + _getpid(), SioParam[i].RecvBuf.MsgCnt, + sizeof(SioParam[i].RecvBuf.MsgData)); + SioParam[i].RecvBuf.MsgCnt = 0; + continue; + } + + if (FunCallPtr[SioParam[i].ProtocolIdx].RecvData) + { + //#ifdef _OS_LINUX_DEBUG_ + //printf("wen: SioParam[%d].RecvBuf.MsgCnt=%d\n", i + 1, SioParam[i].RecvBuf.MsgCnt); + //#endif + //printf("idx = %d\n", SioParam[i].ProtocolIdx); + FunCallPtr[SioParam[i].ProtocolIdx].RecvData(i, + SioParam[i].RecvBuf.MsgData, + SioParam[i].RecvBuf.MsgCnt); + // 端口接收到数据标志应该在这里清零 yizhonghu 20071029 + //SioParam[i].PortNoDataCnt = 0; + + // wen 2005.03.22 记录端口读取数据 + //RecordData(i, RECORD_RO_BUF,SioParam[i].RecvBuf.MsgData,SioParam[i].RecvBuf.MsgCnt); + + SioParam[i].RecvCharNum += SioParam[i].RecvBuf.MsgCnt; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.10.14 增加端口状态设置 + //SioParam[i].Status = TRUE; + //----------------------------------------------------- + // 对于规约为bypass时,不标记为运行正常 + if (SioParam[i].ProtocolIdx > 1) + { + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.24 如果仅仅是接收到数据,不认为端口状态为正常, + // 必须是修改了数据库点才认为是端口正常。子站除外。 + //SioParam[i].Status = TRUE; + //============================================================= + //TimeEx(&SioParam[i].dLineCommTime); + SioParam[i].Status = TRUE; + /*if (SioParam[i].m_psBaoHu) + { + // 如果为子站 + //if(SioParam[i].m_psBaoHu->PortType) + //{ + //if(1 == i) + // printf("设置端口%d端口状态为TRUE\n", i+1); + SioParam[i].Status = TRUE; + //} + } + else + { + SioParam[i].Status = TRUE; + if (i == SioParam[i].MasterPort) + SioParam[SioParam[i].SlavePort].Status = TRUE; + else + SioParam[SioParam[i].MasterPort].Status = TRUE; + }*/ + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + } + SioParam[i].RecvBuf.MsgCnt = 0; + } +} + +void BaohuLibMain(int netportnum) +{ + int msec, tmp1, tmp2; + static int systimecnt = 0; + + SYSTEMTIME stm; + + if (InitBaohuLibMainFlag == 0) + { + systimecnt = 0; + + msec = 0; + + // 读端口配置信息并设置6个网络端口 + //ReadPortConfigInfo(netportnum); + ReadPortConfigInfoEx(netportnum); + + InitBaohuLibMainFlag = 1; + } + + //msec = (msec + TIMER_CNT) % 1000; + + GetLocalTime(&stm); + + DayTime.Year = stm.wYear; + DayTime.Month = (stm.wMonth & 0xff); + DayTime.Day = (stm.wDay & 0xff); + DayTime.Hour = stm.wHour & 0xff; + DayTime.Min = stm.wMinute & 0xff; + DayTime.Sec = stm.wSecond & 0xff; + DayTime.mSec = stm.wMilliseconds; + Sleep(100); + // 网络端口写 + //SetUdpRecv(); + + // 所有端口定时器处理 + TimerProc(); + // wen 2004.10.25 以下代码放入timerproc中,以便规约模块控制发送时序 + //for (i = 0; i < MaxPortNum; i++) + //{ + // SendCmdFormPollCmdBuf(i); + //} + // 所有端口接收数据处理 + PortRecvDataProcess(); + PollAllPort(); + + //CreatUdpSetSock(); + OpenAllPort(); + + if (stm.wSecond == 0) + { + tmp2 = stm.wMinute * 60; + tmp1 = tmp2 - systimecnt; + if (tmp1 < 0) + tmp1 += 3600; + + // 每300秒RTU对时一次 + if ((tmp1 > SYSTEM_TIME) && (tmp2 != systimecnt)) + { + systimecnt = tmp2; + SystemRtuTime(); + } + } +} + +int GetMaxPort() +{ + return MaxPortNum; +} + +//******************************************************************** +//* 存储转发soe数据函数 * +//*参数:int provport : 转发端口 * +//* SOE_DEF *ptrSoe : 待存储的soe数据 * +//*返回值:int retval : soe数据数量 * +//******************************************************************** +int ProvWriteSoeData(int provport, SOE_DEF *ptrSoe) +{ + char szDbg[128]; + int iRear, iSoeNum; + + if(!IsBaoHuPtr(provport)) + return 0; + + iSoeNum = 0; + if(SioParam[provport].m_psBaoHu->ProvSoeBuf.ptrProvSoe) + { + iRear = SioParam[provport].m_psBaoHu->ProvSoeBuf.iRear; + memcpy((void *)&SioParam[provport].m_psBaoHu->ProvSoeBuf.ptrProvSoe[iRear], + (void *)ptrSoe, sizeof(SOE_DEF)); + + SioParam[provport].m_psBaoHu->ProvSoeBuf.iRear = (iRear+1) % MAX_PROV_SOE; + if(SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum < MAX_PROV_SOE) + { + SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum++; + } + else + { + SioParam[provport].m_psBaoHu->ProvSoeBuf.iFront + = (SioParam[provport].m_psBaoHu->ProvSoeBuf.iFront+1) % MAX_PROV_SOE; + sprintf(szDbg, "WARN(%04d): port%02d ProvSoe is overflow(max=%d).", + _getpid(), provport+1, MAX_PROV_SOE); + DebugPrint(szDbg); + } + + iSoeNum = SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum; + } + + return iSoeNum; +} + +//******************************************************************** +//* 初始化组数据定义函数 * +//*参数:int provport : 转发端口 * +//* SOE_DEF *ptrSoe : 获取soe数据的缓冲区 * +//*返回值:int retval : 剩余soe数据数量 * +//******************************************************************** +int ProvAndDelGetSoeData(int provport, SOE_DEF *ptrSoe) +{ + int iFront, iSoeNum; + SOE_DEF *ptrtmpSoe; + + if (!IsBaoHuPtr(provport)) + return 0; + + iSoeNum = 0; + if(SioParam[provport].m_psBaoHu->ProvSoeBuf.ptrProvSoe + && (SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum > 0)) + { + ptrtmpSoe = SioParam[provport].m_psBaoHu->ProvSoeBuf.ptrProvSoe; + iFront = SioParam[provport].m_psBaoHu->ProvSoeBuf.iFront; + memcpy((void *)ptrSoe, (void *)&ptrtmpSoe[iFront], sizeof(SOE_DEF)); + + SioParam[provport].m_psBaoHu->ProvSoeBuf.iFront = (iFront+1) % MAX_PROV_SOE; + SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum--; + iSoeNum = SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum; + } + + return iSoeNum; +} + +//******************************************************************** +//* 转发端口是否含有soe数据函数 * +//*参数:int provport : 转发端口 * +//******************************************************************** +int ProvHaveSoeData(int provport) +{ + if(!IsBaoHuPtr(provport)) + return 0; + + return SioParam[provport].m_psBaoHu->ProvSoeBuf.iSoeNum; +} + +//******************************************************************** +//* 发送数据函数 * +//*参数: int commid : 端口号 * +//* char *buf : 发送数据缓存区 * +//* int len : 发送数据长度 * +//*返回值:无 * +//******************************************************************** +void SendDataToPort(int commid, char *buf, int len) +{ +#ifdef FUNCTION_FEND + // 前置机为备用机时,端口下发数据处理方式 + if(!IsSendDatatoPort(commid)) + { + return; + } +#endif + +#ifdef OS_LINUX + AddNode(commid, (char *)buf, len); +#else + FillAndSendCmd(0, commid, SDS_SIO_SEND_DATA, (u_char*)buf, len); + // wen 2004.12.21 发送计数已经在发送时做了计算 + SioParam[commid].SendCharNum += len; +#endif +} + +//******************************************************************** +//* 发送遥控遥调数据函数 * +//*参 数:int commid : 端口号 * +//* char *buf : 发送数据缓存区 * +//* int len : 发送数据长度 * +//*返回值:无 * +//*说 明:发送来自scada系统(server)的遥控遥调命令 * +//******************************************************************** +void SendYkYtCommand(int commid, char *buf, int len) +{ + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + + DAY_TIME stime; + + // 串行端口 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.10.10 修改可以在netport下发 + //if(commid < MaxSerialPortNum) + if(commid < MaxPortNum) + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + { + if(!IsBaoHuPtr(commid)) + return ; + + if(!FunCallPtr) + return; + + if(FunCallPtr[SioParam[commid].ProtocolIdx].YkYtProcess) + { + if((buf[9] & 0x80) == 0) + { + // 保存遥控参数及环境变量 + GetLocalTimeEx(&stime); + memcpy((void *)&SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_sDayTime, + (void *)&stime, sizeof(DAY_TIME)); + SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iYkYtStep = buf[8]; + + // 该结构成员是用来保存操作类型的(不仅仅针对转发遥控) + SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iYkYtOperate = buf[9]; + SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iCmdFrom = YKYT_CMD_FROM_SCADA; + } + + FunCallPtr[SioParam[commid].ProtocolIdx].YkYtProcess(commid, (u_char *)buf, len); + } + } +} + +//******************************************************************** +//* 发送遥控遥调数据函数 * +//*参 数:int commid : 端口号 * +//* PROV_YKYT_PARAM *pParam : 遥控遥调参数 * +//*返回值:BOOL retval : 是否转发端口数据 * +//*说 明:发送来自转发端口的遥控遥调命令 * +//******************************************************************** +BOOL SendYkYtCommand2(int commid, YKYT_PARAM *pParam) +{ + DAY_TIME stime; + char Val[20]; + int iRealCommid; + // Val[0] --- 端口号(=commid) + // Val[1] + // Val[2] + // Val[3] + // Val[4] --- 控点号 + // Val[5] + // Val[6] + // Val[7] + // Val[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // Val[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + + // 串行端口 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.10.10 修改可以在netport下发 + //if(commid >= MaxSerialPortNum) + //{ + // return FALSE; + //} + if(commid >= MaxPortNum) + { + return FALSE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + memset(Val, 0, sizeof(Val)); + + // 非转发数据 + if(YKYT_SEND_DOWN == pParam->m_iYkYtUpDown) + { + iRealCommid = commid; + + Val[0] = (BYTE)iRealCommid; + Val[1] = (BYTE)((iRealCommid & 0xFF00) >> 8); + Val[2] = (BYTE)((iRealCommid & 0xFF0000) >> 16); + Val[3] = (BYTE)((iRealCommid & 0xFF000000) >> 24); + + Val[4] = (BYTE)pParam->m_iYkYtPnt; + Val[5] = (BYTE)((pParam->m_iYkYtPnt & 0xFF00) >> 8); + Val[6] = (BYTE)((pParam->m_iYkYtPnt & 0xFF0000) >> 16); + Val[7] = (BYTE)((pParam->m_iYkYtPnt & 0xFF000000) >> 24); + + Val[8] = (BYTE)pParam->m_iYkYtStep; + Val[9] = (BYTE)pParam->m_iYkYtOperate; + } + else + { + if(!IsBaoHuPtr(commid)) + return FALSE; + + if(YKYT_CMD_FROM_SCADA == SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iCmdFrom) + { + // wen 2005.10.08 非转发数据,从而上送给scada服务器 + Val[0] = LOBYTE(pParam->m_iYkYtPnt); + Val[1] = HIBYTE(pParam->m_iYkYtPnt); + if(pParam->m_iYkYtOperate == 3) + { + Val[2] = 0; + } + else + { + Val[2] = 1; + } + SetYkYtAckData(commid, Val); + + return TRUE; + } + else if((IsProvYkYtAck(commid, &SioParam[commid].m_psBaoHu->ProvYkYtMsg)) + && (SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iYkYtPointIdx == pParam->m_iYkYtPnt)) + { + iRealCommid = SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iProvPortIdx; + + // 转发站号 + Val[0] = (BYTE)iRealCommid; + Val[1] = (BYTE)((iRealCommid & 0xFF00) >> 8); + Val[2] = (BYTE)((iRealCommid & 0xFF0000) >> 16); + Val[3] = (BYTE)((iRealCommid & 0xFF000000) >> 24); + // 转发控点号 + Val[4] = (BYTE)SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx; + Val[5] = (BYTE)((SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx & 0xFF00) >> 8); + Val[6] = (BYTE)((SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx & 0xFF0000) >> 16); + Val[7] = (BYTE)((SioParam[commid].m_psBaoHu->ProvYkYtMsg.m_iProvYkYtPointIdx & 0xFF000000) >> 24); + + Val[8] = (BYTE)pParam->m_iYkYtStep; + Val[9] = (BYTE)(pParam->m_iYkYtOperate); + Val[9] |= 0x80; + } + else// 异常数据 + { + return FALSE; + } + } + + if(FunCallPtr) + { + if(FunCallPtr[SioParam[iRealCommid].ProtocolIdx].YkYtProcess) + { + if(YKYT_SEND_UP != pParam->m_iYkYtUpDown) + { + // 保存遥控参数及环境变量 + GetLocalTimeEx(&stime); + memcpy((void *)&SioParam[iRealCommid].m_psBaoHu->ProvYkYtMsg.m_sDayTime, + (void *)&stime, sizeof(DAY_TIME)); + SioParam[iRealCommid].m_psBaoHu->ProvYkYtMsg.m_iYkYtStep = pParam->m_iYkYtStep; + + SioParam[iRealCommid].m_psBaoHu->ProvYkYtMsg.m_iCmdFrom = YKYT_CMD_FROM_PROVPORT; + } + + FunCallPtr[SioParam[iRealCommid].ProtocolIdx].YkYtProcess(iRealCommid, (u_char *)Val, 10); + } + } + + return TRUE; +} + +//******************************************************************** +//* 查找转发控点的转发点函数 * +//*参数: int commid : 转发端口号 * +//* int ykytpnt: 转发的遥控遥调点 * +//* SIO_PARAM_BAOHU_DEF *pBaohuParam :转发端口保护参数 * +//*返回值:int retval : 对应的实际转发点号 * +//******************************************************************** +int FindProvPntFromYkYtPnt(int commid, int ykytpnt, SIO_PARAM_BAOHU_DEF *pBaohuParam) +{ + int i; + PROV_DI_PNT *diprovptr; + + if(!pBaohuParam) + { + printf("TIP_(%04d): commid=%d psBaoHu is NULL.\n", + _getpid(), commid + 1); + return -1; + } + + diprovptr = (PROV_DI_PNT*)pBaohuParam->DiPtr; + + if(!diprovptr) + { + printf("TIP_(%04d): commid=%d DiPtr is NULL.\n", + _getpid(), commid + 1); + return -1; + } + + for(i=0; iDiNum; i++) + { + if(((int)diprovptr[i].ControlNo) == ykytpnt) + break; + } + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d ykytpnt=%d", _getpid(), commid + 1, ykytpnt); + if(iDiNum) + { + printf(" ControlNo=%d.\n", diprovptr[i].ControlNo); + } + else + { + printf(".\n"); + } + } + + if(i >= pBaohuParam->DiNum) + return -1; + else + return i; +} + +BOOL ProvPortYkYtIsTimeOut(int commid, PROV_YKYT_DEF *pProvYkYt) +{ + time_t iSaveTime, iCurTime; + struct tm changetm; + DAY_TIME CurTime; + BOOL bReturn; + + changetm.tm_hour = pProvYkYt->m_sDayTime.Hour; + changetm.tm_mday = pProvYkYt->m_sDayTime.Day; + changetm.tm_min = pProvYkYt->m_sDayTime.Min; + changetm.tm_mon = pProvYkYt->m_sDayTime.Month-1; + changetm.tm_sec = pProvYkYt->m_sDayTime.Sec; + changetm.tm_year = pProvYkYt->m_sDayTime.Year - 1900; + changetm.tm_isdst = -1; + iSaveTime = mktime(&changetm); + + GetLocalTimeEx(&CurTime); + changetm.tm_hour = CurTime.Hour; + changetm.tm_mday = CurTime.Day; + changetm.tm_min = CurTime.Min; + changetm.tm_mon = CurTime.Month-1; + changetm.tm_sec = CurTime.Sec; + changetm.tm_year = CurTime.Year - 1900; + changetm.tm_isdst = -1; + iCurTime = mktime(&changetm); + + if((iCurTime-iSaveTime) > pProvYkYt->m_iTimeOut) + { + bReturn = TRUE; + } + else + { + bReturn = FALSE; + } + + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid =%d timeout=%d.\n", + _getpid(), commid + 1, pProvYkYt->m_iTimeOut); + + printf("TIP_(%04d): curtime %02d:%02d:%02d.\n", + _getpid(), CurTime.Hour, CurTime.Min, CurTime.Sec); + + printf("TIP_(%04d): savetime %02d:%02d:%02d.\n", + _getpid(), pProvYkYt->m_sDayTime.Hour, + pProvYkYt->m_sDayTime.Min, + pProvYkYt->m_sDayTime.Sec); + } + + return bReturn; +} + +BOOL IsProvYkYtAck(int commid, PROV_YKYT_DEF *pProvYkYt) +{ + BOOL bReturn; + + bReturn = FALSE; + + if((STEP_YKYT_SELECT == pProvYkYt->m_iYkYtStep) + && (pProvYkYt->m_iProvPntIdx >= 0)) + { + if(!ProvPortYkYtIsTimeOut(commid, pProvYkYt)) + { + bReturn = TRUE; + } + else + { + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid=%d ykytpnt is judging timeout.\n", + _getpid(), commid + 1); + } + } + } + else + { + if(ShmGetDispYkYtFlag()) + { + printf("TIP_(%04d): commid=%d ykyt is not in condition. step=%d, provpntidx=%d.\n", + _getpid(), commid + 1, pProvYkYt->m_iYkYtStep, pProvYkYt->m_iProvPntIdx); + } + } + + return bReturn; +} + +BOOL ShmGetDispYkYtFlag() +{ + return FALSE; +} + +BOOL ShmGetDispHostLinkFlag() +{ + return TRUE; +} + +void PortMemoryMalloc(int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam) +{ + int i, k, increase; + char entry[128], section[128], szbuf[128]; + char *ptr, szDebugInfo[256]; + + AI_DEF aipntmsg; + DI_DEF dipntmsg; + + PROV_AI_PNT aiprovpnt; + PROV_DI_PNT diprovpnt; + PROV_PI_PNT piprovpnt; + + if ((commid < 0) || (commid >= MaxPortNum)) + return; + + if (!IsBaoHuPtr(commid)) + return; + + char szPortConfig[256]; + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + + switch(type) + { + case PROTOCOL_MASTER: + //SioParam[commid].PortType = PROTOCOL_MASTER; + if (pBaohuParam->AiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(aiptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->AiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->AiPtr); + } + + if (pBaohuParam->DiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(diptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->DiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->DiPtr); + } + + if (pBaohuParam->PiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(piptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->PiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->PiPtr); + } + + if(pBaohuParam->AiNum > 0) + { + pBaohuParam->AiPtr + = (AI_DEF*)malloc(sizeof(AI_DEF)*pBaohuParam->AiNum); + + if (pBaohuParam->AiPtr) + { + memset((char*)pBaohuParam->AiPtr, 0, + sizeof(AI_DEF)*pBaohuParam->AiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d aiptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(AI_DEF)*pBaohuParam->AiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->AiNum = 0; + } + } + else + { + pBaohuParam->AiNum = 0; + pBaohuParam->AiPtr = NULL; + } + + if(pBaohuParam->DiNum > 0) + { + pBaohuParam->DiPtr + = (DI_DEF*)malloc(sizeof(DI_DEF)*pBaohuParam->DiNum); + + if (pBaohuParam->DiPtr) + { + memset((char*)pBaohuParam->DiPtr, 0, + sizeof(DI_DEF)*pBaohuParam->DiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d diptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(DI_DEF)*pBaohuParam->DiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->DiNum = 0; + } + + } + else + { + pBaohuParam->DiNum = 0; + pBaohuParam->DiPtr = NULL; + } + + if(pBaohuParam->PiNum > 0) + { + pBaohuParam->PiPtr + = (PI_DEF*)malloc(sizeof(PI_DEF)*pBaohuParam->PiNum); + + if (pBaohuParam->PiPtr) + { + memset((char*)pBaohuParam->PiPtr, 0, + sizeof(PI_DEF)*pBaohuParam->PiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d piptr=malloc(%d) is failed.\n", + _getpid(), commid, sizeof(PI_DEF)*pBaohuParam->PiNum); + OutputDebugString((LPCWSTR)szDebugInfo + 1); + pBaohuParam->PiNum = 0; + } + } + else + { + pBaohuParam->PiNum = 0; + pBaohuParam->PiPtr = NULL; + } + + sprintf(entry, "Port%d", commid + 1); + for (i = 0; i < pBaohuParam->AiNum; i++) + { + sprintf(section, "Ai%dPolar", i+1); + +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d):[%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + { + // wen 2005.09.28 缺省设置为1 + aipntmsg.Polar = 1; + SetPntMsg(commid, i, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + continue; + } + + aipntmsg.Polar = atoi(szbuf) ? 1 : 0; + SetPntMsg(commid, i, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + + // wen 2005.09.13 增加顺序增加配置 + sprintf(section, "Ai%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if(strlen(szbuf) == 0) + continue; + increase = atoi(szbuf); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.12.01 修改连续增加的读取 + //if(increase > 0) + //{ + // for(k=i+1; k= pBaohuParam->AiNum) + // { + // break; + // } + + // SetPntMsg(commid, k, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + // } + + // i = k; + //} + //================================================================ + if(increase > 0) + { + for(k=0; k= pBaohuParam->AiNum) + { + break; + } + + SetPntMsg(commid, i+k+1, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + } + + i += k; + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + + GetPrivateProString(entry, "DiAllCtrlNo", "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + { + dipntmsg.ControlNo = atoi(szbuf); + for (i = 0; i < SioParam[commid].m_psBaoHu->DiNum; i++) + { + SetPntMsg(commid, i, (void*)&dipntmsg, DI_PNT_TYPE, PNT_CTRL_NO); + dipntmsg.ControlNo++; + } + } + + for (i = 0; i < SioParam[commid].m_psBaoHu->DiNum; i++) + { + sprintf(section, "Di%dCtrlNo", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d):[%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + continue; + + dipntmsg.ControlNo = atoi(szbuf); + SetPntMsg(commid, i, (void*)&dipntmsg, DI_PNT_TYPE, PNT_CTRL_NO); + } + break; + + case PROTOCOL_SLAVE: + if ((ProvPortCnt+1) > MAX_PROV_PORT_NUM) + { + sprintf(szDebugInfo, "WARN(%04d): commid_%02d is error, the Prov Port is over !!!\n", + _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + break; + } + ProvPortCnt++; + //SioParam[commid].PortType = PROTOCOL_SLAVE; + + if (pBaohuParam->AiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(aiptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->AiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->AiPtr); + } + + if (pBaohuParam->DiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(diptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->DiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->DiPtr); + } + + if (pBaohuParam->PiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(piptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->PiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->PiPtr); + } + + if(pBaohuParam->ProvSoeBuf.ptrProvSoe) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(soeptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->ProvSoeBuf.ptrProvSoe); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->ProvSoeBuf.ptrProvSoe); + } + + if(pBaohuParam->AiNum > 0) + { + pBaohuParam->AiPtr + = (PROV_AI_PNT*)malloc(sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + + if (pBaohuParam->AiPtr) + { + memset((char*)pBaohuParam->AiPtr, 0, + sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d aiptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->AiNum = 0; + } + } + else + { + pBaohuParam->AiPtr = NULL; + pBaohuParam->AiNum = 0; + } + + if(pBaohuParam->DiNum > 0) + { + pBaohuParam->DiPtr + = (PROV_DI_PNT*)malloc(sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + if (pBaohuParam->DiPtr) + { + memset((char*)pBaohuParam->DiPtr, 0, + sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d diptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->DiNum = 0; + } + + pBaohuParam->ProvSoeBuf.ptrProvSoe + = (SOE_DEF *)malloc(sizeof(SOE_DEF)*MAX_PROV_SOE); + if(pBaohuParam->ProvSoeBuf.ptrProvSoe) + { + memset((char *)pBaohuParam->ProvSoeBuf.ptrProvSoe, 0, + sizeof(SOE_DEF)*MAX_PROV_SOE); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d soeptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(SOE_DEF)*MAX_PROV_SOE); + OutputDebugString((LPCWSTR)szDebugInfo); + } + } + else + { + pBaohuParam->DiNum = 0; + pBaohuParam->DiPtr = NULL; + pBaohuParam->ProvSoeBuf.ptrProvSoe = NULL; + } + + if(pBaohuParam->PiNum > 0) + { + pBaohuParam->PiPtr + = (PROV_PI_PNT*)malloc(sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + if (pBaohuParam->PiPtr) + { + memset((char*)pBaohuParam->PiPtr, 0, + sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d piptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->PiNum = 0; + } + } + else + { + pBaohuParam->PiPtr = NULL; + pBaohuParam->PiNum = 0; + } + + sprintf(entry, "Port%d", commid + 1); + for (i = 0; i < pBaohuParam->AiNum; i++) + { + aiprovpnt.fFactor = 1.0; + sprintf(section, "ProvAi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "####(%04d): %s#\n", _getpid(), szbuf); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + + ptr = strstr(szbuf, "A"); + if (!ptr) + continue; + aiprovpnt.PortNo = atoi(szbuf) - 1; + aiprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "TIP_: commid_%02d provpnt=%d, realport=%d, realpnt=%d\n", + commid + 1, i + 1, aiprovpnt.PortNo, aiprovpnt.PntNo); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + ptr = strstr(ptr, ","); + if(ptr) + { + aiprovpnt.fFactor = (float)atof(ptr+1); + } + + SetPorvPntMsg(commid, i, &aiprovpnt, AI_PNT_TYPE, PNT_PROV_MSG); + + sprintf(section, "ProvAi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvAi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if(strlen(szbuf)) + { + break; + } + + i++; + aiprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &aiprovpnt, AI_PNT_TYPE, PNT_PROV_MSG); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "TIP_: commid_%02d provpnt=%d, realport=%d, realpnt=%d\n", + commid + 1, i + 1, aiprovpnt.PortNo, aiprovpnt.PntNo); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + k--; + } + } + + GetPrivateProString(entry, "ProvDiAllCtrlNo", "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + { + diprovpnt.ControlNo = atoi(szbuf); + for (i = 0; i < pBaohuParam->DiNum; i++) + { + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + diprovpnt.ControlNo++; + } + } + + for (i = 0; i < pBaohuParam->DiNum; i++) + { + sprintf(section, "ProvDi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; + + ptr = strstr(szbuf, "D"); + if (!ptr) + continue; + diprovpnt.PortNo = atoi(szbuf) - 1; + diprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; + + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_PROV_MSG); + + ptr = strstr(szbuf, ","); + if (ptr) + { + diprovpnt.ControlNo = atoi((char*)(ptr+1)); + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + // wen 2005.03.28 增加连续的控点配置 + else + { + diprovpnt.ControlNo = -1; + } + + sprintf(section, "ProvDi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvDi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + break; + + i++; + diprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_PROV_MSG); + k--; + + // wen 2005.03.28 增加连续的控点配置 + if(diprovpnt.ControlNo >= 0) + { + diprovpnt.ControlNo++; + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + } + } + + for (i = 0; i < pBaohuParam->DiNum; i++) + { + sprintf(section, "ProvDi%dCtrlNo", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + continue; + + diprovpnt.ControlNo = atoi(szbuf); + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + + for (i = 0; i < pBaohuParam->PiNum; i++) + { + piprovpnt.fFactor = 1.0; + sprintf(section, "ProvPi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; + + ptr = strstr(szbuf, "P"); + if (!ptr) + continue; + piprovpnt.PortNo = atoi(szbuf) - 1; + piprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; + + ptr = strstr(ptr, ","); + if(ptr) + { + piprovpnt.fFactor = (float)atof(ptr+1); + } + + SetPorvPntMsg(commid, i, &piprovpnt, PI_PNT_TYPE, PNT_PROV_MSG); + + sprintf(section, "ProvPi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvPi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + break; + + i++; + piprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &piprovpnt, PI_PNT_TYPE, PNT_PROV_MSG); + k--; + } + } + break; + + default: + break; + } +} + +void PortMemoryMallocEx(int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam) +{ + char szDebugInfo[256]; + + if ((commid < 0) || (commid >= MaxPortNum)) + return; + + if (!IsBaoHuPtr(commid)) + return; + + char szPortConfig[256]; + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + + switch(type) + { + case PROTOCOL_MASTER: + //SioParam[commid].PortType = PROTOCOL_MASTER; + if (pBaohuParam->AiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(aiptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->AiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->AiPtr); + } + + if (pBaohuParam->DiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(diptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->DiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->DiPtr); + } + + if (pBaohuParam->PiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(piptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->PiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->PiPtr); + } + + if(pBaohuParam->AiNum > 0) + { + pBaohuParam->AiPtr + = (AI_DEF*)malloc(sizeof(AI_DEF)*pBaohuParam->AiNum); + + if (pBaohuParam->AiPtr) + { + memset((char*)pBaohuParam->AiPtr, 0, + sizeof(AI_DEF)*pBaohuParam->AiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d aiptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(AI_DEF)*pBaohuParam->AiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->AiNum = 0; + } + } + else + { + pBaohuParam->AiNum = 0; + pBaohuParam->AiPtr = NULL; + } + + if(pBaohuParam->DiNum > 0) + { + pBaohuParam->DiPtr + = (DI_DEF*)malloc(sizeof(DI_DEF)*pBaohuParam->DiNum); + + if (pBaohuParam->DiPtr) + { + memset((char*)pBaohuParam->DiPtr, 0, + sizeof(DI_DEF)*pBaohuParam->DiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d diptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(DI_DEF)*pBaohuParam->DiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->DiNum = 0; + } + + } + else + { + pBaohuParam->DiNum = 0; + pBaohuParam->DiPtr = NULL; + } + + if(pBaohuParam->PiNum > 0) + { + pBaohuParam->PiPtr + = (PI_DEF*)malloc(sizeof(PI_DEF)*pBaohuParam->PiNum); + + if (pBaohuParam->PiPtr) + { + memset((char*)pBaohuParam->PiPtr, 0, + sizeof(PI_DEF)*pBaohuParam->PiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d piptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PI_DEF)*pBaohuParam->PiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->PiNum = 0; + } + } + else + { + pBaohuParam->PiNum = 0; + pBaohuParam->PiPtr = NULL; + } + break; + + case PROTOCOL_SLAVE: + if ((ProvPortCnt+1) > MAX_PROV_PORT_NUM) + { + sprintf(szDebugInfo, "WARN(%04d): commid_%02d is error, the Prov Port is over !!!\n", + _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + break; + } + ProvPortCnt++; + + if (pBaohuParam->AiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(aiptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->AiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->AiPtr); + } + + if (pBaohuParam->DiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(diptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->DiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->DiPtr); + } + + if (pBaohuParam->PiPtr) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(piptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->PiPtr); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->PiPtr); + } + + if(pBaohuParam->ProvSoeBuf.ptrProvSoe) + { + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free(soeptr=0x%08x).\n", + _getpid(), commid + 1, pBaohuParam->ProvSoeBuf.ptrProvSoe); + OutputDebugString((LPCWSTR)szDebugInfo); + free(pBaohuParam->ProvSoeBuf.ptrProvSoe); + } + + if(pBaohuParam->AiNum > 0) + { + pBaohuParam->AiPtr + = (PROV_AI_PNT*)malloc(sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + + if (pBaohuParam->AiPtr) + { + memset((char*)pBaohuParam->AiPtr, 0, + sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d aiptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_AI_PNT)*pBaohuParam->AiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->AiNum = 0; + } + } + else + { + pBaohuParam->AiPtr = NULL; + pBaohuParam->AiNum = 0; + } + + if(pBaohuParam->DiNum > 0) + { + pBaohuParam->DiPtr + = (PROV_DI_PNT*)malloc(sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + if (pBaohuParam->DiPtr) + { + memset((char*)pBaohuParam->DiPtr, 0, + sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d diptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_DI_PNT)*pBaohuParam->DiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->DiNum = 0; + } + + pBaohuParam->ProvSoeBuf.ptrProvSoe + = (SOE_DEF *)malloc(sizeof(SOE_DEF)*MAX_PROV_SOE); + if(pBaohuParam->ProvSoeBuf.ptrProvSoe) + { + memset((char *)pBaohuParam->ProvSoeBuf.ptrProvSoe, 0, + sizeof(SOE_DEF)*MAX_PROV_SOE); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d soeptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(SOE_DEF)*MAX_PROV_SOE); + OutputDebugString((LPCWSTR)szDebugInfo); + } + } + else + { + pBaohuParam->DiNum = 0; + pBaohuParam->DiPtr = NULL; + pBaohuParam->ProvSoeBuf.ptrProvSoe = NULL; + } + + if(pBaohuParam->PiNum > 0) + { + pBaohuParam->PiPtr + = (PROV_PI_PNT*)malloc(sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + if (pBaohuParam->PiPtr) + { + memset((char*)pBaohuParam->PiPtr, 0, + sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + } + else + { + sprintf(szDebugInfo, "ERR_(%04d): commid_%02d piptr=malloc(%d) is failed.\n", + _getpid(), commid + 1, sizeof(PROV_PI_PNT)*pBaohuParam->PiNum); + OutputDebugString((LPCWSTR)szDebugInfo); + pBaohuParam->PiNum = 0; + } + } + else + { + pBaohuParam->PiPtr = NULL; + pBaohuParam->PiNum = 0; + } + break; + + default: + break; + } +} + +BOOL PortDataPntInit(int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam) +{ + int i, k, increase; + char entry[128], section[128], szbuf[128]; + char *ptr; + + AI_DEF aipntmsg; + DI_DEF dipntmsg; + + PROV_AI_PNT aiprovpnt; + PROV_DI_PNT diprovpnt; + PROV_PI_PNT piprovpnt; + + if((commid < 0) || (commid >= MaxPortNum)) + { + return FALSE; + } + + if(!IsBaoHuPtr(commid)) + { + return FALSE; + } + + char szPortConfig[256]; + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); + + switch(type) + { + case PROTOCOL_MASTER: + sprintf(entry, "Port%d", commid + 1); + for (i = 0; i < pBaohuParam->AiNum; i++) + { + sprintf(section, "Ai%dPolar", i+1); + +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d):[%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + { + // wen 2005.09.28 缺省设置为1 + aipntmsg.Polar = 1; + SetPntMsg(commid, i, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + continue; + } + + aipntmsg.Polar = atoi(szbuf) ? 1 : 0; + SetPntMsg(commid, i, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + + // wen 2005.09.13 增加顺序增加配置 + sprintf(section, "Ai%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if(strlen(szbuf) == 0) + continue; + increase = atoi(szbuf); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.12.01 修改连续增加的读取 + //if(increase > 0) + //{ + // for(k=i+1; k= pBaohuParam->AiNum) + // { + // break; + // } + + // SetPntMsg(commid, k, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + // } + + // i = k; + //} + //================================================================ + if(increase > 0) + { + for(k=0; k= pBaohuParam->AiNum) + { + break; + } + + SetPntMsg(commid, i+k+1, (void*)&aipntmsg, AI_PNT_TYPE, PNT_POLAR); + } + + i += k; + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + + GetPrivateProString(entry, "DiAllCtrlNo", "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + { + dipntmsg.ControlNo = atoi(szbuf); + for (i = 0; i < SioParam[commid].m_psBaoHu->DiNum; i++) + { + SetPntMsg(commid, i, (void*)&dipntmsg, DI_PNT_TYPE, PNT_CTRL_NO); + dipntmsg.ControlNo++; + } + } + + for (i = 0; i < SioParam[commid].m_psBaoHu->DiNum; i++) + { + sprintf(section, "Di%dCtrlNo", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d):[%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + continue; + + dipntmsg.ControlNo = atoi(szbuf); + SetPntMsg(commid, i, (void*)&dipntmsg, DI_PNT_TYPE, PNT_CTRL_NO); + } + break; + + case PROTOCOL_SLAVE: + sprintf(entry, "Port%d", commid + 1); + for (i = 0; i < pBaohuParam->AiNum; i++) + { + aiprovpnt.fFactor = 1.0; + sprintf(section, "ProvAi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "####(%04d): %s#\n", _getpid(), szbuf); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + + ptr = strstr(szbuf, "A"); + if (!ptr) + continue; + aiprovpnt.PortNo = atoi(szbuf) - 1; + aiprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "TIP_: commid_%02d provpnt=%d, realport=%d, realpnt=%d\n", + commid + 1, i + 1, aiprovpnt.PortNo, aiprovpnt.PntNo); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + ptr = strstr(ptr, ","); + if(ptr) + { + aiprovpnt.fFactor = (float)atof(ptr+1); + } + + SetPorvPntMsg(commid, i, &aiprovpnt, AI_PNT_TYPE, PNT_PROV_MSG); + + sprintf(section, "ProvAi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvAi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + break; + + i++; + aiprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &aiprovpnt, AI_PNT_TYPE, PNT_PROV_MSG); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, "TIP_: commid_%02d provpnt=%d, realport=%d, realpnt=%d\n", + commid + 1, i + 1, aiprovpnt.PortNo, aiprovpnt.PntNo); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + k--; + } + } + + GetPrivateProString(entry, "ProvDiAllCtrlNo", "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + { + diprovpnt.ControlNo = atoi(szbuf); + for (i = 0; i < pBaohuParam->DiNum; i++) + { + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + diprovpnt.ControlNo++; + } + } + + for (i = 0; i < pBaohuParam->DiNum; i++) + { + sprintf(section, "ProvDi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; + + ptr = strstr(szbuf, "D"); + if (!ptr) + continue; + diprovpnt.PortNo = atoi(szbuf) - 1; + diprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; + + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_PROV_MSG); + + ptr = strstr(szbuf, ","); + if (ptr) + { + diprovpnt.ControlNo = atoi((char*)(ptr+1)); + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + // wen 2005.03.28 增加连续的控点配置 + else + { + diprovpnt.ControlNo = -1; + } + + sprintf(section, "ProvDi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvDi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + break; + + i++; + diprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_PROV_MSG); + k--; + + // wen 2005.03.28 增加连续的控点配置 + if(diprovpnt.ControlNo >= 0) + { + diprovpnt.ControlNo++; + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + } + } + + for (i = 0; i < pBaohuParam->DiNum; i++) + { + sprintf(section, "ProvDi%dCtrlNo", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf) == 0) + continue; + + diprovpnt.ControlNo = atoi(szbuf); + SetPorvPntMsg(commid, i, &diprovpnt, DI_PNT_TYPE, PNT_CTRL_NO); + } + + for (i = 0; i < pBaohuParam->PiNum; i++) + { + piprovpnt.fFactor = 1.0; + sprintf(section, "ProvPi%d", i+1); +#ifdef _OS_WINDOWS_DEBUG_ + sprintf(szDebugInfo, ">>>>(%04d): [%s]<%s>\n", _getpid(), entry, section); + OutputDebugString((LPCWSTR)szDebugInfo); +#endif + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + StringToUpper(szbuf); + if (strlen(szbuf) == 0) + continue; + + ptr = strstr(szbuf, "P"); + if (!ptr) + continue; + piprovpnt.PortNo = atoi(szbuf) - 1; + piprovpnt.PntNo = atoi((char*)(ptr+1)) - 1; + + ptr = strstr(ptr, ","); + if(ptr) + { + piprovpnt.fFactor = (float)atof(ptr+1); + } + + SetPorvPntMsg(commid, i, &piprovpnt, PI_PNT_TYPE, PNT_PROV_MSG); + + sprintf(section, "ProvPi%dInc", i+1); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + k = atoi(szbuf); + while(k > 0) + { + sprintf(section, "ProvPi%d", i+2); + GetPrivateProString(entry, section, "", szbuf, 120, szPortConfig); + if (strlen(szbuf)) + break; + + i++; + piprovpnt.PntNo++; + SetPorvPntMsg(commid, i, &piprovpnt, PI_PNT_TYPE, PNT_PROV_MSG); + k--; + } + } + break; + + default: + break; + } + + return TRUE; +} + +void PortWriteDataFree(int commid) +{ +/* + char szDebugInfo[256]; + + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free all write data begin...\n", + _getpid(), commid); + OutputDebugString((LPCWSTR)szDebugInfo); + + while (SioParam[commid].WriteData) + { + DelNode(commid); + } + + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free all write data end.\n", + _getpid(), commid); + OutputDebugString((LPCWSTR)szDebugInfo); + */ +} + +void PortMemoryFree(int commid, SIO_PARAM_DEF *pGenParam) +{ + char szDebugInfo[256]; + + //sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free memory begin.\n", _getpid(), commid); + //OutputDebugString((LPCWSTR)szDebugInfo); + if (pGenParam->m_psBaoHu) + { + if (pGenParam->m_psBaoHu->AiPtr) + { + free(pGenParam->m_psBaoHu->AiPtr); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free ai memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + if (pGenParam->m_psBaoHu->DiPtr) + { + free(pGenParam->m_psBaoHu->DiPtr); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free di memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + if (pGenParam->m_psBaoHu->PiPtr) + { + free(pGenParam->m_psBaoHu->PiPtr); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free pi memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + if(pGenParam->m_psBaoHu->ProvSoeBuf.ptrProvSoe) + { + free(pGenParam->m_psBaoHu->ProvSoeBuf.ptrProvSoe); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free ProvSoe memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + free(pGenParam->m_psBaoHu); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free psBaohu memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + if (pGenParam->m_psSerial) + { + free(pGenParam->m_psSerial); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free psSerial memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + if (pGenParam->ExtInfo) + { + // wen 2005.04.13 规约结束时释放内存 + if (FunCallPtr[SioParam[commid].ProtocolIdx].ProtocolExit) + { + FunCallPtr[SioParam[commid].ProtocolIdx].ProtocolExit(commid); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d Protocol Exit.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + HEAP_FREE(pGenParam->ExtInfo); + //free(pGenParam->ExtInfo); + sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free ExtInfo memory.\n", _getpid(), commid + 1); + OutputDebugString((LPCWSTR)szDebugInfo); + } + + PortWriteDataFree(commid); + + pGenParam->m_psBaoHu = NULL; + pGenParam->m_psSerial = NULL; + pGenParam->ExtInfo = NULL; + + //sprintf(szDebugInfo, "TIP_(%04d): commid_%02d free memory end.\n", _getpid(), commid + 1); + //OutputDebugString((LPCWSTR)szDebugInfo); +} + +BOOL IsBaoHuPtr(int commid) +{ + char szInfo[256]; + + if ((commid < 0) || (commid >=MaxPortNum)) + return FALSE; + + if (!SioParam[commid].m_psBaoHu) + { + sprintf(szInfo, "commid_%02d psBaoHu is NULL.\n", commid + 1); + PrintFormatMessage(MSG_CLASS_TIP, szInfo); + return FALSE; + } + + return TRUE; +} + +BOOL IsExtInfoPtr(int commid) +{ + char szInfo[256]; + + if ((commid < 0) || (commid >=MaxPortNum)) + return FALSE; + + if (!SioParam[commid].ExtInfo) + { + sprintf(szInfo, "commid_%02d ExtInfo is NULL.\n", commid + 1); + PrintFormatMessage(MSG_CLASS_TIP, szInfo); + return FALSE; + } + + return TRUE; +} + +BOOL IsSerialPtr(int commid) +{ + char szInfo[256]; + + if ((commid < 0) || (commid >=MaxPortNum)) + return FALSE; + + if (!SioParam[commid].m_psSerial) + { + sprintf(szInfo, "commid_%02d psSerial is NULL.\n", commid + 1); + PrintFormatMessage(MSG_CLASS_TIP, szInfo); + return FALSE; + } + + return TRUE; +} + +int ShmGetPortFlag(int commid, int rwflag) +{ + if(commid >= DEFAULT_MAX_PORT_NUM) + return 0; + + return SioParam[commid].OpenFlag; +} + +void SendProtectCmdToDev(int commid, RTUMSG *rtumsg) +{ + //if(SioParam[commid].OpenFlag == 0) + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + if(SioParam[commid].ProtocolIdx < 1) + { + return; + } + + if(FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess) + { + FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess(commid, rtumsg, FALSE); + } +} + +void PutBaohuDataToPort(RTUMSG *rtumsg) +{ + int commid; + + commid = rtumsg->PortIdx; + //if(SioParam[commid].OpenFlag == 0) + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + if(SioParam[commid].ProtocolIdx < 1) + { + return; + } + + if(FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess) + { + FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess(commid, rtumsg, TRUE); + } +} + +void PutBaohuDataToPortEx(int commid, RTUMSG *rtumsg) +{ + if(!ShmGetPortFlag(commid, FLAG_OPEN)) + { + return; + } + + if(SioParam[commid].ProtocolIdx < 1) + { + return; + } + + if(FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess) + { + FunCallPtr[SioParam[commid].ProtocolIdx].BaoHuCmdProcess(commid, rtumsg, TRUE); + } +} + +void SendDataToAllScadaProtectPort(RTUMSG *rtumsg) +{ + int i, ProtocolIdx; + + ProtocolIdx = GetPortProtocolIdx((char*)"SCADAPROTECT"); + for(i=0; iPortIdx = i; + //PutBaohuDataToPort(rtumsg); + PutBaohuDataToPortEx(i, rtumsg); + } + } +} + +int GetBaohuDB(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB) +{ + int iGrpNum, iProtocolIdx; + + if((commid < 0) || (commid > MaxPortNum)) + { + return 0; + } + + if(SioParam[commid].ProtocolIdx < 1) + { + return 0; + } + + iProtocolIdx = SioParam[commid].ProtocolIdx; + if(FunCallPtr[iProtocolIdx].GetBaohuDataBase) + { + iGrpNum = FunCallPtr[iProtocolIdx].GetBaohuDataBase(commid, iProvAddr, ppBaoHuDB); + } + else + { + iGrpNum = 0; + } + + if(iGrpNum == 0) + { + *ppBaoHuDB = NULL; + } + + return iGrpNum; +} + +int GetSioParam(SIO_PARAM_DEF **ppParam) +{ + *ppParam = SioParam; + + return GetMaxPort(); +} + +int GetDevParam(DEV_DEF **ppParam) +{ + *ppParam = &DevParam[iCurDevIdx]; + return GetMaxPort(); +} + +int SetCurPort(int PortNo) +{ + CurPort = PortNo; + + if(CurPort < 0) + { + RealDataDispFlag = 0; + } + else + { + RealDataDispFlag = 1; + } + + return CurPort; +} + +int GetCurPortEx() +{ + return CurPort; +} + +int SetDispFlag(int iFlag) +{ + RealDataDispFlag = iFlag; + + return RealDataDispFlag; +} + +// 获取全局变量 +SIO_PARAM_DEF *GetSioParamPtr() +{ + return SioParam; +} diff --git a/commport.h b/commport.h new file mode 100644 index 0000000..dc1a614 --- /dev/null +++ b/commport.h @@ -0,0 +1,134 @@ + +#ifndef __COMM_PORT_H_ICL__ +#define __COMM_PORT_H_ICL__ + +#include "common.h" + +#define MSGTYPE_BAOHU_BASE 200 +#define MSGTYPE_BAOHU_103CMD MSGTYPE_BAOHU_BASE+0 +#define MSGTYPE_BAOHU_103DATA MSGTYPE_BAOHU_BASE+1 +#define MSGTYPE_BAOHU_SCADACMD MSGTYPE_BAOHU_BASE+2 +#define MSGTYPE_BAOHU_SCADADATA MSGTYPE_BAOHU_BASE+3 + +// 从 config.ini 或 portconfig.ini 读信息 +u_long GetPrivateProString(const char *section, const char *entry, const char *defaultstr, char *result, int len, char *inifile); +int GetPrivateProInt(const char *section, const char *entry, int idefault, char *inifile); +u_long GetPrivateProString2(const char *section, const char *entry, const char *defaultstr, char *result, int len, HDSFILE hFile); +int GetPrivateProInt2(const char *section, const char *entry, int idefault, HDSFILE hFile); + +int PutDataToBuf( DATA_BUF *buf, u_char *msg, int len ); +int GetDataFormBuf( DATA_BUF *databuf, u_char *buf, int len, int clrflag ); + +// 读设备信息,检查芯片状态和读芯片类型和频率 +void ReadPortConfigInfo( u_short ); +void ReadPortConfigInfoEx(u_short); + +void OpenAllPort( void ); +void CloseOnePort( int commid ); +void CloseAllPort( void ); +void PollAllSerialPort( void ); +void PollAllNetPort( void ); + +int SetPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int GetPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int SetPorvPntMsg( int port, int point, void *pntmsg, BYTE type, BYTE attr ); +int GetPorvPntMsg( int port, int point, void *pntmsg, BYTE type ); + +int CheckPollCmdBufEmpty( int port ); +int PutPollCmdToBuf( int port, int type, WORD wait, char *buf, int len ); +void SendCmdFormPollCmdBuf( int port ); + +// wen 2005.09.08 清空指令缓冲区中的所有指令 +void ClearAllCmdFromPollCmdBuf(int port); +// wen 2004.10.25 公布函数接口 +void ClearCmdFormPollCmdBuf( int port ); +void ClearCmdFormPollCmdBufEx( int port, char *file, int line ); +void ClearCmdAllFlag( int port ); +int GetCmdFormPollCmdBuf( int port, u_char *buf, int len ); +int ReGetCmdFormPollCmdBuf( int port, u_char *buf, int len ); + +int GetMaxPort(); +int GetPortProtocolIdx(char *name); +char *GetPortProtocolName(int Idx); + +// wen 2004.11.16 增加转发soe数据的处理 +// 返回缓冲区中的soe数据数量 +int ProvWriteSoeData( int provport, SOE_DEF *ptrSoe ); +int ProvAndDelGetSoeData( int provport, SOE_DEF *ptrSoe ); +int ProvHaveSoeData( int provport ); + +// wen 2005.02.23 +void SendDataToPort(int commid, char *buf, int len); + +// wen 2005.02.28 +void SendYkYtCommand(int commid, char *buf, int len); +BOOL SendYkYtCommand2(int commid, YKYT_PARAM *pParam); +int FindProvPntFromYkYtPnt(int commid, int ykytpnt, SIO_PARAM_BAOHU_DEF *pBaohuParam); +BOOL ProvPortYkYtIsTimeOut( int commid, PROV_YKYT_DEF *pProvYkYt ); +BOOL IsProvYkYtAck(int commid, PROV_YKYT_DEF *pProvYkYt); +BOOL ShmGetDispYkYtFlag(); +BOOL ShmGetDispHostLinkFlag(); + +// wen 2005.04.18 内存的分配与释放 +void PortMemoryMalloc( int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam ); +void PortMemoryMallocEx( int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam ); +BOOL PortDataPntInit(int commid, int type, SIO_PARAM_BAOHU_DEF *pBaohuParam); +void PortMemoryFree( int commid, SIO_PARAM_DEF *pGenParam ); +void PortWriteDataFree( int commid ); + +BOOL IsBaoHuPtr( int commid ); +BOOL IsExtInfoPtr( int commid ); +BOOL IsSerialPtr( int commid ); + +/*! + \brief 获取端口打开标识 + \param commid -- 端口号 + \param rwflag -- 读标识还是写标识 + \返回值 retval-- 返回端口读或者写状态 + */ +int ShmGetPortFlag(int commid, int rwflag); + +// 保护数据处理 +/*! + \brief 发送保护数据到实际的装置 + \param commid -- 端口号 + \param rtumsg -- 转发的保护指令 + \note + 指令格式暂时用部颁103规约格式 + */ +void SendProtectCmdToDev(int commid, RTUMSG *rtumsg); + +/*! + \brief 将实际装置数据保存到指令下发端口 + \param rtumsg -- 转发的保护指令 + \note + 指令格式暂时用部颁103规约格式 + */ +void PutBaohuDataToPort(RTUMSG *rtumsg); +void PutBaohuDataToPortEx(int commid, RTUMSG *rtumsg); + +/*! + \brief 将数据发送到所有的scadaprotect规约端口 + \param rtumsg -- 转发的保护指令 + */ +void SendDataToAllScadaProtectPort(RTUMSG *rtumsg); + +/*! + \brief 获取指定装置的保护数据库 + \param commid -- 端口号 + \param iProvAddr -- 保护装置转发地址,端口统一编排的地址 + \param ppBaoHuDB -- 存储保护装置保护数据的指针(PAI,PDI,PFIX...) + \retval 返回该装置保护数据组数 + */ +int GetBaohuDB(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB); + +int GetSioParam(SIO_PARAM_DEF **ppParam); +int GetDevParam(DEV_DEF **ppParam); +int SetCurPort(int PortNo); +int GetCurPortEx(); +int SetDispFlag(int iFlag); + +// 获取全局变量 +SIO_PARAM_DEF *GetSioParamPtr(); +#endif + diff --git a/conf_close.cpp b/conf_close.cpp new file mode 100644 index 0000000..dfd9c5e --- /dev/null +++ b/conf_close.cpp @@ -0,0 +1,42 @@ + + + +//#include +#include +#include + +#include "confrw_errno.h" +//#include "confrw.h" + +#include "_confrw.h" +#include "Profile_Hash.h" + +/* + * 关闭配置文件句柄 + * + * 参数 + * handle -- 配置文件句柄 + * + * 返回值 + * SUCCESS -- 成功的关闭了指定的配置文件句柄(包括资源释放等工作) + * 其它 -- 失败代码 + * + * 备注 + * 如果输入的参数非配置文件(上下文)句柄, 则不作任何事. + * + */ +int conf_close ( void * handle ) +{ + int ret = SUCCESS; + + if ( NULL == handle ) + return NULL; + + ret = close_profile_handle ( (HPROFILE )*(int *)handle ); + if ( SUCCESS != ret ) + return ret; + + free ( handle ); + + return SUCCESS; +} diff --git a/conf_open.cpp b/conf_open.cpp new file mode 100644 index 0000000..b509f4e --- /dev/null +++ b/conf_open.cpp @@ -0,0 +1,47 @@ + +//#include +#include +#include + +#include "confrw_errno.h" +#include "confrw.h" + +#include "_confrw.h" +#include "Profile_Hash.h" + + +/* + * 打开配置文件, 返回表示配置文件的句柄 + * + * 参数 + * pszfname -- 配置文件的全路径名(默认为 char [MAX_PATH]类型) + * ppvhandle -- 在函数执行成功的情况下, 返回配置文件(的上下文环境)句柄 + * + * 返回值 + * SUCCESS -- 成功的执行了该函数, 并打开了给定的配置文件 + * 其它 -- 失败代码 + * + */ +int conf_open ( const char * pszfname, void ** ppvhandle ) +{ + int ret = SUCCESS; + + if ( NULL == pszfname || NULL == ppvhandle ) + return ERROR_POINTER; + + int handle = -1; + + ret = create_profile_cache ( (char *)pszfname, &handle ); + if ( SUCCESS != ret ) + { + *ppvhandle = NULL; + return ret; + } + else + { + *ppvhandle = calloc ( 1, sizeof(long) ); + *((int *)*ppvhandle) = handle; + return SUCCESS; + } +} + diff --git a/conf_read_key.cpp b/conf_read_key.cpp new file mode 100644 index 0000000..b71683a --- /dev/null +++ b/conf_read_key.cpp @@ -0,0 +1,111 @@ +/******************************************************************************** + * + * Copyright (C) 1999-2000 SCADA Technology Control Co., Ltd. All rights reserved. + * + * 读配置文件的调用接口函数 之 + * 根据指定的 [段]及键的名称, 获取配置文件中的配置项 + * + * 创建日期: 2002/01/21 + * + * + * + * $Name: $ + * + * $Revision: 1.2 $ + * + * $Date: 2006/08/04 03:37:33 $ + * + * $State: Exp $ + * + * $Log: conf_read_key.cpp,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.1.2.1 2006/07/28 07:54:02 zhuzhenhua + * no message + * + * Revision 1.2 2003/01/02 03:14:51 scada + * trim substitution line + * + * Revision 1.1.1.1 2002/08/21 07:16:39 harold + * temporarily import + * + * Revision 1.8 2002/03/20 03:40:22 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 13:43:21 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 08:17:11 harold + * no message + * + * Revision 1.7 2002/01/23 06:07:22 harold + * no message + * + * Revision 1.6 2002/01/23 05:43:55 harold + * no message + * + * Revision 1.5 2002/01/23 05:41:06 harold + * no message + * + * Revision 1.4 2002/01/23 03:35:41 harold + * no message + * + * Revision 1.3 2002/01/23 03:34:24 harold + * no message + * + * Revision 1.2 2002/01/23 03:26:24 harold + * no message + * + * Revision 1.1 2002/01/21 02:46:53 harold + * no message + * + * + * + ********************************************************************************/ + + + +//#include +#include "confrw_errno.h" +#include "confrw.h" + +#include "_confrw.h" +#include "Profile_Hash.h" + + +/* + * 根据指定的 [段]及键的名称, 获取配置文件中的配置项 + * + * 参数 + * handle -- 配置文件句柄 + * pszsec_name -- 段名 + * pszkey_name -- 键名称 + * pszdefault -- 键的默认值, 以null字符结尾的字符串, + * 如果配置文件中没有该键的配置, 同时, 该参数不为空, 则返回该值 + * pbuf -- 返回值的缓冲区 + * buffer_length -- 缓冲区长度 + * + * 返回值 + * SUCCESS -- 成功的执行了本函数 + * 其它 -- 失败代码 + * + */ +int conf_read_key ( void * handle, + const char * pszsec_name, + const char * pszkey_name, + const char * pszdefault, + char * pbuf, + int buffer_length ) +{ + int len = buffer_length; + + return get_pgcprofile_string ( (char *)pszsec_name, + (char *)pszkey_name, + (char *)pszdefault, + pbuf, + (pgcu32 *)&len, + (HPROFILE)*(int *)handle ); + +} + diff --git a/conf_write_key.cpp b/conf_write_key.cpp new file mode 100644 index 0000000..9ef2ae3 --- /dev/null +++ b/conf_write_key.cpp @@ -0,0 +1,96 @@ +/******************************************************************************** + * + * Copyright (C) 1999-2000 SCADA Technology Control Co., Ltd. All rights reserved. + * + * 读配置文件的调用接口函数 之 + * 修改/添加一个新的配置项 + * + * 创建日期: 2002/01/21 + * + * + * + * $Name: $ + * + * $Revision: 1.2 $ + * + * $Date: 2006/08/04 03:37:33 $ + * + * $State: Exp $ + * + * $Log: conf_write_key.cpp,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.1.2.1 2006/07/28 07:54:02 zhuzhenhua + * no message + * + * Revision 1.2 2003/01/02 03:14:51 scada + * trim substitution line + * + * Revision 1.1.1.1 2002/08/21 07:16:39 harold + * temporarily import + * + * Revision 1.5 2002/03/20 03:40:22 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 13:43:21 harold + * no message + * + * Revision 1.1.1.1 2002/03/15 08:17:11 harold + * no message + * + * Revision 1.4 2002/01/23 05:41:06 harold + * no message + * + * Revision 1.3 2002/01/23 03:35:41 harold + * no message + * + * Revision 1.2 2002/01/23 03:26:24 harold + * no message + * + * Revision 1.1 2002/01/21 02:46:53 harold + * no message + * + * + * + ********************************************************************************/ + + + +//#include +#include "confrw_errno.h" +#include "confrw.h" + +#include "_confrw.h" +#include "typedef.h" +#include "Profile_Hash.h" + + +/* + * 修改/添加一个新的配置项 + * + * 参数 + * handle -- 配置文件句柄 + * pszsec_name -- 段名 + * pszkey_name -- 键名 + * pszkey_value -- 键的值 + * force_insert -- 如果(段, 键)不存在, 是否需要插入该(段, 键)的配置值, + * 如果该参数等于0, 则不插入该配置项, 否则, 插入该配置项. + * + * 返回值 + * SUCCESS -- 成功 + * 其它 -- 失败代码 + * + */ +int conf_write_key ( void * handle, + const char * pszsec_name, + const char * pszkey_name, + const char * pszkey_value, + int force_insert ) +{ + return write_pgcprofile_string ( pszsec_name, + pszkey_name, + pszkey_value, + force_insert ? PGCTRUE : PGCFALSE, + (HPROFILE)*(int *)handle ); +} diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..a080125 --- /dev/null +++ b/config.ini @@ -0,0 +1,44 @@ +[网络设置] +主机网络端口=7119 +PING接收端口=13124 +PING发送端口=13123 +[主机地址] +主机A地址1=192.168.1.199 +停止向主机发送端口全数据=0 +[前置机] +前置机A地址1=192.168.1.143 +前置机A地址2=192.168.2.143 +前置机B地址1=192.168.1.113 +前置机B地址2=192.168.2.113 +前置机A地址1掩码=255.255.255.0 +前置机A地址2掩码=255.255.255.0 +前置机B地址1掩码=255.255.255.0 +前置机B地址2掩码=255.255.255.0 +允许前置机连接=1 +前置机连接=2 +起始厂站号=0 +运行方式=0 +主备切换端口屏蔽字=0x00000000 +[对时] +对时方式=1 +[NetCommPort] +UdpCommPort=0xfe00 +TcpCommPort=0xff01 +WatchCommPort=0xff02 +[PortConfig] +Port1=1 +Port2=1 +Port3=1 +Port4=1 +Port5=1 +Port6=1 +Port7=1 +Port8=1 +Port9=1 +Port10=1 +Port11=1 +Port12=1 +Port13=1 +Port14=1 +Port15=1 +Port16=1 diff --git a/confrw.h b/confrw.h new file mode 100644 index 0000000..24d4e00 --- /dev/null +++ b/confrw.h @@ -0,0 +1,177 @@ + + + + +#if !defined(__CONFRW_H__QWERUOIPUADFJHAFKLHADSFHADSFVCMBVZXCVQOEWIRADSHJKXZJVBLWQERYO) +#define __CONFRW_H__QWERUOIPUADFJHAFKLHADSFHADSFVCMBVZXCVQOEWIRADSHJKXZJVBLWQERYO + +/*! + * \if developer_doc + * \file + * + * \brief 读配置文件的调用接口头文件,包括:系统限值常量, 外部接口函数声明头文件。 + * + * id: $Id: confrw.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif +*/ + + +//#include +#include "confrw_errno.h" + +#ifdef OS_LINUX +#define DSLIB_API +#else +#ifdef CONFRWLIB_EXPORTS + #define CONFRWLIB_API __declspec(dllexport) +#else + #define CONFRWLIB_API __declspec(dllimport) +#endif// CONFRWLIB_EXPORTS +#endif//OS_LINUX + +/*! +* \if by_group +* \addtogroup grp_config_rw +* @{ +* \endif +*/ + +/*! + * \brief 打开配置文件, 返回表示配置文件的句柄 + * + * \param pszfname --[in] 配置文件的全路径名(默认为 char [MAX_PATH]类型) + * \param ppvhandle --[in] 在函数执行成功的情况下, 返回配置文件(的上下文环境)句柄 + * + * \retval 返回值 + * \retval SUCCESS -- 成功的执行了该函数, 并打开了给定的配置文件 + * \retval 其它 -- 失败代码 + * + */ +CONFRWLIB_API int conf_open ( const char * pszfname, void ** ppvhandle ); + + + + + + +/*! + * \brief 关闭配置文件句柄 + * + * \param handle --[in] 配置文件句柄 + * + * \retval SUCCESS -- 成功的关闭了指定的配置文件句柄(包括资源释放等工作) + * \retval ERROR_CONF_HANLDE -- 错误的配置文件读写句柄 + * \retval 其它 -- 失败代码 + * + * \note + * 如果输入的参数非配置文件(上下文)句柄, 则不作任何事. + * + */ +CONFRWLIB_API int conf_close ( void * handle ); + + + + + +/*! + * \brief 根据指定的 [段]及键的名称, 获取配置文件中的配置项 + * + * \param handle --[in] 配置文件句柄 + * \param pszsec_name --[in] 段名, 以null字符结尾的字符串 + * \param pszkey_name --[in] 键名称, 以null字符结尾的字符串 + * \param pszdefault --[in] 键的默认值, 以null字符结尾的字符串,如果配置文件中没有该键的配置, 同时, 该参数不为空, 则返回该值 + * \param pbuf --[out] 返回值的缓冲区 + * \param buffer_length --[in] 缓冲区长度 + * + * \retval SUCCESS -- 配置的键值存在, 且成功地读出 + * \retval 如果给出默认值, 则在欲读取的键值/键不存在地情况下, 同样返回SUCCESS + * \retval ERROR_CONF_SECTION -- 欲读取的键所在的段不存在 + * \retval ERROR_CONF_KEY -- 欲读取的键不存在 + * \retval 其它 -- 失败代码 + */ +CONFRWLIB_API int conf_read_key ( void * handle, + const char * pszsec_name, + const char * pszkey_name, + const char * pszdefault, + char * pbuf, + int buffer_length ); + + + + + + +/*! + * \brief 修改/添加一个新的配置项 + * + * \param handle --[in] 配置文件句柄 + * \param pszsec_name --[in] 段名 + * \param pszkey_name --[in] 键名 + * \param pszkey_value --[in] 键的值 + * \param force_insert --[in] 如果(段, 键)不存在, 是否需要插入该(段, 键)的配置值, + * 如果该参数等于0, 则不插入该配置项, 否则, 插入该配置项. + * + * \retval SUCCESS -- 成功 + * \retval 其它 -- 失败代码 + * + * \note + * 如果 force_insert 为0, 则当配置文件中不存在指定段时, 返回 ERROR_CONF_SECTION; + * 如果不存在指定(段/键)组合时, 返回 ERROR_CONF_KEY. + */ +CONFRWLIB_API int conf_write_key ( void * handle, + const char * pszsec_name, + const char * pszkey_name, + const char * pszkey_value, + int force_insert ); + + + + + +/*! + * \brief 从配置文件中删除一个指定的配置项(段, 键) + * + * \param handle --[in] 配置文件句柄 + * \param pszsec_name --[in] 段名 + * \param pszkey_name --[in] 键名 + * + * \retval SUCCESS -- 成功的删除了指定的配置项 + * \retval 其它 -- 失败代码 + * + * \note + * 如果指定的段不存在, 则返回 ERROR_CONF_SECTION + * 如果指定(段, 键名称)组合不存在, 则返回 ERROR_CONF_KEY + */ +CONFRWLIB_API int conf_delete_key ( void * handle, + const char * pszsec_name, + const char * pszkey_name ); + + + + + +/*! + * \brief 删除配置文件中一个整段的配置 + * + * \param handle --[in] 配置文件句柄 + * \param pszsec_name --[in] 希望删除的段的名称, 以null字符结尾的字符串 + * + * \retval SUCCESS -- 成功的删除了配置文件中的指定的段 + * \retval 其它 -- 失败代码 + * + * \note + * 如果指定的段不存在, 则返回 ERROR_CONF_SECTION + */ +CONFRWLIB_API int conf_delete_section ( void * handle, + const char * pszsec_name ); + +/*! +* \if by_group +* @} +* \endif +*/ + + +#endif //!defined(__CONFRW_H__QWERUOIPUADFJHAFKLHADSFHADSFVCMBVZXCVQOEWIRADSHJKXZJVBLWQERYO) diff --git a/confrw_errno.h b/confrw_errno.h new file mode 100644 index 0000000..25915a9 --- /dev/null +++ b/confrw_errno.h @@ -0,0 +1,69 @@ + +#if !defined(__CONFRW_ERRNO_H__OPQEWUIPADSJKHZXCXZVNZCADLHJFOQEWPOQYUEHJASDFHPWQEUQ) +#define __CONFRW_ERRNO_H__OPQEWUIPADSJKHZXCXZVNZCADLHJFOQEWPOQYUEHJASDFHPWQEUQ +/*! + * \if developer_doc + * \file + * + * \brief 读配置文件的调用接口函数库的错误代码定义头文件。 + * + * id: $Id: confrw_errno.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif +*/ + +#include "global_errno.h" + +/*! +* \if by_group +* \addtogroup grp_config_rw +* @{ +* \endif +*/ + +//!< 不能为当前打开的配置文件缓冲分配一个句柄,原因是句柄已经全被占用 +#define ERROR_CONF_NOHANDLE (ERROR_CONF_BASE + 1) + +//!< 创建哈希表失败 +#define ERROR_CONF_CREATEHASH (ERROR_CONF_BASE + 2) + +//!< 输入了非法的配置文件缓冲句柄 +#define ERROR_CONF_INVALIDHANDLE (ERROR_CONF_BASE + 3) + +//!< 在读配置文件时,用户开辟的接收缓冲区不够大 +#define ERROR_CONF_REVBUFFER (ERROR_CONF_BASE + 4) + +//!< 在读配置文件时,因指定的段的项目名不存在,函数执行缺省拷贝,并返回此结果 +#define SUCCESS_CONF_DEFCOPY (ERROR_CONF_BASE + 5) + +//!< 不能输入一个空的句柄指针作参数 +#define ERROR_CONF_NULL_HANDEPTR (ERROR_CONF_BASE + 6) + +//!< 输入的段名,项目名,项目值的字符串长度超长 +#define ERROR_CONF_INPUTSTRING_TOOLARGE (ERROR_CONF_BASE + 7) + +//!< 指定的段或项目并不存在 +#define ERROR_CONF_NOTEXIST (ERROR_CONF_BASE + 8) + + +/*! +*\verbatim + 以下为confrw_ex中定义的错误代码 +*\endvervatim +*/ +//!< 无效的配置文件句柄 +#define ERROR_CONF_HANDLE (ERROR_CONF_BASE + 9) + +//!< 指定的段不存在 +#define ERROR_CONF_SECTION (ERROR_CONF_BASE + 10) + +//!< 指定的键值不存在 +#define ERROR_CONF_KEY (ERROR_CONF_BASE + 11) + +/*! +* \if by_group +* @} +* \endif +*/ +#endif //!defined(__CONFRW_ERRNO_H__OPQEWUIPADSJKHZXCXZVNZCADLHJFOQEWPOQYUEHJASDFHPWQEUQ) diff --git a/display.cpp b/display.cpp new file mode 100644 index 0000000..86fe9c9 --- /dev/null +++ b/display.cpp @@ -0,0 +1,625 @@ + + +//#include "stdafx.h" +#include "display.h" +#include "commport.h" + +extern SIO_PARAM_DEF SioParam[]; + +extern int iCurDevIdx; +extern DEV_DEF DevParam[]; + +HWND hMainWnd; + +int RealDataDispFlag; + +int CurPort; +int DispType = 0; + +int ListIndex = 0; // 显示序号索引起始 +int ItemNumOfPage; // 页显示项目数 + + +COLORREF dwColorVal[16] = // 显示颜色定义 +{ + RGB(255,255,255), RGB(128,128,128), + RGB(255, 0, 0), RGB(255,255, 0), + RGB( 0,255, 0), RGB( 0,255,255), + RGB( 0, 0,255), RGB(255, 0,255), + RGB(192,192,192), RGB( 0, 0, 0), + RGB(128, 0, 0), RGB(128,128, 0), + RGB( 0,128, 0), RGB( 0,128,128), + RGB( 0, 0,128), RGB(128, 0,128) +}; + +void RealAiDataDisp( HDC hdc ) +{ + UINT xWd, yHg, lineh, tmp; + int i, j, total, idx, itemofline; + char szbuf[256]; + RECT rc; + AI_DEF *aiptr; + + float sp; + int pos[6]; + + GetClientRect( hMainWnd, &rc ); + + itemofline = 2; + + CaculateWH( hdc, &xWd, &yHg, (char*)"行距" ); + lineh = yHg + 5; + + rc.top = 10; + + SetTextColor( hdc, dwColorVal[BLUE] ); + + // 显示标题 + sprintf( szbuf,"端口%02d 实时遥测数据信息", CurPort + 1 ); + DrawText(hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + rc.top += (lineh + 5); + + SetTextColor( hdc, dwColorVal[BLACK] ); + + // 计算显示位置 + pos[0] = 0; + pos[3] = rc.right / 2; + + tmp = 0; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + tmp += xWd; + + pos[1] = pos[0] + xWd; + pos[4] = pos[3] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + tmp += xWd; + + pos[2] = pos[1] + xWd; + pos[5] = pos[4] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"测点原值" ); + tmp += xWd; + sp = ((float)rc.right - (float)tmp*itemofline) / (itemofline*4); + pos[0] += (int)sp; + pos[1] += (int)(sp*2); + pos[2] += (int)(sp*3); + pos[3] += (int)(sp); + pos[4] += (int)(sp*2); + pos[5] += (int)(sp*3); + + // 显示项目名称 + for ( i = 0; i < itemofline; i++ ) + { + sprintf( szbuf, (char*)"序号" ); + rc.left = pos[i*3]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + sprintf( szbuf, (char*)"测点名称" ); + rc.left = pos[i*3+1]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + sprintf( szbuf, (char*)"测点原值" ); + rc.left = pos[i*3+2]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + } + rc.top += lineh; + + ItemNumOfPage = (rc.bottom - rc.top) / lineh; + + if( !IsBaoHuPtr(CurPort) ) + return; + + // 计算总行数 + total = (SioParam[CurPort].m_psBaoHu->AiNum + itemofline - 1) / itemofline; + + // 调整显示的起始位置 + if ( total < ItemNumOfPage ) + ListIndex = 0; + if ( (ListIndex + ItemNumOfPage) > total ) + ListIndex = total - ItemNumOfPage; + if ( ListIndex < 0 ) + ListIndex = 0; + + // 显示输出 + idx = ListIndex * itemofline; + aiptr = (AI_DEF*)SioParam[CurPort].m_psBaoHu->AiPtr; + if( !aiptr ) + return; + + for ( i = 0; (i < ItemNumOfPage) && (idx < SioParam[CurPort].m_psBaoHu->AiNum); i++ ) + { + for ( j = 0; j < itemofline; j++ ) + { + if((idx + j) >= SioParam[CurPort].m_psBaoHu->AiNum) + break; + + sprintf( szbuf, "%03d", idx + j + 1 ); + rc.left = pos[j*3+0]; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "遥测%03d", idx + j + 1 ); + rc.left = pos[j*3+1]; + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "0x%04x", aiptr[idx+j].RawValue & 0xffff ); + rc.left = pos[j*3+2]; + CaculateWH( hdc, &xWd, &yHg, (char*)"测点原值" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + } + + idx += itemofline; + rc.top += lineh; + } +} + +void RealDiDataDisp( HDC hdc ) +{ + UINT xWd, yHg, lineh, tmp; + int i, j, total, idx, itemofline; + char szbuf[256], stchar = 1; + RECT rc; + DI_DEF *diptr; + + float sp; + int pos[6]; + + GetClientRect( hMainWnd, &rc ); + + CaculateWH( hdc, &xWd, &yHg, (char*)"行距" ); + lineh = yHg + 5; + + itemofline = 2; + + rc.top = 10; + + SetTextColor( hdc, dwColorVal[BLUE] ); + + // 显示标题 + sprintf( szbuf,"端口%02d 实时遥信数据信息", CurPort + 1 ); + DrawText(hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + rc.top += (lineh + 5); + + SetTextColor( hdc, dwColorVal[BLACK] ); + + // 计算显示位置 + pos[0] = 0; + pos[3] = rc.right / 2; + + tmp = 0; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + tmp += xWd; + + pos[1] = pos[0] + xWd; + pos[4] = pos[3] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + tmp += xWd; + + pos[2] = pos[1] + xWd; + pos[5] = pos[4] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"状态" ); + tmp += xWd; + sp = ((float)rc.right - (float)tmp*itemofline) / (itemofline*4); + pos[0] += (int)sp; + pos[1] += (int)(sp*2); + pos[2] += (int)(sp*3); + pos[3] += (int)(sp); + pos[4] += (int)(sp*2); + pos[5] += (int)(sp*3); + + // 显示项目名称 + for ( i = 0; i < itemofline; i++ ) + { + sprintf( szbuf, (char*)"序号" ); + rc.left = pos[i*3+0]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + + sprintf( szbuf, (char*)"测点名称" ); + rc.left = pos[i*3+1]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + + sprintf( szbuf, (char*)"状态" ); + rc.left = pos[i*3+2]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + } + rc.top += lineh; + + ItemNumOfPage = (rc.bottom - rc.top) / lineh; + + if( !IsBaoHuPtr(CurPort) ) + return; + + // 计算总行数 + total = (SioParam[CurPort].m_psBaoHu->DiNum + itemofline - 1) / itemofline; + + // 调整显示的起始位置 + if ( total < ItemNumOfPage ) + ListIndex = 0; + if ( (ListIndex + ItemNumOfPage) > total ) + ListIndex = total - ItemNumOfPage; + if ( ListIndex < 0 ) + ListIndex = 0; + + // 显示输出 + idx = ListIndex * itemofline; + diptr = (DI_DEF*)SioParam[CurPort].m_psBaoHu->DiPtr; + if( !diptr ) + return; + + for ( i = 0; (i < ItemNumOfPage) && (idx < SioParam[CurPort].m_psBaoHu->DiNum); i++ ) + { + for ( j = 0; j < itemofline; j++ ) + { + if((idx + j) >= SioParam[CurPort].m_psBaoHu->DiNum) + break; + + sprintf( szbuf, "%03d", idx + j + 1 ); + rc.left = pos[j*3+0]; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "遥信%03d", idx + j + 1 ); + rc.left = pos[j*3+1]; + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "%s", diptr[idx+j].Status ? (char*)"合" : (char*)"分" ); + rc.left = pos[j*3+2]; + CaculateWH( hdc, &xWd, &yHg, (char*)"状态" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + } + + idx += itemofline; + rc.top += lineh; + } +} + +void RealPiDataDisp( HDC hdc ) +{ + UINT xWd, yHg, lineh, tmp; + int i, j, total, idx, itemofline; + char szbuf[256]; + RECT rc; + PI_DEF *piptr; + + float sp; + int pos[6]; + + GetClientRect( hMainWnd, &rc ); + itemofline = 2; + + CaculateWH( hdc, &xWd, &yHg, (char*)"行距" ); + lineh = yHg + 5; + + rc.top = 10; + + SetTextColor( hdc, dwColorVal[BLUE] ); + + // 显示标题 + sprintf( szbuf,"端口%02d 实时电度数据信息", CurPort + 1 ); + DrawText(hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + rc.top += (lineh + 5); + + SetTextColor( hdc, dwColorVal[BLACK] ); + + // 计算显示位置 + pos[0] = 0; + pos[3] = rc.right / 2; + + tmp = 0; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + tmp += xWd; + + pos[1] = pos[0] + xWd; + pos[4] = pos[3] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + tmp += xWd; + + pos[2] = pos[1] + xWd; + pos[5] = pos[4] + xWd; + + CaculateWH( hdc, &xWd, &yHg, (char*)"测点原值" ); + tmp += xWd; + sp = ((float)rc.right - (float)tmp*itemofline) / (itemofline*4); + pos[0] += (int)sp; + pos[1] += (int)(sp*2); + pos[2] += (int)(sp*3); + pos[3] += (int)(sp); + pos[4] += (int)(sp*2); + pos[5] += (int)(sp*3); + + // 显示项目名称 + for ( i = 0; i < itemofline; i++ ) + { + sprintf( szbuf, (char*)"序号" ); + rc.left = pos[i*3+0]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + + sprintf( szbuf, (char*)"测点名称" ); + rc.left = pos[i*3+1]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + + sprintf( szbuf, (char*)"测点原值" ); + rc.left = pos[i*3+2]; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + } + rc.top += lineh; + + ItemNumOfPage = (rc.bottom - rc.top) / lineh; + + if( !IsBaoHuPtr(CurPort) ) + return; + + // 计算总行数 + total = (SioParam[CurPort].m_psBaoHu->PiNum + itemofline - 1) / itemofline; + + // 调整显示的起始位置 + if ( total < ItemNumOfPage ) + ListIndex = 0; + if ( (ListIndex + ItemNumOfPage) > total ) + ListIndex = total - ItemNumOfPage; + if ( ListIndex < 0 ) + ListIndex = 0; + + // 显示输出 + idx = ListIndex * itemofline; + piptr = (PI_DEF*)SioParam[CurPort].m_psBaoHu->PiPtr; + if( !piptr ) + return; + + for ( i = 0; (i < ItemNumOfPage) && (idx < SioParam[CurPort].m_psBaoHu->PiNum); i++ ) + { + for ( j = 0; j < itemofline; j++ ) + { + if((idx + j) >= SioParam[CurPort].m_psBaoHu->PiNum) + break; + + sprintf( szbuf, "%03d", idx + j + 1 ); + rc.left = pos[j*3+0]; + CaculateWH( hdc, &xWd, &yHg, (char*)"序号" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "电度%03d", idx + j + 1); + rc.left = pos[j*3+1]; + CaculateWH( hdc, &xWd, &yHg, (char*)"测点名称" ); + rc.right = rc.left + xWd; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_CENTER ); + + sprintf( szbuf, "0x%08x", piptr[idx+j].RawValue ); + rc.left = pos[j*3+2]; + CaculateWH( hdc, &xWd, &yHg, (char*)"测点原值" ); + // wen 2004.11.19 显示的长度是名称的1.5倍 + //rc.right = rc.left + xWd; + //DrawText( hdc, szbuf, strlen(szbuf), &rc, DT_CENTER ); + rc.right = rc.left + xWd/4*6; + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + } + + idx += itemofline; + rc.top += lineh; + } +} + +void WatchDataDisp( HDC hdc ) +{ + UINT xWd, yHg, lineh; + int i, j, total, idx, type; + char szbuf[256]; + RECT rc; + + GetClientRect( hMainWnd, &rc ); + + CaculateWH( hdc, &xWd, &yHg, (char*)"行距" ); + lineh = yHg + 5; + + rc.top = 10; + + if ( DevParam[iCurDevIdx].WatchDispLine.LineCnt == 0 ) + { + sprintf( szbuf, "当前没有数据....." ); + DrawText(hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + return; + } + + ItemNumOfPage = (rc.bottom - rc.top) / lineh; + + total = DevParam[iCurDevIdx].WatchDispLine.LineCnt; + if ( RealDataDispFlag ) + ListIndex = 100000; + + // 调整显示的起始位置 + if ( total < ItemNumOfPage ) + ListIndex = 0; + if ( (ListIndex + ItemNumOfPage) > total ) + ListIndex = total - ItemNumOfPage; + if ( ListIndex < 0 ) + ListIndex = 0; + + // 寻找数据起始位置 + idx = DevParam[iCurDevIdx].WatchDispLine.Rear - total; + if ( idx < 0 ) + idx += MAX_DISP_LINE; + + // 显示起始位置 + idx += ListIndex; + + for ( i = 0; i < min(ItemNumOfPage, total); i++ ) + { + j = (idx + i) % MAX_DISP_LINE; + + type = DevParam[iCurDevIdx].WatchDispLine.Line[j][0]; + if ( type == 'R' ) // 接收数据 + SetTextColor( hdc, dwColorVal[BLUE] ); + else + SetTextColor( hdc, dwColorVal[MAGENTA] ); + + strcpy( szbuf, (char*)&DevParam[iCurDevIdx].WatchDispLine.Line[j][1] ); + + DrawText( hdc, (CONST WCHAR*)szbuf, strlen(szbuf), &rc, DT_LEFT ); + + rc.top += lineh; + } +} + +//*************************************************************** +//* 新字体函数? * +//*************************************************************** +HFONT NewFont( int nFSize ) +{ + /* + WCHAR typeface[32] = (WCHAR *)"宋体"; + + LOGFONT LogFont = { 0, 0, 0, 0, + 400, + 0, + 0, + 0, + DEFAULT_CHARSET, + //OUT_STROKE_PRECIS, + OUT_STRING_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + DEFAULT_PITCH, + typeface + //"新宋体" + //"黑体" + //"隶书" + //"幼圆" + //"仿宋_GB2312" + }; + + LogFont.lfWidth = (LONG)((float)nFSize*.618); + + LogFont.lfHeight = (LONG)nFSize; + + strcpy( LogFont.lfFaceName, "Lee宋体" ); + return( CreateFontIndirect( &LogFont ));*/ + return NULL; +} + +void DataDisp( HWND hWnd ) +{ + HDC hdc; + HFONT hFont; + int nFSize; + + hdc = GetDC( hWnd ); + + if( WATCH_DATA_DISP != DispType) + nFSize = 16; + else + nFSize = 12; + + hFont = (HFONT)SelectObject( hdc, NewFont( nFSize ) ); + + if( !IsBaoHuPtr(CurPort) ) + return; + + switch( DispType ) + { + case AI_DATA_DISP: + if(PROV_PROTOCOL != SioParam[CurPort].m_psBaoHu->PortType) + RealAiDataDisp( hdc ); + break; + + case DI_DATA_DISP: + if(PROV_PROTOCOL != SioParam[CurPort].m_psBaoHu->PortType) + RealDiDataDisp( hdc ); + break; + + case PI_DATA_DISP: + if(PROV_PROTOCOL != SioParam[CurPort].m_psBaoHu->PortType) + RealPiDataDisp( hdc ); + break; + + case WATCH_DATA_DISP: + WatchDataDisp( hdc ); + break; + } + + DeleteObject( SelectObject(hdc, hFont) ); + + ReleaseDC( hWnd, hdc ); +} + +//*************************************************************** +//* 计算字串显示宽度和高度 * +//*************************************************************** +void CaculateWH( HDC hdc, UINT *xWidth, UINT *yHeight, char *szStr ) +{ + RECT rc; + + DrawText( hdc, (CONST WCHAR*)szStr, strlen(szStr), &rc, DT_CALCRECT ); + *xWidth = rc.right - rc.left; + *yHeight = rc.bottom - rc.top; +} + +//**************************************************************** +//* 显示数据上页? * +//**************************************************************** +void PageUp( void ) +{ + ListIndex -= ItemNumOfPage; + if ( ListIndex < 0 ) + ListIndex = 0; +} + +//*************************************************************** +//* 显示数据下页? * +//*************************************************************** +void PageDown( void ) +{ + ListIndex += ItemNumOfPage; +} + +//*************************************************************** +//* 显示端口最后一页数据 * +//*************************************************************** +void PageEnd( void ) +{ + ListIndex = 100000; +} + +//*************************************************************** +//* 显示端口最前一页数据? * +//*************************************************************** +void PageHome( void ) +{ + ListIndex = 0; +} + +void LineUp( void ) +{ + ListIndex--; + + if ( ListIndex < 0 ) + ListIndex = 0; +} + +//*************************************************************** +//* 显示下移一行? * +//*************************************************************** +void LineDown( void ) +{ + ListIndex++; +} + +int GetCurPort() +{ + return CurPort; +} + +int IsRealDataDisp() +{ + return RealDataDispFlag; +} diff --git a/display.h b/display.h new file mode 100644 index 0000000..2c33bfb --- /dev/null +++ b/display.h @@ -0,0 +1,55 @@ + +#include "common.h" + +#ifndef __DISPLAY_H_ICL__ +#define __DISPLAY_H_ICL__ + +#define WHITE 0 +#define DARKGRAY 1 +#define RED 2 +#define YELLOW 3 +#define GREEN 4 +#define CYAN 5 +#define BLUE 6 +#define MAGENTA 7 +#define GRAY 8 +#define BLACK 9 +#define BROWN 10 +#define DYELLOW 11 +#define DGREEN 12 +#define DCYAN 13 +#define DBLUE 14 +#define DMAGENTA 15 + +#define AI_DATA_DISP 4 +#define DI_DATA_DISP 5 +#define PI_DATA_DISP 6 + +#define WATCH_DATA_DISP 8 + +void RealAiDataDisp( HDC hdc ); +void RealDiDataDisp( HDC hdc ); +void RealPiDataDisp( HDC hdc ); +void RealStatInfoDisp( HDC hdc ); +void WatchDataDisp( HDC hdc ); + +int CheckDev( HDC hdc ); +void DataDisp( HWND hWnd ); + +HFONT NewFont( int nFSize ); + +void CaculateWH( HDC hdc, UINT *xWidth, UINT *yHeight, char *szStr ); + +void PageUp( void ); +void PageDown( void ); +void PageHome( void ); +void PageEnd( void ); +void LineUp( void ); +void LineDown( void ); + +// wen 2004.10.25 +int GetCurPort(); +int IsRealDataDisp(); + +#endif + diff --git a/filelist.txt b/filelist.txt new file mode 100644 index 0000000..d11de2f --- /dev/null +++ b/filelist.txt @@ -0,0 +1,11 @@ +portconfig.ini +config.ini +inf/scada.csv +inf/port103ser.csv +inf/port103sie.csv +inf/top9xxx_h.csv +dat/top9xxx_h.dat +dat/103-RCS925A.dat +dat/103-7SJ682.dat +dat/mach300.dat +inf/mach300.csv \ No newline at end of file diff --git a/global_errno.h b/global_errno.h new file mode 100644 index 0000000..7d8cf24 --- /dev/null +++ b/global_errno.h @@ -0,0 +1,803 @@ +/***************************************************************************** + * + * Copyright (C) 1999-2000 SCADA Technology Control Co., Ltd. All rights reserved. + * + * 2001/11/3 + * + * 全局性的共同性的错误代码宏定义, 以"ERROR_"开头 + * 公共的错误代码从1开始到0xffff结束. + * + * + * + * $Name: $ + * + * $Revision: 1.2 $ + * + * $Date: 2006/08/04 03:37:33 $ + * + * $State: Exp $ + * + + * $Log: global_errno.h,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.12 2003/09/17 15:00:37 scada + * 添加错误代码: ERROR_MKDIR/ERROR_OPEN/ERROR_EXIST + * + * Revision 1.11 2003/08/01 06:38:01 scada + * 定义在Windows操作系统上没有定义的, 但是SYSV(unix)系统上定义了的操作代码的基值 + * + * Revision 1.10 2003/06/05 03:56:15 jehu + * 将注释修改为符合doxgen工具提取开发文档 + * + * Revision 1.9 2003/01/15 10:25:41 scada + * update thread dead lock + * + * Revision 1.8 2003/01/02 03:14:29 scada + * trim substitution line + * + * Revision 1.7 2002/12/06 01:05:04 scada + * for NT + * + * Revision 1.6 2002/12/04 07:47:36 scada + * for NT + * + * Revision 1.5 2002/10/24 09:07:33 scada + * avoid conflict between ERROR_AUTHSERV_BASE and ERROR_RTDBM_BASE + * + * Revision 1.4 2002/10/10 07:31:27 jehu + * *** empty log message *** + * + * Revision 1.3 2002/10/09 13:01:29 harold + * add errno base macro ERROR_RTDBM_BASE + * + * Revision 1.2 2002/09/18 09:13:38 harold + * revised errors and warning under solaris/CC environment + * + * Revision 1.1.1.1 2002/08/21 07:16:36 harold + * temporarily import + * + * Revision 1.23 2002/07/26 13:07:55 scada + * 为写文件fputs调用失败添加一个全局错误代码=>ERROR_FPUTS + * + * Revision 1.22 2002/07/23 06:59:04 scada + * 使所有模块的错误代码的低16bit不等于0, 以免和进程返回成功码(低8bit)冲突 + * + * Revision 1.21 2002/07/12 10:01:47 harold + * add module errno base: ERROR_MISRELAY_BASE + * + * Revision 1.20 2002/06/03 08:47:05 harold + * add tracable module librmtcalc and rmtcalc + * + * Revision 1.19 2002/05/14 06:53:02 harold + * add ERROR_DBRW_BASE for dbrw module + * + * Revision 1.18 2002/04/12 08:58:38 harold + * global_errno.h + * + * Revision 1.17 2002/04/12 01:01:32 harold + * add ERROR_RECV and ERROR_TIMEOUT + * + * Revision 1.16 2002/04/09 13:19:36 harold + * *** empty log message *** + * + * Revision 1.15 2002/04/05 07:27:59 harold + * add error code ERROR_EXECV, ERROR_PTHREAD_CREATE + * + * Revision 1.14 2002/04/03 06:59:18 harold + * add EXP_STRCASECMP and EXP_STRNCASECMP for compare two string ignoring case + * + * Revision 1.13 2002/04/02 15:54:48 harold + * revise unkown linux-g++ compile error by copying the older tru64-cxx version + * + * Revision 1.12 2002/03/29 00:56:27 harold + * *** empty log message *** + * + * Revision 1.11 2002/03/20 03:39:56 harold + * no message + * + * Revision 1.2 2002/03/17 15:33:51 harold + * changed for iccp v0.9 + * + * Revision 1.1.1.1 2002/03/15 13:43:17 harold + * no message + * + * Revision 1.2 2002/03/15 13:10:03 harold + * *** empty log message *** + * + * Revision 1.1.1.1 2002/03/15 08:17:07 harold + * no message + * + * Revision 1.11 2002/03/11 11:02:53 harold + * *** empty log message *** + * + * Revision 1.10 2002/03/05 07:41:18 harold + * *** empty log message *** + * + * Revision 1.9 2002/03/05 03:01:34 harold + * *** empty log message *** + * + * Revision 1.8 2002/02/28 00:53:17 harold + * *** empty log message *** + * + * Revision 1.7 2002/02/27 13:04:29 harold + * no message + * + * Revision 1.6 2002/02/25 07:30:21 harold + * no message + * + * Revision 1.5 2002/01/25 09:11:19 harold + * no message + * + * Revision 1.4 2002/01/22 08:55:06 harold + * modify2002-01-22-16:46 + * + * Revision 1.3 2002/01/21 13:44:51 harold + * no message + * + * Revision 1.2 2002/01/18 10:01:39 harold + * 添加"读取配置文件函数库"错误代码基值定义 + * + * Revision 1.1.1.1 2001/12/24 09:33:23 harold + * no message + * + * Revision 1.2 2001/12/24 06:39:57 harold + * 为了适应不同的操作系统, 不同的CPU类型, 及不同的编译器, + * 对头文件做了相应的修改, 同时添加了一些宏定义, 如: + * HAVE__FUNCTION__, __OS__, __PLATFORM__,__TIMEZONE__等等. + * + * + *****************************************************************************/ + + +#ifndef __GLOBAL_ERROR_H__ADSFQEWRUPOHJCVLKJZHCVLKBAFLQWHPHFJJWTHNALSJFPQWJPH +#define __GLOBAL_ERROR_H__ADSFQEWRUPOHJCVLKJZHCVLKBAFLQWHPHFJJWTHNALSJFPQWJPH +/*! + * \if developer_doc + * \file + * + * \brief 全局性的共同性的错误代码宏定义, 以"ERROR_"开头,公共的错误代码从1开始到0xffff结束. + * + * id: $Id: global_errno.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif + */ + +/*! + * 函数执行成功 + */ +#define SUCCESS 0 + +#ifndef OS_WINDOWS +# ifndef ERROR_SUCCESS +# define ERROR_SUCCESS (SUCCESS) +# endif //end of ERROR_SUCCESS +#endif // end of defined(__unix) + +/*! + * 非错误性质的函数调用返回, 比如寻找缓冲区未找到等 + */ +#define ERROR_FAIL 1 + + +/*! + * 致命错误, 应该重新启动进程 + */ +#define ERROR_FATAL 2 + + +/*! + * 警告信息 + */ +#define ERROR_WARNING 3 + + +/*! + * 一些提示信息 + */ +#define ERROR_TIPINFO 4 + +/*! + * 功能未实现 + */ +#define ERROR_NOT_IMPLEMENT 5 + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 下面定义了各种库或者可执行模块中的错误代码基值 +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/*! + * 公共错误码的基础值 + */ +#define ERROR_BASE 10 + +/*! + * 定义在Windows操作系统上没有定义的, 但是SYSV(unix)系统上定义了的操作代码的基值 + * 要求常规的错误代码不能超过0xfff + */ +//#ifndef __unix +//# define ERROR_SYSV_BASE (ERROR_BASE + 0xfff) +//# include +//#endif + +/*! + * 实时数据库模块中的错误代码的基础值 + */ +#define ERROR_RTDB_BASE (0x10001) + + +/*! + * 历史库模块中的错误代码基础值 + */ +#define ERROR_HDB_BASE (0x20001) + + +/*! + * 调试记录模块中的错误代码基础值 + */ +#define ERROR_DBG_BASE (0x30001) + + +/*! + * 与Windows及旧Windows工作站软件上的日期时间兼容的日期时间处理库 + * 中的错误代码基础值 + */ +#define ERROR_XTIME_BASE (0x40001) + + +/*! + * 网络通信模块中的错误代码基础值 + */ +#define ERROR_NET_BASE (0x50001) + + +/*! + * 网络写库函数模块错误代码基值 + */ +#define ERROR_NET_WRITER_BASE (0x60001) + + +/*! + * DATASERV服务进程模块中的错误代码基值 + */ +#define ERROR_DATASERV_BASE (0x70001) + + +/*! + * 配置文件读写库模块中的错误代码基值 + */ +#define ERROR_CONF_BASE (0x80001) + + +/*! + * 事故追忆模块中的错误代码基值 + */ +#define ERROR_PDR_BASE (0x90001) + + +/*! + * 软件跟踪模块中的错误代码基值 + */ +#define ERROR_TRACE_BASE (0xA0001) + + +/*! + * 时间服务模块错误代码基值 + */ +#define ERROR_TMSERV_BASE (0xB0001) + + +/*! + * 报警库错误代码基值 + */ +#define ERROR_ALM_BASE (0xC0001) + + +/*! + * ICCP模块错误代码基值 + */ +#define ERROR_ICCP_BASE (0xD0001) + + +/*! + * telectrl模块的错误代码基值 + */ +#define ERROR_TELECTRL_BASE (0xE0001) + + +/*! + * dbrw模块的错误代码基值 + */ +#define ERROR_DBRW_BASE (0xF0001) + + +/*! + * 计算模块(libcal, cal, librmtcalc, rmtcalc)中的错误代码基值 + */ +#define ERROR_CALC_BASE (0x100001) + + +/*! + * Misserver中继服务模块中错误代码基值 + */ +#define ERROR_MISRELAY_BASE (0x110001) + +/*! + * AUTHSERV服务进程模块中的错误代码基值 + */ +#define ERROR_AUTHSERV_BASE (0x120001) + + +/*! + * rtdbm之模块dbstudio/rtattr_s中的错误处理代码定义 + */ +#define ERROR_RTDBM_BASE (0x130001) + + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 下面定义了最基本的错误代码, 则整个系统中公用 +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +/*! + * 不可预料的错误 + */ +#define ERROR_UNEXPECTED (ERROR_BASE + 1) + +/*! + * 代码在执行过程中, 发生异常, 没有明确指明发生了何种异常 + */ +#define ERROR_EXCEPTION (ERROR_BASE + 2) + +/*! + * 代码在执行过程中, 发生访问冲突异常 + */ +#define ERROR_EXCEPTION_ACCESS_VIOLATION (ERROR_BASE + 3) + +/*! + * 给函数传递的参数错误, 如缓冲区长度不合理(非期望的长度), + * 又如, 序号值没有在给定的范围内等等. + */ +#define ERROR_PARAMETER (ERROR_BASE + 4) + +/*! + * 在期望正确的指针参数时, 发现真正的指针参数为NULL + */ +#define ERROR_POINTER (ERROR_BASE + 5) + +/*! + * 内存分配不成功 + */ +#define ERROR_MEMORY_ALLOC (ERROR_BASE + 6) + +/*! + * 找不到指定的环境变量 + */ +#define ERROR_ENVIRONMENT_VARIABLE (ERROR_BASE + 7) + +/*! + * 指定键值的IPC对象不存在, 即还未创建. + */ +#define ERROR_IPC_OBJECT_EXISTED (ERROR_BASE + 8) + +/*! + * 打开文件调用fopen失败 + */ +#define ERROR_FOPEN (ERROR_BASE + 9) + +/*! + * 对文件内容调用fread失败. + */ +#define ERROR_FREAD (ERROR_BASE + 10) + +/*! + * 映射共享内存到进程地址空间失败(shmat) + */ +#define ERROR_SHMAT (ERROR_BASE + 11) + +/*! + * 取出进程空间中对共享内存的映射失败(shmdt) + */ +#define ERROR_SHMDT (ERROR_BASE + 13) + +/*! + * 信号量操作失败(semctl) + */ +#define ERROR_SEMCTL (ERROR_BASE + 14) + +/*! + * 系统没有足够的内存. + */ +#define ERROR_NO_MEMORY (ERROR_BASE + 15) + +/*! + * 原始字节流队列已满 + */ +#define ERROR_RAW_STREAM_QUEUE_IS_FULL (ERROR_BASE + 16) + +/*! + * 原始字节流队列已删除 + */ +#define ERROR_RAW_STREAM_QUEUE_IS_DELETE (ERROR_BASE + 17) + +/*! + * 原始字节流队列中没有足够的数据 + */ +#define ERROR_RAW_STREAM_QUEUE_NOT_ENOUGH_BYTE (ERROR_BASE + 18) + +/*! + * 动态连接库装载失败(dlopen) + */ +#define ERROR_SHLIB_DLOPEN (ERROR_BASE + 19) + +/*! + * 调用msgctl删除消息队列失败 + */ +#define ERROR_MSGCTL_RMID (ERROR_BASE + 20) + +/*! + * 调用msgget创建消息队列ipc对象失败 + */ +#define ERROR_MSGGET_CREATE (ERROR_BASE + 21) + +/*! + * 无效的消息队列ipc对象的id + */ +#define ERROR_MSG_QUEUE_ID (ERROR_BASE + 22) + +/*! + * 从消息队列接收消息发生不可预料的错误 + */ +#define ERROR_MSGRCV (ERROR_BASE + 23) + +/*! + * 消息队列中当前被接收的消息超过给定的缓冲区 + */ +#define ERROR_MSGRCV_TOO_BIG_ITEM (ERROR_BASE + 24) + +/*! + * 欲操作的消息队列已经被删除(不存在, 需要重新创建) + */ +#define ERROR_MSG_QUEUE_REMOVED (ERROR_BASE + 25) + + +/*! + * 消息队列中没有消息 + */ +#define ERROR_MSGRCV_NO_MSG (ERROR_BASE + 26) + +/*! + * 调用msgget引用消息队列失败. + */ +#define ERROR_MSGGET_REFER (ERROR_BASE + 27) + +/*! + * 调用SHMCTL获取共享内存属性失败 + */ +#define ERROR_SHMCTL_STAT (ERROR_BASE + 28) + +/*! + * 用于共享内存的挂接进程数目不为零而不能删除它. + */ +#define ERROR_DELETE_ATTACHED_SHM (ERROR_BASE + 29) + +/*! + * 调用shmctl删除共享内存失败 + */ +#define ERROR_SHMCTL_RMID (ERROR_BASE + 30) + +/*! + * 调用shmctl锁定共享内存失败 + */ +#define ERROR_SHMCTL_LOCK (ERROR_BASE + 31) + + +/*! + * 调用shmctl解除共享内存锁定失败 + */ +#define ERROR_SHMCTL_UNLOCK (ERROR_BASE + 32) + + +/*! + * 调用semctl删除信号量组失败 + */ +#define ERROR_SEMCTL_RMID (ERROR_BASE + 33) + +/*! + * 调用shmget引用给定键值的共享内存区域失败 + */ +#define ERROR_SHMGET_REFER (ERROR_BASE + 34) + +/*! + * 调用shmget创建给定键值的共享内存区域失败 + */ +#define ERROR_SHMGET_CREATE (ERROR_BASE + 35) + +/*! + * 无效的进程内共享内存映射地址 + */ +#define ERROR_SHM_ADDR_INVALID (ERROR_BASE + 36) + +/*! + * 调用semop函数失败 + */ +#define ERROR_SEMOP (ERROR_BASE + 37) + +/*! + * 不存在指定的文件 + */ +#define ERROR_NO_FILE (ERROR_BASE + 38) + +/*! + * 调用stat取文件属性失败 + */ +#define ERROR_STAT (ERROR_BASE + 39) + +/*! + * 调用shmget失败, 创建一个新的信号量组失败 + */ +#define ERROR_SEMGET_CREATE (ERROR_BASE + 40) + +/*! + * 调用shmget失败, 创建一个新的信号量组失败 + */ +#define ERROR_SEMGET_REFER (ERROR_BASE + 41) + +/*! + * 调用fwrite失败 + */ +#define ERROR_FWRITE (ERROR_BASE + 42) + +/*! + * 参数中指定的缓冲区长度不够 + */ +#define ERROR_BUFFER_LENGTH (ERROR_BASE + 43) + +/*! + * 无效的属性号 + */ +#define ERROR_ATTR_NO (ERROR_BASE + 44) + +/*! + * 错误的SCADA日期时间串(这里仅指示日期时间串的格式错误, 不表明 + * 其包含的日期时间值的正确与否 + */ +#define ERROR_SCADA_DT_STRING (ERROR_BASE + 45) + + +/*! + * 缓冲区中的参数不完整(非自洽) + */ +#define ERROR_BUFFER_INTEGRALITY (ERROR_BASE + 46) + + +/*! + * 调用gethostname函数失败 + */ +#define ERROR_GETHOSTNAME (ERROR_BASE + 47) + + +/*! + * 调用gethostbyname函数失败 + */ +#define ERROR_GETHOSTBYNAME (ERROR_BASE + 48) + + +/*! + * 调用sendto非阻塞型失败 + */ +#define ERROR_SENDTO (ERROR_BASE + 49) + + +/*! + * 接收到的消息的长度与与其预期的长度不等. + */ +#define ERROR_MSG_UNEXPECTED_LENGTH (ERROR_BASE + 50) + + +/*! + * 接收到的消息的类型与预期的不相同. + */ +#define ERROR_MSG_UNEXPECTED_TYPE (ERROR_BASE + 51) + + +/*! + * 调用socket创建套接字失败 + */ +#define ERROR_SOCKET (ERROR_BASE + 52) + +/*! + * 调用bind绑定套接字失败 + */ +#define ERROR_BIND (ERROR_BASE + 53) + + +/*! + * 调用fcntl失败 + */ +#define ERROR_FCNTL (ERROR_BASE + 54) + + +/*! + * 调用setsockopt失败 + */ +#define ERROR_SETSOCKOPT (ERROR_BASE + 55) + +/*! + * 调用getsockopt失败 + */ +#define ERROR_GETSOCKOPT (ERROR_BASE + 56) + + +/*! + * 调用connect建立网络连接失败 + */ +#define ERROR_CONNECT (ERROR_BASE + 57) + + +/*! + * 调用read意外失败 + */ +#define ERROR_READ (ERROR_BASE + 58) + + +/*! + * 调用write意外失败 + */ +#define ERROR_WRITE (ERROR_BASE + 59) + + +/*! + * 调用select函数意外失败 + */ +#define ERROR_SELECT (ERROR_BASE + 60) + + +/*! + * 调用listen函数失败 + */ +#define ERROR_LISTEN (ERROR_BASE + 61) + + +/*! + * 执行fork调用失败 + */ +#define ERROR_FORK (ERROR_BASE + 62) + + +/*! + * 执行execve调用失败 + */ +#define ERROR_EXECVE (ERROR_BASE + 63) + + +/*! + * 执行execv调用失败 + */ +#define ERROR_EXECV (ERROR_BASE + 64) + + +/*! + * 创建线程失败pthread_create调用失败 + */ +#define ERROR_PTHREAD_CREATE (ERROR_BASE + 65) +#define ERROR_CREATE_THREAD ERROR_PTHREAD_CREATE + +/*! + * 调用recv接收套接字上的数据失败 + */ +#define ERROR_RECV (ERROR_BASE + 66) + + +/*! + * 因为超时而失败 + */ +#if defined(OS_LINUX) +#ifndef ERROR_TIMEOUT +#define ERROR_TIMEOUT (ERROR_BASE + 67) +#endif //end of ERROR_TIMEOUT +#endif // end of defined(__unix) + + +/*! + * 调用send失败 + */ +#define ERROR_SEND (ERROR_BASE + 68) + + +/*! + * 调用select后, 发现异常fdset集合中异常事件. + */ +#define ERROR_SELECT_EXCEPTION (ERROR_BASE + 69) + + +/*! + * 当select探测到读事件, 但是随后读操作中仅读到0个字节 + */ +#define ERROR_READ_ZERO (ERROR_BASE + 70) + + +/*! + * 当select探测到写事件, 但是随后写操作中仅写入0个字节 + */ +#define ERROR_WRITE_ZERO (ERROR_BASE + 71) + + +/*! + * 当select探测接收事件, 但是随后接收操作中仅接收到0个字节 + */ +#define ERROR_RECV_ZERO (ERROR_BASE + 72) + + +/*! + * 当select探测可以发送事件, 但是随后发送操作中仅发送了0个字节 + */ +#define ERROR_SEND_ZERO (ERROR_BASE + 73) + + +/*! + * 不存在指定的目标 + */ +#define ERROR_NOT_EXIST (ERROR_BASE + 74) + + +/*! + * 事务操作提交失败 + */ +#define ERROR_COMMIT (ERROR_BASE + 75) + + +/*! + * 事务操作撤销/回滚失败 + */ +#define ERROR_ROLLBACK (ERROR_BASE + 76) + + +/*! + * 调用fputs写文件失败 + */ +#define ERROR_FPUTS (ERROR_BASE + 77) + + +/*! + * 调用mkdir失败 + */ +#define ERROR_MKDIR (ERROR_BASE + 78) + + +/*! + * 调用OPEN失败 + */ +#define ERROR_OPEN (ERROR_BASE + 79) + + +/*! + * 指定目标已经存在 + */ +#define ERROR_EXIST (ERROR_BASE + 80) + + +/*! + * 调用fseek失败 + */ +#define ERROR_FSEEK (ERROR_BASE + 81) + + +/*! + * 调用rename/MoveFile/MoveFileEx失败 + */ +#define ERROR_RENAME (ERROR_BASE + 82) + +/*! + * 无需运行cpfile.exe(当cpfile.exe在主服务器上时,返回本错误) + */ +#define ERROR_RUN_CPFILE_TCP_C_ON_PRAMIRY_HOST (ERROR_BASE + 83) + +/*! + * 从消息队列中接收到无效的实时/历史数据请求数据帧类型 + */ +#define ERROR_AUTHSERV_UNKNOWN_NET_FRAME (ERROR_AUTHSERV_BASE + 1) + + + +#endif //__GLOBAL_ERROR_H__ADSFQEWRUPOHJCVLKJZHCVLKBAFLQWHPHFJJWTHNALSJFPQWJPH diff --git a/harximoban.h b/harximoban.h new file mode 100644 index 0000000..ae0d56c --- /dev/null +++ b/harximoban.h @@ -0,0 +1,1021 @@ +/****************************************************************************************** + * + * 作者: 杨小波 + * + * 链地址哈希模板 + * + * 目的: + * 提供一个模板, 为日常应用中需要按哈希方法组织数据提供一个模板类. + * 该哈希模板采用链地址法解决冲突. + * + * $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * $Log: harximoban.h,v $ + * Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * no message + * + * Revision 1.5 2003/06/05 03:56:21 jehu + * 将注释修改为符合doxgen工具提取开发文档 + * + * Revision 1.4 2003/05/06 02:31:31 scada + * 添加替换标记: $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $, $Log: harximoban.h,v $ + * 添加替换标记: $Id: chain_hash.h,v 1.5 2003/06/05 03:56:21 jehu Exp $, Revision 1.2 2006/08/04 03:37:33 zhuzhenhua + * 添加替换标记: $Id: chain_hash.h,v 1.5 2003/06/05 03:56:21 jehu Exp $, no message + * 添加替换标记: $Id: chain_hash.h,v 1.5 2003/06/05 03:56:21 jehu Exp $, + * 添加替换标记: $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $, Revision 1.5 2003/06/05 03:56:21 jehu + * 添加替换标记: $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $, 将注释修改为符合doxgen工具提取开发文档 + * 添加替换标记: $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $, + * + * + ******************************************************************************************/ + +#ifndef __CHAIN_HASH_H__ASDFJQWPEUTOUDSAFHJDSAFADSAFWQERUGSKGEWRTPYZNXM +#define __CHAIN_HASH_H__ASDFJQWPEUTOUDSAFHJDSAFADSAFWQERUGSKGEWRTPYZNXM + /*! + * \if developer_doc + * \file + * + * \brief 链地址哈希模板,头文件。 + * + * 提供一个模板, 为日常应用中需要按哈希方法组织数据提供一个模板类, + * 该哈希模板采用链地址法解决冲突.\n + * id: $Id: harximoban.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif +*/ + +/*! +* \brief 最小的默认哈希表尺寸 +*/ +#define CONST_CHAIN_HASH_DEFAULT_MIN_SIZE 0x10 + + +/*! +* \brief 最大的默认哈希尺寸 +*/ +#define CONST_CHAIN_HASH_DEFAULT_MAX_SIZE 0xffff + + + +/*! +* \brief 链地址哈希表模板 +* \param T ---- 在哈希表中存储的元素的类型 +* +* \par 快速参考 +* #include +*/ +#pragma pack (1) +// 是pc机系统还是嵌入式系统 + +#ifdef PC_MACHINE + +#ifdef OS_WINDOWS + + #pragma pack (push,1) + +#else// OS_UNIX + +#pragma pack(1) + +#endif //OS_UNIX +#endif + + +template class TChainHash +{ +public: + /*! 根据哈希表存储的元素的关键字以及哈希表的尺寸,求哈希序号的函数重定义 */ + typedef u32 (* pfnindex_of_t)(const void * pKey, u32 hash_size); + /*! 根据哈希表存储的元素的关键字的函数重定义 */ + typedef void * (* pfnkey_of_t)(const T * pItem); + /*! 两个哈希表中存储的元素的关键字之间的比较,主要是比较是否相等 */ + typedef int (* pfncompare_t)(const void * pKey1, const void * pKey2); + /*! 根据已经一个已经存在的哈希元素,赋值一个新的对象 */ + typedef T * (* pfncreate_item_t)(const T * pItem); + /*! 释放调用 *pfncreate_item_t 返回的对象 */ + typedef void (* pfnfree_item_t)(T * pItem); + /*! 哈希元素之间的拷贝 */ + typedef T * (* pfncopy_item_t)(T * pItemDest, const T * pItemSrc); + /*! 使用者提供的内存分配函数 */ + typedef void * (* pfnalloc_t)(u32 size); + /*! 释放调用 *pfnalloc_t 分配的内存 */ + typedef void (* pfndealloc_t)(void *); + + /*! + * 哈希数组项保存的"数据" + */ + typedef struct + { + /*! + * 哈希数组项保存的"数据" + */ + T * pT; + + /*! + * 调用使用者提供的哈希键值函数返回的键值 + */ + void * pvTKey; + + } ITEM_t, *PITEM_t, **PPITEM_t; + + + + /*! + * 哈希表的一行, 这一行保存所有"同义"哈希项, \n + * 这一行实际上是产生冲突的所有的哈希项的数组.\n + * 在简单地使用线性数组的方式保存. + */ + typedef struct + { + /*! + * 数组中已有数据项的大小--冲突的个数 + */ + u32 cntItems; + + /*! + * 在这一行内能够容纳的最大冲突元素个数. + * 实际上是分配给数组pItems的实际内存的大小 + */ + u32 cntAllocItems; + + /*! + * 数组本身 + */ + PITEM_t pItems; + + /*! + * 哈希项保存的"数据" + */ + T * pT; + + /*! + * 数据项的键值 + */ + void * pvTKey; + + } TABLEENTRY_t, *PTABLEENTRY_t, **PPTABLEENTRY_t; + + +private: + /*! + * 不容许使用缺省构造函数. + */ + TChainHash(){}; + +public: + /*! + * \brief 构造函数 + * + * \param u32TableSize --[in] 哈希表的大小 + * \param pfnIndexOf --[in] 使用者提供的从键值到哈希值的转换函数 + * \param pfnKeyOf --[in] 使用者提供的返回一个哈希项保存的数据项的关键值. + * \param pfnCompare --[in] 比较两个数据项的关键字的大小 + * \param pfnCreateItem --[in] 使用者提供的从一个给定数据项的创建另一个新的数据项的函数 + * \param pfnFreeItem --[in] 使用者提供的用户释放数据项的函数 + * \param pfnCopyItem --[in] 使用者提供的拷贝函数. + * \param pfnAlloc --[in] 使用者提供的用户分配内存的函数. + * \param pfnDeAlloc --[in] 使用者提供的用户释放由pfnAlloc所分配的内存的函数 + * + * \note + * 在构造函数不会调用使用从构造函数传递的参数函数. + * 参数中的函数指针的类型定义说明参见模板中与这些函数指针项对应的成员变量. + */ + TChainHash( + u32 u32TableSize, + u32 (* pfnIndexOf)(const void * pKey, u32 hash_size), + void * (* pfnKeyOf)(const T * pItem), + int (* pfnCompare)(const void * pKey1, const void * pKey2), + T * (* pfnCreateItem)(const T * pItem), + void (* pfnFreeItem)(T * pItem), + T * (* pfnCopyItem)(T * pItemDest, const T * pItemSrc), + void * (* pfnAlloc)(u32 size), + void (* pfnDeAlloc)(void *) + ) + { + /* + * 记住使用者提供的工具函数 + */ + if(pfnIndexOf) + m_pfnIndexOf = pfnIndexOf; + else + m_pfnIndexOf = NULL; + + if(pfnKeyOf) + m_pfnKeyOf = pfnKeyOf; + else + m_pfnKeyOf = NULL; + + if(pfnCompare) + m_pfnCompare = pfnCompare; + else + m_pfnCompare = NULL; + + if(pfnCreateItem) + m_pfnCreateItem = pfnCreateItem; + else + m_pfnCreateItem = NULL; + + if(pfnFreeItem) + m_pfnFreeItem = pfnFreeItem; + else + m_pfnFreeItem = NULL; + + if(pfnCopyItem) + m_pfnCopyItem = pfnCopyItem; + else + m_pfnCopyItem = NULL; + + if(pfnAlloc) + m_pfnAlloc = pfnAlloc; + else + m_pfnAlloc = NULL; + + if(pfnDeAlloc) + m_pfnDeAlloc = pfnDeAlloc; + else + m_pfnDeAlloc = NULL; + + /* + * 初始化哈希表的尺寸 + */ + m_uiSize = u32TableSize; + if(m_uiSize > (u32)CONST_CHAIN_HASH_DEFAULT_MAX_SIZE) + m_uiSize = (u32)CONST_CHAIN_HASH_DEFAULT_MAX_SIZE; + + if(m_uiSize < CONST_CHAIN_HASH_DEFAULT_MIN_SIZE) + m_uiSize = CONST_CHAIN_HASH_DEFAULT_MIN_SIZE; + + + /* + * 初始化哈希表 + */ + if(m_pfnAlloc && m_pfnDeAlloc) + m_pTable = (PTABLEENTRY_t)(*m_pfnAlloc)((u32)sizeof(TABLEENTRY_t) * m_uiSize); + else + m_pTable = (PTABLEENTRY_t) new u_8[(sizeof(TABLEENTRY_t) * m_uiSize)]; + + if(NULL != m_pTable) + memset((void *)m_pTable, 0, sizeof(TABLEENTRY_t) * m_uiSize); + } + + + /*! + * \brief 析构函数 + */ + virtual ~TChainHash() + { + if(NULL == m_pTable) + return; + + /* + * 释放哈希表中同义词数组所占用的内存空间. + */ + for(u32 i = 0; i < m_uiSize; i++) + { + if(NULL != m_pTable[i].pItems) + { + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(m_pTable[i].pItems); + m_pTable[i].pItems = NULL; + } + else + { + delete m_pTable[i].pItems; + m_pTable[i].pItems = NULL; + } + } + } + + /* + * 释放哈希表所占用的内存空间 + */ + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(m_pTable); + m_pTable = NULL; + } + else + { + delete m_pTable; + m_pTable = NULL; + } + } + + +private: + /*! + * 哈希链表的尺寸 + */ + u32 m_uiSize; + + + /*! + * 哈希表 + */ + PTABLEENTRY_t m_pTable; + + + /*! + * \brief 用户定义的返回一个哈希表项的索引值函数, 传给函数的参数有本哈希表的当前无冲突尺寸 + * + * \param pKey --[in] 数据项的键值 + * \param hash_size --[in] 本哈希表的尺寸 + * + * \return + * [0 -- hash_size - 1)范围内的整数 + */ + u32 (* m_pfnIndexOf)(const void * pKey, u32 hash_size); + + + /*! + * \brief 返回一个哈希表项的键值 + * + * \param pItem --[in] 数据项 + * + * \return + * 数据项的键值 + */ + void * (* m_pfnKeyOf)(const T * pItem); + + + /*! + * \brief 比较两个哈希表项的大小 + * + * \param pKey1 --[in] 键值1 + * \param pKey2 --[in] 键值2 + * + * \return + * 大于0 -- pKey1所代表的数据项大于pKey2所代表的数据项 + * 0 -- pKey1所代表的数据项等于pKey2所代表的数据项 + * 小于0 -- pKey1所代表的数据项小于pKey2所代表的数据项 + */ + int (* m_pfnCompare)(const void * pKey1, const void * pKey2); + + + /*! + * \brief 以一个已知表项为蓝本, 创建一个新的哈希表项. + * + * \param pItem --[in] 源数据项 + * + * \return + * 新的数据项 + */ + T * (* m_pfnCreateItem)(const T * pItem); + + + /*! + * \brief 和m_pfnCreateItem的派对, 用于释放由m_pfnCreateItem创建的哈希表项 + * + * \param pItem --[in] 欲被释放的数据项 + */ + void (* m_pfnFreeItem)(T * pItem); + + + /*! + * \brief 拷贝源哈希表项到目的哈希表项. + * + * \param pItemDest --[in] 目的数据项 + * \param pItemSrc --[in] 源数据项 + * + * \return + * 目的数据项 + */ + T * (* m_pfnCopyItem)(T * pItemDest, const T * pItemSrc); + + + /*! + * \brief 用户提供的分配内存的函数, 使用该函数, 可以使该链地址哈希模板与内存分配方法无关. + * + * \param size --[in] 欲分配内存的尺寸, 以字节为单位 + * + * \return + * 分配的内存的指针 + */ + void * (* m_pfnAlloc)(u32 size); + + + /*! + * \brief 是m_pfnAlloc的派对, 用于释放由m_pfnAlloc分配的内存, 其参数一定是由m_pfnAlloc所返回的值. + * + * \param pVoid --[in][out] 调用m_pfnAlloc分配的内存 + */ + void (* m_pfnDeAlloc)(void * pVoid); + + + /*! + * \brief 当哈希表中的一行空间不够时, 需要增加空间, + * 由于是内部私有函数, 因此在调用时, 内部代码必须保证参数的正确性. + * + * \param pEntry -- 哈希表中的一行. + * + * \retval true -- 成功 + * \retval false -- 失败 + * + * \note + * 在函数实现中使用倍增式的分配内存 + */ + bool increaseSynonyms(PTABLEENTRY_t pEntry) + { + // 倍增式地分配内存 + u32 count = pEntry->cntAllocItems; + if(0 == count) + count = 2; + else + count = count * 2; + + // 首先分配目的尺寸的哈希项数组--同义词数组 + PITEM_t pItems = NULL; + if(m_pfnAlloc && m_pfnDeAlloc) + pItems = (PITEM_t) (*m_pfnAlloc)(count * (u32)sizeof(ITEM_t)); + else + pItems = (PITEM_t) new u_8[count * sizeof(ITEM_t)]; + + if(NULL != pItems) + memset((void *)pItems, 0, count * sizeof(ITEM_t)); + else + return false; + + + // 拷贝, 此处显然两块内存不会重叠, 所以使用memcpy内存拷贝, 而不是memmove + memcpy((void *)pItems, (void *)pEntry->pItems, pEntry->cntItems * sizeof(ITEM_t)); + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(pEntry->pItems); + pEntry->pItems = NULL; + } + else + { + delete pEntry->pItems; + pEntry->pItems = NULL; + } + + pEntry->pItems = pItems; + pEntry->cntAllocItems = count; + return true; + } + + + /*! + * \brief 将一个元素插入到指定的"行", 由于是内部私有函数, 因此在调用时, 内部代码必须保证参数的正确性. + * + * \param pEntry --[in] 哈希表中的一行 + * \param pT --[in] 欲插入的数据项 + * \param pvTKey --[in] 欲插入的数据项的键值. + * + * \retval true -- 成功 + * \retval false -- 失败 + * + * \note + * 如果返回失败, 则原同义词数组不发生任何变化. + */ + bool insertIntoEntry(PTABLEENTRY_t pEntry, T * pT, void * pvTKey) + { + if(NULL == pEntry->pT) + { + pEntry->pT = pT; + pEntry->pvTKey = pvTKey; + return true; + } + + if(pEntry->cntItems == pEntry->cntAllocItems) + { + if(false == increaseSynonyms(pEntry)) + return false; + } + + u32 count = pEntry->cntItems; + pEntry->pItems[count].pT = pT; + pEntry->pItems[count].pvTKey = pvTKey; + pEntry->cntItems++; + + return true; + } + +public: + /*! + * \brief 返回哈希表的尺寸 + */ + u32 hash_size() + { + return m_uiSize; + } + + + /*! + * \brief 返回在哈希表中保存的数据项的个数 + */ + u32 count() + { + u32 count; + + PTABLEENTRY_t pEntry = NULL; + for(int i = 0; i < m_uiSize; i++) + { + if(NULL != pEntry->pT) + count += 1; + + if(pEntry->cntItems > 0 && NULL != pEntry->pItems) + count += pEntry->cntItems + 1; + } + + return count; + } + + + /*! + * \brief 搜索指定关键字的哈希元素, 返回第一个搜索到的元素, 因此, 应该保证没有重复的关键字. + * + * \param pKey --[in] 数据项的键值 + * + * \retval 和数据项的键值相对应的数据项 -- 成功 + * \retval NULL -- 失败, 或者, 在哈希表中根本就没有这一项 + * + * \note + * 搜索过程不会改变哈希表及哈希表所保存的数据项及数据项的键值,\n + * 在函数的实现中使用到使用者提供的函数:\n + * pfnKeyOf -- 使用者提供的返回一个哈希项保存的数据项的关键值;\n + * pfnCompare -- 比较两个数据项的关键字的大小;\n + */ + T * searchItem(const void * pKey) + { + if(NULL == m_pTable || NULL == m_pfnIndexOf || NULL == m_pfnCompare) + return NULL; + + /* + * 由键值求哈希值. + */ + u32 u32index = (*m_pfnIndexOf)(pKey, m_uiSize); + if(u32index >= m_uiSize) + return NULL; + + // 找到同义词数组 + PTABLEENTRY_t pEntry = &m_pTable[u32index]; + if(NULL != pEntry->pT && 0 == (*m_pfnCompare)(pKey, pEntry->pvTKey)) + return pEntry->pT; + + // 查看首项是否符合. + u32 count = pEntry->cntItems; + PITEM_t pSynonyms = pEntry->pItems; + if(0 == count || NULL == pSynonyms) + return NULL; + + // 在同义词数组中作线性搜索 + for(u32 i = 0; i < count; i++) + { + if(pSynonyms[i].pT) + { + if(0 == (*m_pfnCompare)(pKey, pSynonyms[i].pvTKey)) + return pSynonyms[i].pT; + } + } + + return NULL; + } + + + /*! + * \brief 如果原先的哈希表的尺寸比较小, 后来需要其管理的数据项急剧增加, + * 这样会造成冲突严重, 后果是影响到查询的效率, 因此, 需要能够动态 + * 的改变哈希表的尺寸 + * + * \param size --[in] 新的哈希表尺寸 + * + * \retval true -- 成功 + * \retval false -- 失败 + * + * \note + * 如果调用失败, 函数保证原哈希表不发生任何变化.\n + * 在函数实现中使用了使用者提供的函数, \n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数. + */ + bool resize(u32 size) + { + if(size == m_uiSize || NULL == m_pfnIndexOf) + return true; + + // 设置新的尺寸 + u32 u32Size = size; + if(u32Size > CONST_CHAIN_HASH_DEFAULT_MAX_SIZE) + u32Size = CONST_CHAIN_HASH_DEFAULT_MAX_SIZE; + if(u32Size < CONST_CHAIN_HASH_DEFAULT_MIN_SIZE) + u32Size = CONST_CHAIN_HASH_DEFAULT_MIN_SIZE; + + // 分配哈希表 + PTABLEENTRY_t pTable = NULL; + if(m_pfnAlloc && m_pfnDeAlloc) + pTable = (PTABLEENTRY_t) (*m_pfnAlloc)(sizeof(TABLEENTRY_t) * size); + else + pTable = (PTABLEENTRY_t) new unsigned char[sizeof(TABLEENTRY_t) * size]; + + if(NULL == pTable) + return false; + + memset((void *)pTable, 0, sizeof(TABLEENTRY_t) * size); + + // 把原哈希表中的元素逐个插入到新的哈希表中去 + u32 u32Index = 0; + PITEM_t pSynonyms = NULL; + u32 i = 0, j = 0; + for(i = 0; i < m_uiSize; i++) + { + if(NULL != m_pTable[i].pT) + { + u32Index = (*m_pfnIndexOf)(m_pTable[i].pvTKey, u32Size); + if(u32Index >= u32Size) + goto label_failed_resize; + + if(!insertIntoEntry(&pTable[u32Index], m_pTable[i].pT, m_pTable[i].pvTKey)) + goto label_failed_resize; + } + + pSynonyms = m_pTable[i].pItems; + for(j = 0; j < m_pTable[i].cntItems; j++) + { + if(NULL != pSynonyms[j].pT) + { + u32Index = (*m_pfnIndexOf)(pSynonyms[j].pvTKey, u32Size); + if(u32Index >= u32Size) + goto label_failed_resize; + + if(false == insertIntoEntry(&pTable[u32Index], pSynonyms[j].pT, pSynonyms[j].pvTKey)) + goto label_failed_resize; + } + } + } + + // 释放原哈希表所扎内存 + for(i = 0; i < m_uiSize; i++) + { + if(NULL != m_pTable[i].pItems) + { + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(m_pTable[i].pItems); + m_pTable[i].pItems = NULL; + } + else + { + delete m_pTable[i].pItems; + m_pTable[i].pItems = NULL; + } + } + } + + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(m_pTable); + m_pTable = NULL; + } + else + { + delete m_pTable; + m_pTable = NULL; + } + + // 置换新的哈希表及尺寸 + m_pTable = pTable; + m_uiSize = u32Size; + + return true; + + // 如果执行失败, 则释放执行过程中分配的内存 + label_failed_resize: + for(i = 0; i < u32Size; i++) + { + if(NULL != pTable[i].pItems) + { + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(pTable[i].pItems); + pTable[i].pItems = NULL; + } + else + { + delete pTable[i].pItems; + pTable[i].pItems = NULL; + } + } + } + + if(m_pfnAlloc && m_pfnDeAlloc) + { + (*m_pfnDeAlloc)(pTable); + pTable = NULL; + } + else + { + delete pTable; + pTable = NULL; + } + + return false; + } + + + /*! + * \brief 插入一个哈希表项 + * + * \param pT --[in] 欲插入的数据项 + * + * \retval true -- 成功 + * \retval false -- 失败 + * + * \note + * 在失败的情况下, 函数实现保证原哈希表不发生任何变化.\n + * 在函数实现中使用了使用者提供的函数\n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数\n + * pfnKeyOf -- 使用者提供的返回一个哈希项保存的数据项的关键值. + */ + bool insertItem(T * pT) + { + if(NULL == pT || NULL == m_pTable || NULL == m_pfnKeyOf || NULL == m_pfnIndexOf) + return false; + + // 求关键字及哈希值 + void * pKey = (*m_pfnKeyOf)(pT); + u32 index = (*m_pfnIndexOf)(pKey, m_uiSize); + if(index >= m_uiSize) + return false; + + PTABLEENTRY_t pEntry = &m_pTable[index]; + if(NULL == pEntry->pT) + { + pEntry->pT = pT; + pEntry->pvTKey = pKey; + return true; + } + + // 插入到同义词数组中去 + if(pEntry->cntItems == pEntry->cntAllocItems) + { + if(false == this->increaseSynonyms(pEntry)) + return false; + } + + PITEM_t pSynonyms = pEntry->pItems; + u32 count = pEntry->cntItems; + pSynonyms[count].pT = pT; + pSynonyms[count].pvTKey = pKey; + pEntry->cntItems++; + return true; + } + + /*! + * \brief 删除一个哈希表项 + * + * \param pT --[in] 数据项 + * + * \retval true -- 成功地删除了指定地数据项 + * \retval false -- 失败, 或者, 哈希表中没有指定的数据项 + * + * \note + * 在返回false的情况下, 函数实现保证原哈希表不发生任何变化\n + * 在函数实现中使用了使用者提供的函数\n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数\n + * pfnKeyOf -- 使用者提供的返回一个哈希项保存的数据项的关键值. \n + * pfnCompare -- 比较两个数据项的关键字的大小\n + * pfnFreeItem-- 使用者提供的用户释放由pfnAlloc所分配的内存的函数 + */ + bool deleteItem(T * pT) + { + if(NULL == pT || NULL == m_pTable || NULL == m_pfnKeyOf + || NULL == m_pfnIndexOf || NULL == m_pfnCompare || NULL == m_pfnFreeItem) + return false; + + void * pKey = (*m_pfnKeyOf)(pT); + return deleteItem_with_key(pKey); + } + + /*! + * \brief 删除一个哈希表项 + * + * \param pKey --[in] 欲被删除的数据项的键值 + * + * \retval true -- 成功地删除了指定地数据项 + * \retval false -- 失败, 或者, 哈希表中没有指定的数据项 + * + * \note + * 在返回false的情况下, 函数实现保证原哈希表不发生任何变化\n + * 在函数实现中使用了使用者提供的函数\n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数\n + * pfnCompare -- 比较两个数据项的关键字的大小\n + * pfnFreeItem -- 使用者提供的用户释放由pfnAlloc所分配的内存的函数 + */ + bool deleteItem_with_key(void * pKey) + { + u32 i = 0; + + if(NULL == m_pTable || NULL == m_pfnIndexOf || NULL == m_pfnCompare || NULL == m_pfnFreeItem) + return false; + + // 求哈希值 + u32 index = (*m_pfnIndexOf)(pKey, m_uiSize); + if(index >= m_uiSize) + return false; + + PTABLEENTRY_t pEntry = &m_pTable[index]; + if(NULL != pEntry->pT && 0 == (*m_pfnCompare)(pKey, pEntry->pvTKey)) + { + (*m_pfnFreeItem)(pEntry->pT); + pEntry->pT = NULL; + pEntry->pvTKey = NULL; + return true; + } + + if(0 == pEntry->cntItems || NULL == pEntry->pItems) + return false; + + u32 count = pEntry->cntItems; + PITEM_t pSynonyms = pEntry->pItems; + for(i = 0; i < count; i++) + { + if(NULL == pSynonyms[i].pT) + continue; + + if(0 == (*m_pfnCompare)(pKey, pSynonyms[i].pvTKey)) + { + (*m_pfnFreeItem)(pSynonyms[i].pT); + pSynonyms[i].pT = NULL; + pSynonyms[i].pvTKey = NULL; + memmove((void *)(pSynonyms + i), (void *)(pSynonyms + i + 1), sizeof(*pSynonyms) * (count - i - 1)); + memset((void *)(pSynonyms + count - 1), 0, sizeof(*pSynonyms)); + pEntry->cntItems -= 1; + break; + } + } + + if(i == count) + return false; + else + return true; + } + + /*! + * \brief 从哈希表中分离出一个指定的哈希表项 + * + * \param pT --[in] 欲被从哈希表中分离出来的数据项 + * + * \retval 分离出来的数据项 -- 成功 + * \retval NULL -- 失败, 或者, 哈希表中根本就没有欲分离的数据项 + * + * \note + * 在函数执行成功的情况下, 该数据项从哈希表中移出.\n + * 在返回NULL的情况下, 函数实现保证原哈希表不发生任何变化\n + * 在函数实现中使用了使用者提供的函数\n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数\n + * pfnKeyOf -- 使用者提供的返回一个哈希项保存的数据项的关键值. \n + * pfnCompare -- 比较两个数据项的关键字的大小\n + */ + T * detachItem(T * pT) + { + if(NULL == pT || NULL == m_pfnKeyOf || NULL == m_pfnIndexOf || NULL == m_pfnCompare) + return NULL; + + void * pKey = (*m_pfnKeyOf)(pT); + return detachItem_with_key(pKey); + } + + /*! + * \brief 从哈希表中分离出一个指定的哈希表项 + * + * \param pKey --[in] 欲被从哈希表中分离出来的数据项的键值 + * + * \retval 分离出来的数据项 -- 成功 + * \retval NULL -- 失败, 或者, 哈希表中根本就没有欲分离的数据项 + * + * \note + * 在函数执行成功的情况下, 该数据项从哈希表中移出.\n + * 在返回NULL的情况下, 函数实现保证原哈希表不发生任何变化\n + * 在函数实现中使用了使用者提供的函数\n + * pfnIndexOf -- 使用者提供的从键值到哈希值的转换函数\n + * pfnCompare -- 比较两个数据项的关键字的大小\n + */ + T * detachItem_with_key(void * pKey) + { + if(NULL == m_pTable || NULL == m_pfnIndexOf || NULL == m_pfnCompare) + return NULL; + + u32 index = (*m_pfnIndexOf)(pKey, m_uiSize); + if(index >= m_uiSize) + return NULL; + + PTABLEENTRY_t pEntry = &m_pTable[index]; + if(NULL != pEntry->pT && 0 == (*m_pfnCompare)(pKey, pEntry->pvTKey)) + { + T * ptempT = pEntry->pT; + pEntry->pT = NULL; + pEntry->pvTKey = NULL; + return ptempT; + } + + if(0 == pEntry->cntItems || NULL == pEntry->pItems) + return NULL; + + u32 count = pEntry->cntItems; + PITEM_t pSynonyms = pEntry->pItems; + for(u32 i = 0; i < count; i++) + { + if(NULL == pSynonyms[i].pT) + continue; + + if(0 == (*m_pfnCompare)(pKey, pSynonyms[i].pvTKey)) + { + T * ptempT = NULL; + ptempT = pSynonyms[i].pT; + memmove((void *)(pSynonyms + i), (void *)(pSynonyms + i + 1), sizeof(*pSynonyms) * (count - i - 1)); + memset((void *)(pSynonyms + count - 1), 0, sizeof(*pSynonyms)); + pEntry->cntItems -= 1; + return ptempT; + } + } + + return NULL; + } + + + /*! + * \brief 释放哈希表所管理的所有数据项 + * + * \note + * 在函数实现中使用了使用者提供的函数\n + * pfnFreeItem -- 使用者提供的用户释放由pfnAlloc所分配的内存的函数 + */ + bool deleteItems() + { + if(NULL == m_pTable) + return true; + + if(m_pfnFreeItem== NULL) + return false; + + PTABLEENTRY_t pEntry = NULL; + PITEM_t pSynonyms = NULL; + for(u32 i = 0; i < m_uiSize; i++) + { + pEntry = &m_pTable[i]; + if(pEntry->pT) + (*m_pfnFreeItem)(pEntry->pT); + pEntry->pT = NULL; + pEntry->pvTKey = NULL; + + if(pEntry->cntItems > 0 && NULL != pEntry->pItems) + { + pSynonyms = pEntry->pItems; + for(u32 j = 0; j < pEntry->cntItems; j++) + { + if(pSynonyms[j].pT) + (*m_pfnFreeItem)(pSynonyms[j].pT); + + pSynonyms[j].pT = NULL; + pSynonyms[j].pvTKey = NULL; + } + } + + pEntry->cntItems = 0; + } + + return true; + } + + /*! + * \brief 分离哈希表所管理的所有数据项 + */ + void detachItems() + { + if(NULL == m_pTable) + return; + + PTABLEENTRY_t pEntry = NULL; + for(u32 i = 0; i < m_uiSize; i++) + { + pEntry = &m_pTable[i]; + pEntry->pT = NULL; + pEntry->pvTKey = NULL; + + if(pEntry->cntItems > 0 && NULL != pEntry->pItems) + memset((void *)pEntry->pItems, 0, sizeof(pEntry->pItems[0]) * pEntry->cntAllocItems); + + pEntry->cntItems = 0; + } + } +}; + +// 是pc机系统还是嵌入式系统 +#ifdef PC_MACHINE + +#ifdef OS_WINDOWS + + #pragma pack (pop) + +#else// OS_UNIX + +#pragma pack (0) + +#endif //OS_UNIX +#endif + + + +#endif //__CHAIN_HASH_H__ASDFJQWPEUTOUDSAFHJDSAFADSAFWQERUGSKGEWRTPYZNXM diff --git a/inifile.h b/inifile.h new file mode 100644 index 0000000..e15ec90 --- /dev/null +++ b/inifile.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------- + 平台无关的INI文件读写函数 V1.65 + + 张磊 2002.10.3 +----------------------------------------------------------*/ + +#ifndef INI_FILE_H +#define INI_FILE_H + +#include "platform_def.h" + +#define MAX_LINE_BUF_LENGTH 2048 //最大行缓冲区长度 + +#define FILE_OPEN_ERROR -1 //文件打开错误 +#define SECTION_NOT_FOUND -2 //段没有找到 +#define KEY_NOT_FOUND -3 //键没有找到 + +//工具函数 +void StrTrimLeft(char* szBuf); +void StrTrimRight(char* szBuf); +void StrTrimAll(char* szBuf); +long GetFileSize(char* lpszFileName); +int ReadLineFromFile(FILE* IniFile, char* lpszLineBuf, int iLen); //从指定文件中读取一行内容 +bool IfBeforeHasRet(FILE* pFile); //辅助函数,判断当前文件位置前面是否是换行符号 + +//读配置文件中指定段下指定键的值(字符串) +int QGetPrivateProfileString( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + char* lpszDefault, //缺省字符串 + char* lpszReturnedString, //结果字符串 + u_32 nSize, //结果字符串长度 + char* lpszFileName, //ini文件名 + char* lpszRemarkInLineStr = (char*)";", //行内注释符 + char chContinueLineChar = '\\' //续行符号 +); + +//读配置文件中指定段下指定键的值(整数) +int QGetPrivateProfileInt( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + int nDefault, //缺省值 + char* lpszFileName, //ini文件名 + char* lpszRemarkInLineStr = (char*)";", //行内注释符 + char chContinueLineChar = '\\' //续行符号 +); + +//向配置文件写入指定段下指定键的值(字符串) +int QWritePrivateProfileString( + char* lpszSectionName, //段名 + char* lpszKeyName, //键名 + char* lpszString, //要写入的字符串 + char* lpszFileName //INI文件名 +); + +#endif diff --git a/list_entry.cpp b/list_entry.cpp new file mode 100644 index 0000000..e59435c --- /dev/null +++ b/list_entry.cpp @@ -0,0 +1,103 @@ +/************************************************************************ + * + * Copyright (C) 2003-2004 + * Shenzhen SCADA Control Technology Co., Ltd. + * All rights reserved. + * + * 实现双链表 + * + * 创建日期: 2004/01/10 + * + * $Id: list_entry.cpp,v 1.1.1.1 2006/07/05 07:31:43 jehu Exp $ + * + ***********************************************************************/ + +#include + +#include "list_entry.h" + +/* + * 双向链表的操纵例程函数的实现 + */ +void Initialize_list_head ( list_entry_t * plist_head ) +{ + plist_head->flink = plist_head->blink = plist_head; +} + +/* + * 判断双向链表是否为空 + * + * \retval 0 空链表 + * \retval 非0 空链表 + */ +int is_list_empty ( list_entry_t * plist_head ) +{ + return (int)(plist_head->flink == plist_head); +} + +/* + * 从双向链表的头部移取一个链表元素--与链表脱离链接关系 + */ +list_entry_t * remove_head_list ( list_entry_t * plist_head ) +{ + list_entry_t * pHeadEntry = plist_head->flink; + remove_entry_list ( plist_head->flink ); + return pHeadEntry; +} + + +/* + * 从双向链表的尾部移取一个链表元素--与链表脱离链接关系 + */ +list_entry_t * remove_tail_list ( list_entry_t * plist_head ) +{ + list_entry_t * pHeadEntry = plist_head->blink; + remove_entry_list ( plist_head->blink ); + return pHeadEntry; +} + +/* + * 从双向链表中移取制定的链表元素--与链表脱离链接关系 + */ +void remove_entry_list ( list_entry_t * pEntry ) +{ + list_entry_t * _EX_Blink = (list_entry_t *)0; + list_entry_t * _EX_Flink = (list_entry_t *)0; + + _EX_Flink = pEntry->flink; + _EX_Blink = pEntry->blink; + _EX_Blink->flink = _EX_Flink; + _EX_Flink->blink = _EX_Blink; +} + +/* + * 将一个链表元素从尾部插入到双向链表中 + */ +void insert_tail_list ( list_entry_t * plist_head, list_entry_t * pEntry ) +{ + list_entry_t * _EX_Blink = (list_entry_t *)0; + list_entry_t * _EX_ListHead = (list_entry_t *)0; + + _EX_ListHead = plist_head; + _EX_Blink = _EX_ListHead->blink; + pEntry->flink = _EX_ListHead; + pEntry->blink = _EX_Blink; + _EX_Blink->flink = pEntry; + _EX_ListHead->blink = pEntry; + } + +/* + * 将一个链表元素从尾部插入到双向链表中 + */ +void insert_head_list ( list_entry_t * plist_head, list_entry_t * pEntry) +{ + list_entry_t * _EX_Flink = (list_entry_t *)0; + list_entry_t * _EX_ListHead = (list_entry_t *)0; + + _EX_ListHead = plist_head; + _EX_Flink = _EX_ListHead->flink; + pEntry->flink = _EX_Flink; + pEntry->blink = _EX_ListHead; + _EX_Flink->blink = pEntry; + _EX_ListHead->flink = pEntry; +} diff --git a/list_entry.h b/list_entry.h new file mode 100644 index 0000000..6150445 --- /dev/null +++ b/list_entry.h @@ -0,0 +1,107 @@ +/************************************************************************ + * + * Copyright (C) 2003-2004 + * Shenzhen SCADA Control Technology Co., Ltd. + * All rights reserved. + * + * 双链表 + * + * 创建日期: 2004/01/10 + * + * 摘自Windoes $(DDKPATH)/inc/ntdef.h和$(DDKPATH)/inc/ddk/ntddk.h + * + * $Id: list_entry.h,v 1.1.1.1 2006/07/05 07:31:43 jehu Exp $ + * + ***********************************************************************/ + +#ifndef __LIST_ENTRY_H__SKLJFALKJZLJVADFHOPSHVPZIOXJHCVOIPADFDFNXVCQWEDAH +#define __LIST_ENTRY_H__SKLJFALKJZLJVADFHOPSHVPZIOXJHCVOIPADFDFNXVCQWEDAH + +/*! + * 双向链表结构定义, 可以用链表的头或者链表成员. + */ +typedef struct tag_list_entry_t { + + struct tag_list_entry_t * flink; /*!< 指向链表元素的前驱元素 */ + + struct tag_list_entry_t * blink; /*!< 指向链表元素的后继元素 */ + +} list_entry_t; + +typedef list_entry_t * plist_entry_t; +typedef list_entry_t ** pplist_entry_t; + + +/* + * 下面是双向链表的操纵例程函数 + * + * +---------------------------+-----------------------------------------------------+ + * | Initialize_list_head | 初始化链表头中的list_entry_t结构 | + * +---------------------------+-----------------------------------------------------+ + * | is_list_empty | 判断链表是否为空 | + * +---------------------------+-----------------------------------------------------+ + * | remove_head_list | 从双向链表的头部移取一个链表元素--与链表脱离链接关系| + * +---------------------------+-----------------------------------------------------+ + * | remove_tail_list | 从双向链表的尾部移取一个链表元素--与链表脱离链接关系| + * +---------------------------+-----------------------------------------------------+ + * | remove_entry_list | 从双向链表中移取指定的链表元素--与链表脱离链接关系 | + * +---------------------------+-----------------------------------------------------+ + * | insert_tail_list | 在起始处插入一个元素 | + * +---------------------------+-----------------------------------------------------+ + * | insert_head_list | 在结尾处插入一个元素 | + * +---------------------------+-----------------------------------------------------+ + * | CONTAINING_RECORD | 由链表元素指针反演出链表元素所包含的元素指针 | + * +---------------------------+-----------------------------------------------------+ + * + */ + +/* + * 由链表元素指针反演出链表元素所包含的元素指针 + */ +#ifdef CONTAINING_RECORD +#undef CONTAINING_RECORD +#endif +#define CONTAINING_RECORD(_addr, _type, _field) ((_type *)((char *)(_addr) - (char *)(&((_type *)0)->_field))) + +/* + * 初始化双向链表 + * + * \param plist_head 指向链表的头 + */ +void Initialize_list_head ( list_entry_t * plist_head ); + +/* + * 判断双向链表是否为空 + * + * \retval 0 空链表 + * \retval 非0 空链表 + */ +int is_list_empty ( list_entry_t * plist_head ); + +/* + * 从双向链表的头部移取一个链表元素--与链表脱离链接关系 + */ +list_entry_t * remove_head_list ( list_entry_t * plist_head ); + + +/* + * 从双向链表的尾部移取一个链表元素--与链表脱离链接关系 + */ +list_entry_t * remove_tail_list ( list_entry_t * plist_head ); + +/* + * 从双向链表中移取制定的链表元素--与链表脱离链接关系 + */ +void remove_entry_list ( list_entry_t * pEntry); + +/* + * 将一个链表元素从尾部插入到双向链表中 + */ +void insert_tail_list ( list_entry_t * plist_head, list_entry_t * pEntry ); + +/* + * 将一个链表元素从头部插入到双向链表中 + */ +void insert_head_list ( list_entry_t * plist_head, list_entry_t * pEntry); + +#endif /* __LIST_ENTRY_H__SKLJFALKJZLJVADFHOPSHVPZIOXJHCVOIPADFDFNXVCQWEDAH */ diff --git a/netport.cpp b/netport.cpp new file mode 100644 index 0000000..b6c8ff9 --- /dev/null +++ b/netport.cpp @@ -0,0 +1,871 @@ + /***************************************************************************** + * FileName : netport.c * + * Programmer : Li Liangchu * + * Writen at : 2004.07.21 * + * Version : * + * Description: base on net comm sports driver * + * Last modify: 2004.07.21 * + *****************************************************************************/ + +//#include "serialport.h" +#include "netport.h" +#include "commport.h" + +int netWSAStartupErr = FALSE; + +extern SIO_PARAM_DEF SioParam[]; + +extern u_short MaxSerialPortNum; +extern u_short MaxNetPortNum; +extern u_short MaxPortNum; + +//创建 UDP 通讯 socket +BYTE CreateUdpSock(int *CommSock, DWORD NetPort, DWORD NetCommIpAddr) +{ + int tmp, retval; + struct sockaddr_in addr; + u_long largp = 1L; //非阻塞模式 + char tmp_buf[256]; + + if(*CommSock > -1) + return SOCKET_BEING; + + if((NetPort == 0) && (NetCommIpAddr == 0)) + return FAIL_GREATE; + + *CommSock = socket(AF_INET, SOCK_DGRAM, 0); + if(*CommSock < 0) + { + *CommSock = -1; + return FAIL_GREATE; + } + + // 将socket设置为非阻塞模式 + //tmp = fcntl(*CommSock, F_GETFL, 0); + //fcntl(*CommSock, F_SETFL, tmp|O_NONBLOCK); + + retval = ioctlsocket(*CommSock, FIONBIO, (u_long FAR *)&largp); + if (SOCKET_ERROR == retval) + { + retval = WSAGetLastError(); + sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *CommSock); + DebugPrint(tmp_buf); + closesocket(*CommSock); + *CommSock = -1; + return FAIL_GREATE; + } + + //设置socket输入输出缓冲 + tmp = MAX_NET_BUF_SIZE; + setsockopt(*CommSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp)); + tmp = MAX_NET_BUF_SIZE; + setsockopt(*CommSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)); + + tmp = 1; + setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp)); + setsockopt(*CommSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp)); + + // 增加udp广播通讯(广播地址) + if((NetCommIpAddr & 0x000000FF) == 0x000000FF) + { + setsockopt(*CommSock, SOL_SOCKET, SO_BROADCAST, (char*)&tmp, sizeof(tmp)); + } + + //让配置socket 能收不同网段的配置命令 + //bzero(&addr, sizeof(addr)); + memset((char*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(NetPort); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + closesocket(*CommSock); + *CommSock = -1; + return FAIL_GREATE; + } + return SUCCEED_GREATE; +} + +//创建 TCP Server socket +BYTE CreateTcpServerSock(int *LiSock, DWORD NetPort) +{ + int i, tmp, ret, retval, len; + int keep_alive = 1; // 设定KeepAlive + int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间(s) + int keep_interval = 3; // 两次KeepAlive探测间的时间间隔(s) + int keep_count = 3; // 判定断开前的KeepAlive探测次数 + struct sockaddr_in addr; + u_long largp = 1L; //非阻塞模式 + char tmp_buf[256]; + + if(-1 < *LiSock) + return SOCKET_BEING; + + if(NetPort == 0) + return FAIL_GREATE; + + *LiSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + //len = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + //*LiSock = len; + + if(*LiSock < 0) + { + retval = WSAGetLastError(); + sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *LiSock); + *LiSock = -1; + return FAIL_GREATE; + } + + // 将socket设置为非阻塞模式 + //tmp = fcntl(*LiSock, F_GETFL, 0); + //fcntl(*LiSock, F_SETFL, tmp|O_NONBLOCK); + retval = ioctlsocket(*LiSock, FIONBIO, (u_long FAR *)&largp); + if (SOCKET_ERROR == retval) + { + retval = WSAGetLastError(); + sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, *LiSock); + DebugPrint(tmp_buf); + closesocket(*LiSock); + *LiSock = -1; + return FAIL_GREATE; + } + ///设置socket的输入输出缓冲区大小 + tmp = MAX_NET_BUF_SIZE; + setsockopt(*LiSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp)); + tmp = MAX_NET_BUF_SIZE; + setsockopt(*LiSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)); + + len = 4; + tmp_buf[0] = 1; + + tmp = setsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, len); + tmp = getsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &len); + tmp = 1; + // setsockopt(*LiSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp)); + setsockopt(*LiSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp)); + //set_keepalive(*LiSock, keep_alive, keep_idle, keep_interval, keep_count); + + //让TCP接收所有连线 + memset((char*)&addr,0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(NetPort); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + //printf("TIP_(%04d): Port = %d, NetCommIpAddr(%08x), addr.sin_addr.s_addr(%08x)\n", getpid(), commid+1, *NetCommIpAddr, addr.sin_addr.s_addr); + if(bind(*LiSock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + //printf("errno = %d\n", errno); + //close(*LiSock); + closesocket(*LiSock); + *LiSock = -1; + return FAIL_GREATE; + } + //printf("succeed!\n"); + + ret = listen(*LiSock, 4); + if(ret < 0) + { + //close(*LiSock); + closesocket(*LiSock); + *LiSock = -1; + return FAIL_GREATE; + } + return SUCCEED_GREATE; +} + +//创建 TCP Client socket +BYTE CreateTcpClientSock(int *CommSock, DWORD NetPort, DWORD NetCommIpAddr) +{ + int tmp,len; + int keep_alive = 1; // 设定KeepAlive + int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间 + int keep_interval = 3; // 两次KeepAlive探测间的时间间隔 + int keep_count = 3; // 判定断开前的KeepAlive探测次数 + struct sockaddr_in addr; + u_long largp = 1L; //非阻塞模式 + char tmp_buf[256]; + + if(-1 < *CommSock) + return SOCKET_BEING; + + if((NetPort == 0) && (NetCommIpAddr == 0)) + return FAIL_GREATE; + + *CommSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(*CommSock < 0) + { + *CommSock = -1; + return FAIL_GREATE; + } + + // 将socket设置为非阻塞模式 + //tmp = fcntl(*CommSock, F_GETFL, 0); + //fcntl(*CommSock, F_SETFL, tmp|O_NONBLOCK); + tmp = ioctlsocket(*CommSock, FIONBIO, (u_long FAR *)&largp); + if (SOCKET_ERROR == tmp) + { + tmp = WSAGetLastError(); + sprintf(tmp_buf, "ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", tmp, *CommSock); + DebugPrint(tmp_buf); + closesocket(*CommSock); + *CommSock = -1; + return FAIL_GREATE; + } + + ///设置socket的输入输出缓冲区大小 + tmp = MAX_NET_BUF_SIZE; + setsockopt(*CommSock, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp)); + tmp = MAX_NET_BUF_SIZE; + setsockopt(*CommSock, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)); + + len = 4; + tmp_buf[0] = 1; + + tmp = setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, len); + tmp = getsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &len); + + tmp = 1; + // setsockopt(*CommSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&tmp, sizeof(tmp)); + setsockopt(*CommSock, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, sizeof(tmp)); +// set_keepalive(*CommSock, keep_alive, keep_idle, keep_interval, keep_count); + + //bzero(&addr, sizeof(addr)); + memset((char*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(NetPort); + addr.sin_addr.s_addr = htonl(NetCommIpAddr); + + //printf("TIP_(%04d): Port = %d, connect(%08x)\n", getpid(), commid+1, *NetCommIpAddr); + if(connect(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) != 0) + { + //printf(" connect error errno= %d, EINPROGRESS=%d\n", errno,EINPROGRESS); + if(EINPROGRESS != errno) + { + closesocket(*CommSock); + //printf(" connect error errno= %d, EINPROGRESS=%d\n", errno,EINPROGRESS); + *CommSock = -1; + return FAIL_GREATE; + } + // 非阻塞的情况下不能这样使用 +// else +// { +// if(connect(*CommSock, (struct sockaddr *)&addr, sizeof(addr)) < 0) +// { +// //printf(" connect error errno= %d, EISCONN=%d\n", errno,EISCONN); +// if(EISCONN != errno) +// { +// printf(" connect error errno= %d, EISCONN=%d\n", errno,EISCONN); +// close(*CommSock); +// *CommSock = -1; +// return FAIL_GREATE; +// } +// } +// //printf(" connect succeed errno= %d EISCONN=%d\n", errno, EISCONN); +// } + } + return SUCCEED_GREATE; +} + +//int keep_alive = 1;//设定KeepAlive +//int keep_idle = 1;//开始首次KeepAlive探测前的TCP空闭时间 +//int keep_interval = 1;//两次KeepAlive探测间的时间间隔 +//int keep_count = 3;//判定断开前的KeepAlive探测次数 +/*void set_keepalive(int fd, int keep_alive, int keep_idle, int keep_interval, int keep_count) +{ + if(keep_alive) + { + if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keep_alive, sizeof(keep_alive)) == -1) + { + fprintf(stderr, "setsockopt SOL_SOCKET::SO_KEEPALIVE failed, %s\n",strerror(errno)); + } + if(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void *)&keep_idle,sizeof(keep_idle)) == -1) + { + fprintf(stderr, "setsockopt SOL_TCP::TCP_KEEPIDLE failed, %s\n", strerror(errno)); + } + if(setsockopt(fd,SOL_TCP,TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)) == -1) + { + fprintf(stderr, "setsockopt SOL_tcp::TCP_KEEPINTVL failed, %s\n", strerror(errno)); + } + if(setsockopt(fd,SOL_TCP,TCP_KEEPCNT, (void *)&keep_count,sizeof(keep_count)) == -1) + { + fprintf(stderr, "setsockopt SOL_TCP::TCP_KEEPCNT failed, %s\n", strerror(errno)); + } + } +}*/ + +void OpenNetPort(int commid) +{ + BYTE succeedflag; + int i, commsock; + DWORD netport, netcommipaddr; + + commsock = SioParam[commid].CommSock; + netport = SioParam[commid].NetPort; + netcommipaddr = SioParam[commid].NetCommIpAddr; + switch(SioParam[commid].NetType) + { + case UDP_COMM: // UDP 通讯 + if(OPEN_PORT == SioParam[commid].OpenFlag) + return; + succeedflag = CreateUdpSock(&commsock, netport, netcommipaddr); + if(SUCCEED_GREATE == succeedflag) + { + SioParam[commid].OpenFlag = OPEN_PORT; + SioParam[commid].CommSock = commsock; + } + break; + + case TCP_S_COMM: // TCP 服务器通讯 + commsock = SioParam[commid].LiSock; + succeedflag = CreateTcpServerSock(&commsock, netport); + if(SUCCEED_GREATE == succeedflag) + { + for(i=MaxSerialPortNum; i -1) + closesocket(SioParam[commid].CommSock); + + SioParam[commid].CommSock = -1; + if(CLOSE_PORT != SioParam[commid].OpenFlag) + { + SioParam[commid].OpenFlag = CLOSE_PORT; + } + break; + + case TCP_S_COMM: // TCP 服务器通讯 + if(SioParam[commid].CommSock > -1) + closesocket(SioParam[commid].CommSock); + //printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock); + SioParam[commid].CommSock = -1; + if(CLOSE_PORT != SioParam[commid].OpenFlag) + { + SioParam[commid].OpenFlag = CLOSE_PORT; + } + break; + + case TCP_C_COMM: // TCP 客户端通讯 + if(SioParam[commid].CommSock > -1) + closesocket(SioParam[commid].CommSock); + + SioParam[commid].CommSock = -1; + //printf("关闭端口%d TCP客户端Socket=%d\n", commid+1, SioParam[commid].CommSock); + if(CLOSE_PORT != SioParam[commid].OpenFlag) + { + SioParam[commid].OpenFlag = CLOSE_PORT; + } + break; + } + // 删除所有的发送缓冲区wen 2005.07.27 + PortWriteDataFree(commid); +} + +// TCP服务器端的侦听socket关闭与打开与端口是否打开的标识(SioParam[commid].OpenFlag)无关 +void CloseNetListenPort(int commid) +{ + int i; + + switch(SioParam[commid].NetType) + { + case TCP_S_COMM: // TCP 服务器通讯 + if(SioParam[commid].LiSock > -1) + //close(SioParam[commid].LiSock); + closesocket(SioParam[commid].LiSock); + SioParam[commid].LiSock = -1; + // 使用相同TCP服务端口的端口的listen套接字全部标识为-1(关闭) + for(i=MaxSerialPortNum; i= MAX_MSG_BUF_SIZE); +} + +//从头结点往后删 +void DelNode(int commid) +{ + struct WR_DATA *next; + + if (!SioParam[commid].WriteData) + { + return; + } + + //SioParam[commid].iWriteDataNo--; + next = SioParam[commid].WriteData->Next; + HEAP_FREE(SioParam[commid].WriteData); + SioParam[commid].WriteData = next; +} + +void UdpSend(int commid) +{ + int len, plen, slen; + struct sockaddr_in addr; + + if(!IsBaoHuPtr(commid)) + return; + if(NULL == SioParam[commid].WriteData) + return; + + //bzero(&addr, sizeof(addr)); + memset((char*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SioParam[commid].NetPort); + addr.sin_addr.s_addr = SioParam[commid].NetCommIpAddr; + + // 错误判断和断点续传 + plen = SioParam[commid].WriteData->PLen; + slen = SioParam[commid].WriteData->MsgLen - plen; + if(slen <= 0) + { + DelNode(commid); + return; + } + len = sendto(SioParam[commid].CommSock,(const char*)&SioParam[commid].WriteData->MsgData[plen], slen, + 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); + if(len > 0) + { + if(len < slen) + { + if(EINPROGRESS != errno) + { + CloseNetPort(commid); + } + else + { + SioParam[commid].WriteData->PLen += len; + } + } + else + { + DelNode(commid); + } + //ShmAddSendCount(commid, len); + } + else if(EINPROGRESS != errno) + { + CloseNetPort(commid); + } +} + +BOOL TcpRecv(int commid, int fds, u_long ipaddr) +{ + BOOL bRetVal; + int len, nread; + char revbuf[MAX_MSG_BUF_SIZE]; + +// if(OPEN_PORT != SioParam[commid].OpenFlag) +// return FALSE; + bRetVal = TRUE; + //删除已断开的子socket + //ioctl(fds, FIONREAD, &nread); + /*if(nread == 0) + { + //if(commid == 8) + // printf("TIP_(%04d): Port=%d Peer Socket is closed already.\n", getpid(), commid+1); + CloseNetPort(commid); + bRetVal = FALSE; + } + else*/ + { + do + { + len = recv(fds, revbuf, MAX_MSG_BUF_SIZE, 0); + // 错误判断 len = 0 有可能是对方已经关闭socket + if(len <= 0) + { + printf("port%d read error len=%d\n", commid+1, len); + if(EINPROGRESS != errno) + { + //printf("port%d read error\n", commid+1); + CloseNetPort(commid); + bRetVal = FALSE; + break; + } + } + + if(IsBaoHuPtr(commid)) + { + PutDataToBuf(&SioParam[commid].RecvBuf, (u_char*)revbuf, len); + } + }while(len >= MAX_MSG_BUF_SIZE); + } + + return bRetVal; +} + +void TcpSend(int commid) +{ + int len, plen, slen; + + if(OPEN_PORT != SioParam[commid].OpenFlag) + { + SioParam[commid].OpenFlag = OPEN_PORT; + //printf("设置Tcp端口%d 端口状态为OPEN_PORT!\n", commid+1); + } + else + { + if(!IsBaoHuPtr(commid)) + { + return; + } + + if(NULL == SioParam[commid].WriteData) + { + return; + } + + // 增加错误判断和断点续传 + plen = SioParam[commid].WriteData->PLen; + slen = SioParam[commid].WriteData->MsgLen - plen; + if(slen <= 0) + { + DelNode(commid); + return; + } + + len = send(SioParam[commid].CommSock,(const char*)&SioParam[commid].WriteData->MsgData[plen], slen, 0); + if(len > 0) + { + if(len < slen) + { + if(EINPROGRESS != errno) + { + //printf("端口%d 发送错误,关闭Tcp通讯\n", commid+1); + CloseNetPort(commid); + } + else + { + SioParam[commid].WriteData->PLen += len; + } + } + else + { + DelNode(commid); + } + + //ShmAddSendCount(commid, len); + } + else if(EINPROGRESS != errno) + { + //printf("端口%d 不能发送数据,关闭Tcp通讯\n", commid+1); + CloseNetPort(commid); + } + } +} + +void TcpAccept(int commid, int lisfds) +{ + int sock, result, i, addr_len, tmp; + struct sockaddr_in addr; + int keep_alive = 1; // 设定KeepAlive + int keep_idle = 5; // 开始首次KeepAlive探测前的TCP空闭时间 + int keep_interval = 3; // 两次KeepAlive探测间的时间间隔 + int keep_count = 3; // 判定断开前的KeepAlive探测次数 + fd_set set; + u_long largp = 1L; //非阻塞模式 + char tmp_buf[256]; + + addr_len = sizeof(struct sockaddr_in); + //printf("端口%d 检查是否有客户端过来连接\n", commid+1); + sock = accept(lisfds, (struct sockaddr *)&addr, &addr_len); + if(sock < 0) + { + return; + } + printf("TIP_(%04d): Port = %d, addr.sin_addr.s_addr(%08x), sock = %d\n", _getpid(), commid+1, addr.sin_addr.s_addr, sock); + // 多客户端向服务端连接时判断客户端来自的端口号 yizhonghu 20070704 + for(i=MaxSerialPortNum; i SioParam[commid].CommSock) && (-1 < SioParam[commid].LiSock)) + { + fds = SioParam[commid].LiSock; + setflag = 3; + break; + } + if (-1 < SioParam[commid].CommSock) + { + fds = SioParam[commid].CommSock; + setflag = 3; + break; + } + setflag = 2; + break; + case TCP_C_COMM: // 检查TCP客户端套接字是否建立 + if (-1 < SioParam[commid].CommSock) + { + fds = SioParam[commid].CommSock; + setflag = 3; + break; + } + setflag = 2; + break; + } + + if (0 == setflag) + return inum; + if ((1 == setflag) || (3 == setflag)) + { + inum++; + FD_SET(fds, fdset_ro); + FD_SET(fds, fdset_wr); + FD_SET(fds, fdset_ex); + *fd_max = max(*fd_max, fds); + } + if (1 == setflag) + return inum; + // if(2 == setflag) 无需处理 + return inum; +} + + +void PollAllPort(void) +{ + struct timeval timeout; + int i, inum, nfds, commid, fds, lisfds, ret, ierr, ierrlen; + u_long ipaddr; + fd_set fdset_ro, fdset_wr, fdset_ex; + /*static int ok=0;*/ + + inum = 0; + nfds = 0; + FD_ZERO(&fdset_ro); + FD_ZERO(&fdset_wr); + FD_ZERO(&fdset_ex); + for(i=0; i +#include +#endif*/ + +#include +#include +#include +#include +#include + +#include "time.h" +#include "list_entry.h" +#include "os_heap.h" + +//#if defined(WIN32) + #include + #include + #include +//#endif + +#ifdef _fclose +#undef _fclose +#endif +#define _fclose(_fp) do {if (_fp) {while (EOF == fclose((_fp)) && EINTR == errno);}} while(0) + +/*! + * 堆内存块的类型 + */ +typedef enum { + eMalloc = 0, /* 使用malloc分配的内存块 */ + eCalloc = 1 /* 使用calloc分配的内存块 */ +} heap_type_t; + +/*! + * 堆内存块附加头 + * + * \note + * 必须保证本结构的尺寸被16整除。 + */ +typedef struct tag_heap_head_t { + + /* 堆内存块附加头所在的链表的占位 */ + list_entry_t anchor; + + /*! 堆内存块分配发生的时间 */ + struct timeval tv; + + /*! 堆内存块类型 */ + heap_type_t type; + + /*! 堆内存块分配发生的源文件名,NULL表示匿名源文件。 */ + char * fl; + + /*! 堆内存块分配发生的源代码行 */ + int line; + + /*! 堆内存块的尺寸(字节) */ + size_t size; + +} heap_list_t; + + +/* 边界对齐量 */ +#define os_heap_alignment 16 +#define os_heap_pad ((sizeof(heap_list_t) % os_heap_alignment) ? (os_heap_alignment - (sizeof(heap_list_t) % os_heap_alignment)) : 0) + +/* 根据数据地址求os_heap块的起始地址 */ +#define os_heap_start_addr(_data) ((void *)(((unsigned char *)(_data)) - sizeof(heap_list_t) - os_heap_pad)) + +/* 根据os_heap块的起始地址求数据地址 */ +#define os_heap_data_addr(_start) ((void *)(((unsigned char *)(_start)) + sizeof(heap_list_t) + os_heap_pad)) + +/* 根据数据块的尺寸求os_heap块的尺寸 */ +#define os_heap_mb_size(_size) (sizeof(heap_list_t) + os_heap_pad + (_size)) + +/* + * 内存管理模块: + * + * 1. 初始化过程 + * 2. 具有一个私有线程,专门侦听外部的信号,并打印报告。 + * 3. 堆内存块链表头、尾指针。 + * 4. 互斥访问保护 + */ + +/* 堆内存块设施是否已经初始化 */ +static int g_heap_initialized = 0; + +/* 堆内存块双向链表头 */ +static list_entry_t g_heap_head; + +/* + * 进程中使用heap_malloc/heap_calloc分配的内存 + * 且现在还在使用的内存块的总数。 + */ +static size_t g_heap_item_counter = 0; + +/* + * 进程中使用heap_malloc/heap_calloc分配的内存 + * 且现在还在使用的总量(字节) + */ +static size_t g_heap_byte_counter = 0; + + +/* 初始化堆内存块设施 */ +static void heap_intialize(); + +/*! + * \brief 堆内存分配 + * + * \param size 希望分配的内存的尺寸 + * \param file 指向发生堆内存分配的源代码文件名称,以null字符结尾。 + * 如果等于NULL, 表示匿名源代码文件名(anony) + * \param line 发生堆内存分配的源代码行号 + * + * \retutrn + * 对内存分配成功的情况下,返回指向分配的内存的指针。如果内存 + * 分配失败,返回NULL。 + * + * \note + * 当分配的内存不在使用时,必须调用heap_free是否分配的内存。 + * + * 参见 ANSI C 函数 malloc。 + */ +void * heap_malloc ( + size_t size, + const char * file, + int line ) +{ + // #ifdef DISABLE_OS_HEAP + return malloc(size); + /*#else /* #ifdef DISABLE_OS_HEAP */ +/* + struct timeval tv; + char * fl = NULL; + void * mb = NULL; + heap_list_t * hl = NULL; + + if (0 == size) + return NULL; + + if (file) { + fl = (char *)malloc(strlen(file) + 4); + if (fl) strcpy (fl, file); + } + + gettimeofday(&tv, NULL); + + mb = malloc(os_heap_mb_size(size)); + if (NULL == mb) { + if (fl) free (fl); + return mb; + } else { + memset (mb, 0, os_heap_mb_size(size)); + } + + hl = (heap_list_t *)mb; + + hl->type = eMalloc; + hl->tv = tv; + hl->fl = fl; + hl->line = line; + hl->size = size; + + if (!g_heap_initialized) { + heap_intialize(); + g_heap_initialized = 1; + } + + insert_tail_list (&g_heap_head, &(hl->anchor)); + g_heap_item_counter++; + g_heap_byte_counter += hl->size; + + return os_heap_data_addr(hl); + #endif *//* #ifdef DISABLE_OS_HEAP */ +} + +/*! + * \brief 堆内存分配, 且内存块被初始化0. + * + * \param num 内存块个数 + * \param elm_size 每一个内存块的尺寸(字节) + * \param file 指向发生堆内存分配的源代码文件名称,以null字符结尾。 + * 如果等于NULL, 表示匿名源代码文件名(anony) + * \param line 发生堆内存分配的源代码行号 + * + * \retutrn + * 对内存分配成功的情况下,返回指向分配的内存的指针。如果内存 + * 分配失败,返回NULL。 + * + * \note + * 当分配的内存不在使用时,必须调用heap_free释放分配的内存。 + * + * 参见 ANSI C 函数 calloc。本函数与 calloc 不同之处在于不能 + * 象calloc那样保证返回的堆内存块的其实地址对齐在elm_size边界 + * 上。 + */ +void * heap_calloc ( + size_t num, + size_t elm_size, + const char * file, + int line ) +{ + //#ifdef DISABLE_OS_HEAP + return calloc(num, elm_size); + //#else /* #ifdef DISABLE_OS_HEAP */ + + /* struct timeval tv; + char * fl = NULL; + void * mb = NULL; + heap_list_t * hl = NULL; + + if (0 == num * elm_size) + return NULL; + + if (file) { + fl = (char *)malloc(strlen(file) + 4); + if (fl) strcpy (fl, file); + } + + gettimeofday(&tv, NULL); + + mb = malloc(os_heap_mb_size(elm_size * num)); + if (NULL == mb) { + if (fl) free (fl); + return mb; + } else { + memset (mb, 0, os_heap_mb_size(elm_size * num)); + } + + hl = (heap_list_t *)mb; + + hl->type = eCalloc; + hl->tv = tv; + hl->fl = fl; + hl->line = line; + hl->size = elm_size * num; + + if (!g_heap_initialized) { + heap_intialize(); + g_heap_initialized = 1; + } + + insert_tail_list (&g_heap_head, &(hl->anchor)); + g_heap_item_counter++; + g_heap_byte_counter += hl->size; + + return os_heap_data_addr(hl); + #endif *//* #ifdef DISABLE_OS_HEAP */ +} + +/*! + * \brief 释放堆内存 + * + * \param memblock 指向先前调用heap_alloc/heap_calloc分配的内存。 + * + * \return + * 无。 + */ +void heap_free (void * mb) +{ + #ifdef DISABLE_OS_HEAP + free (mb); + #else /* #ifdef DISABLE_OS_HEAP */ + size_t sz = 0; + heap_list_t * hl = NULL; + + if (NULL == mb) + return; + + if (!g_heap_initialized) { + heap_intialize(); + g_heap_initialized = 1; + return; + } + + hl = (heap_list_t *)os_heap_start_addr(mb); + + #if defined(WIN32) && (defined(DEBUG) || defined(_DEBUG)) + if (IsBadReadPtr((void *)hl, sizeof(heap_list_t))) { + return; + } + + if (IsBadReadPtr((void *)hl, os_heap_mb_size(hl->size))) { + return; + } + #endif + + remove_entry_list (&(hl->anchor)); + sz = hl->size; + if (hl->fl) + free ((void *)(hl->fl)); + free ((void *)hl); + + g_heap_item_counter--; + g_heap_byte_counter -= sz; + + #endif /* #ifdef DISABLE_OS_HEAP */ +} + +/*! + * \brief 报告堆内存分配 + * + * 调用本函数将堆内存分配情况以追加的方式输出到指定文件中。 + * + * \param fname 对内存分配报告将输出到该文件中。如果fname等于NULL, + * 则报告将输出到标准输出上。 + * + * \retval -1 函数调用失败。 + * \retval 0 函数调用成功。 + * + * \note + * 报告的格式如下 + * 时间: + * 内存使用总量: + * ...... + * 内存块列表i: + * 时间: tv + * 类型: malloc/calloc, + * 源码位置: fl(line) + * 尺寸: size + * ...... + */ +int heap_report(const char * fname) +{ + /* #ifndef DISABLE_OS_HEAP + int i = 0; + FILE * fp = NULL; + + heap_list_t * hl = NULL; + + list_entry_t * item = NULL; + list_entry_t * first = NULL; + list_entry_t * next = NULL; + + char szdt[32]; + + if (fname) { + fp = fopen (fname, "a+t"); + if (NULL == fp) + return -1; + } else + fp = stdout; + + if (!g_heap_initialized) { + heap_intialize(); + g_heap_initialized = 1; + if (fname) _fclose(fp); + return 0; + } + + fprintf (fp, "\n" + "heap allocation summary...\n" + "time: %s\n" + "heap_item_counter: %u\n" + "heap_byte_counter: %u(bytes)\n", + cur_tm_string (szdt), + g_heap_item_counter, + g_heap_byte_counter); + + first = &g_heap_head; + for ( next = first->flink; next != first; next = next->flink ) + { + item = next; + hl = CONTAINING_RECORD ( item, heap_list_t, anchor ); + + fprintf (fp, " heap block %d:" + " times: %s" + " type: %s" + " size: %08u (bytes)" + " source: %s [%d]\n", + i++, timeval_string(&(hl->tv), szdt), + (eMalloc == hl->type ? "malloc" : "calloc"), + hl->size, (hl->fl ? hl->fl : "nony"), hl->line); + } + + if (fname) _fclose(fp); + #endif*/ + + return 0; +} + +static void heap_intialize() +{ + Initialize_list_head (&g_heap_head); +} diff --git a/os_heap.h b/os_heap.h new file mode 100644 index 0000000..be875fe --- /dev/null +++ b/os_heap.h @@ -0,0 +1,110 @@ +/************************************************************************ + * + * Copyright (C) 2003-2004 + * Shenzhen SCADA Control Technology Co., Ltd. + * All rights reserved. + * + * 用于调试内存泄漏的对内存分配函数 + * + * 创建日期: 2005/04/12 + * + ***********************************************************************/ + +#ifndef __OS_HEAP_H_ASDFJLCXJVZXHCROEYUIODFGFMHFOIUHSDIHFZXKJCHGVLSDHFAJD +#define __OS_HEAP_H_ASDFJLCXJVZXHCROEYUIODFGFMHFOIUHSDIHFZXKJCHGVLSDHFAJD + +#include "basetype.h" + +/*! + * \brief 堆内存分配 + * + * \param size 希望分配的内存的尺寸 + * \param file 指向发生堆内存分配的源代码文件名称,以null字符结尾。 + * 如果等于NULL, 表示匿名源代码文件名(anony) + * \param line 发生堆内存分配的源代码行号 + * + * \retutrn + * 对内存分配成功的情况下,返回指向分配的内存的指针。如果内存 + * 分配失败,返回NULL。 + * + * \note + * 当分配的内存不在使用时,必须调用heap_free是否分配的内存。 + * + * 参见 ANSI C 函数 malloc。 + */ +DSLIB_API void * heap_malloc (size_t size, const char * file, int line); + + +/*! + * \brief 堆内存分配, 且内存块被初始化0. + * + * \param num 内存块个数 + * \param elm_size 每一个内存块的尺寸(字节) + * \param file 指向发生堆内存分配的源代码文件名称,以null字符结尾。 + * 如果等于NULL, 表示匿名源代码文件名(anony) + * \param line 发生堆内存分配的源代码行号 + * + * \retutrn + * 对内存分配成功的情况下,返回指向分配的内存的指针。如果内存 + * 分配失败,返回NULL。 + * + * \note + * 当分配的内存不在使用时,必须调用heap_free释放分配的内存。 + * + * 参见 ANSI C 函数 calloc。本函数与 calloc 不同之处在于不能 + * 象calloc那样保证返回的堆内存块的其实地址对齐在elm_size边界 + * 上。 + */ +DSLIB_API void * heap_calloc (size_t num, size_t elm_size, + const char * file, int line); + +/*! + * \brief 释放堆内存 + * + * \param mb 指向先前调用heap_alloc/heap_calloc分配的内存。 + * + * \return + * 无。 + */ +DSLIB_API void heap_free (void * mb); + +/*! + * \brief 报告堆内存分配 + * + * 调用本函数将堆内存分配情况以追加的方式输出到指定文件中。 + * + * \param fname 对内存分配报告将输出到该文件中。如果fname等于NULL, + * 则报告将输出到标准输出上。 + * + * \retval -1 函数调用失败。 + * \retval 0 函数调用成功。 + */ +DSLIB_API int heap_report (const char * fname); + +/* + * 堆内存分配和释放宏定义, 为了方便使用者而提供这些宏定义。 + * + * 1. HEAP_MALLOC(_size) + * 2. HEAP_CALLOC(_num, _elm_size) + * 3. HEAP_FREE(_mb) + */ +#define HEAP_MALLOC(_size) heap_malloc((_size), __FILE__, __LINE__) + +#define HEAP_CALLOC(_num, _elm_size) heap_calloc((_num), (_elm_size), __FILE__, __LINE__) + +#define HEAP_FREE(_mb) do{if(_mb) {heap_free((_mb)); (_mb) = NULL;}} while(0) + +#ifdef DISABLE_OS_HEAP + #undef HEAP_MALLOC + #undef HEAP_CALLOC + #undef HEAP_FREE + + #define HEAP_MALLOC(_size) malloc(_size) + + #define HEAP_CALLOC(_num, _elm_size) calloc(_num, _elm_size) + + #define HEAP_FREE(_mb) do {if (_mb) {free(_mb); (_mb) = NULL;}} while(0) + +#endif + +#endif /* __OS_HEAP_H_ASDFJLCXJVZXHCROEYUIODFGFMHFOIUHSDIHFZXKJCHGVLSDHFAJD */ diff --git a/platform_def.h b/platform_def.h new file mode 100644 index 0000000..529586b --- /dev/null +++ b/platform_def.h @@ -0,0 +1,162 @@ +/*----------------------------------------------------------------------------- + platform_def.h 操作系统相关定义 zl 2002.11.5 + + 本文件定义所有和操作系统平台相关的常量、类型、宏及头文件引用 +-----------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------------- + +条件编译常量定义约定: + +(1) Windows操作系统: OS_WINDOWS + +(2) Unix(统称)操作系统: OS_UNIX +(3) Linux操作系统: _OS_UNIX_LINUX_ +(4) True64操作系统: _OS_UNIX_TRUR64_ +(5) Solaris操作系统: _OS_UNIX_SOLARIS_ + +(6) 64位操作系统: _OS_64BIT_ + +(7) Windows字节顺序: _OS_WINDOWS_BYTEORDER_ +(8) Solaris字节顺序: _OS_SOLARIS_BYTEORDER_ + +[说明]: + +a. 64位操作系统主要有:DEC True64, solaris(有时可能是32位系统,可以通过测试sizeof + (long)是否=8来判断) + +b. windows, linux, true64 等操作系统的字节顺序和solaris相反,因此分别以Windows + 和solaris为代表定义不同的字节顺序 + +c. Unix操作系统种类繁多,每个变种有一定的差别,因此为常见的unix系统每种定义一个 + 条件编译常量 + +-----------------------------------------------------------------------------*/ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +/*------------------------------------ 头文件引用 --------------------------------*/ + +#ifdef OS_WINDOWS //windows + #include + #include + #include + #include +#endif + +#ifdef OS_UNIX //unix + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include //inet地址族的所有结构和常量定义都在这里 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +// #include + #include //定义bsd socket的gethostbyname()函数 +#endif + +/*------------------------------------ 名字定义 --------------------------------*/ + +//全局名字替换名字,为减少移植时大量修改结构及函数名的工作量而设置 + +#ifdef OS_UNIX + #define SYSTEMTIME QSYSTEMTIME + #define GetLocalTime QGetLocalTime + #define SetLocalTime QSetLocalTime + + #define GetPrivateProfileString QGetPrivateProfileString + #define GetPrivateProfileInt QGetPrivateProfileInt + #define WritePrivateProfileString QWritePrivateProfileString + + #define closesocket close //winsock中关闭socket用closesocket(),而bsd socket中用close() +#endif + +/*-------------------------------- 类型定义 ------------------------------------*/ + +#ifdef OS_UNIX + + typedef unsigned char BYTE; + typedef unsigned char u_char; + typedef unsigned char UCHAR; + + typedef unsigned long DWORD; + typedef unsigned short WORD; + typedef unsigned short u_short; + typedef unsigned short USHORT; + + typedef int BOOL; + typedef int INT; + + typedef unsigned int u_int; + typedef unsigned int UINT; + typedef unsigned int SOCKET; //为编译通过而临时从Winsock.h中提取的类型定义 + + typedef unsigned long u_long; + typedef unsigned long ULONG; + +#endif + +#ifdef _OS_64BIT_ + typedef int i_32; //固定长度为4个字节的有符号整数类型 + typedef unsigned int u_32; //固定长度为4个字节的无符号整数类型 + + typedef long _int64; //Vc中64位整数_int64在64位unix下对应long(8个字节), dnp30.cpp中引用 +#else + typedef long i_32; + typedef unsigned long u_32; + + #ifdef OS_UNIX + typedef int64_t _int64; //Vc中64位整数_int64在32位unix下对应int64_t,在sys/types.h中定义 + #endif +#endif + +#ifdef OS_UNIX + typedef u_32 DWORD; //DWORD为固定长度4个字节的无符号整数 +#endif + +/*----------------------------------- 常数定义 ----------------------------------*/ + +#ifdef OS_UNIX + #define TRUE 1 + #define FALSE 0 + #define NULL 0 + + #define INVALID_SOCKET (SOCKET)(~0) //为编译通过而临时从Winsock.h中提取的类型定义 + #define SOCKET_ERROR (-1) + #define INADDR_NONE 0xffffffff +#endif + +/*------------------------------------ 宏定义 -----------------------------------*/ + +#ifdef OS_UNIX + #define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8)) + #define MAKELONG(a, b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16)) + #define LOWORD(l) ((WORD)(l)) + #define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) + #define LOBYTE(w) ((BYTE)(w)) + #define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) + #define max(a,b) (((a) > (b)) ? (a) : (b)) + #define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/*-------------------------------------------------------------------------------*/ + + +#endif //PLATFORM_DEF_H diff --git a/portconfig.ini b/portconfig.ini new file mode 100644 index 0000000..0e2ec77 --- /dev/null +++ b/portconfig.ini @@ -0,0 +1,246 @@ +[Port1] +Protocol=buban103 +CommMode=9600,e,8,1 +WorkMode=RS-485 +HandshakeMode=NO_HANDSHAKE +XonXoff=0000 +AiNum=128 +DiNum=256 +PiNum=0 +Retry=1 +RetryTime=3 +WaitTime=0 +ykyttimeout=20 +PortType=0 +CheckTime=NO +#@@规约配置 +时间同步过程=60.00 +总查询过程=60.00 +电度量查询=300.00 +通用分类数据模拟量查询=3.00 +通用分类数据状态量查询=3.00 +链路数量=1 +链路1模板文件名称=port103ser.csv +链路2模板文件名称= +链路3模板文件名称= +链路4模板文件名称= +链路5模板文件名称= +链路6模板文件名称= +上送遥信变位=0 +#@@测点配置--主站 +Di2CtrlNo=0 +[Port2] +Protocol = modbus +CommMode = 9600,n,8,1 +WorkMode = RS-485 +AiNum = 128 +DiNum = 256 +#PiNum = 48 +# 轮询指令时间配置 +Retry = 1 +RetryTime = 1 +WaitTime = 0 +# 端口类型(=0, 主站端口; =1, 子站端口) +PortType = 0 +# 时间校正(=no, 不对时(缺省); =up, 上对时; =down, 下对时) +CheckTime = no +装置数量=1 +装置状态输入厂站端口号 = 16 +装置状态输入厂站起始点号 = 3 +是否屏蔽未配置信息事件 = 0 +模拟量指令 = 3,0,53 +开关量指令 = 3,100,4 +遥控项数=1 +遥控1配置=1,16,3,0,108,8899,300,110,21930,200,110,43605,0,1,108,8899,300,109,21930,200,109,43605,0 +Di1CtrlNo = 1 +寄存器位数 = 16 +#装置1配置信息文件名称 = mach300 +装置1线路名称 = +装置1寄存器位数=16 +装置1型号 = mach300 +装置1地址 = 1 +#模板文件名称=mach300 +指令发送序列=dda +SOE状态即遥信状态=1 +[Port3] +Protocol=buban103 +CommMode=9600,e,8,1 +WorkMode=RS-485 +HandshakeMode=NO_HANDSHAKE +XonXoff=0000 +AiNum=128 +DiNum=256 +PiNum=0 +Retry=1 +RetryTime=3 +WaitTime=0 +ykyttimeout=20 +PortType=0 +CheckTime=NO +#@@规约配置 +时间同步过程=0 +总查询过程=60.00 +电度量查询=300.00 +通用分类数据模拟量查询=3.00 +通用分类数据状态量查询=3.00 +链路数量=1 +链路1模板文件名称=port103sie.csv +链路2模板文件名称= +链路3模板文件名称= +链路4模板文件名称= +链路5模板文件名称= +链路6模板文件名称= +上送遥信变位=0 +#@@测点配置--主站 +Di1CtrlNo=0 +Di2CtrlNo=1 +[Port4] +Protocol=buban103 +CommMode=9600,e,8,1 +WorkMode=RS-485 +HandshakeMode=NO_HANDSHAKE +XonXoff=0000 +AiNum=128 +DiNum=256 +PiNum=0 +Retry=1 +RetryTime=3 +WaitTime=0 +ykyttimeout=20 +PortType=0 +CheckTime=NO +装置数量 = 1 +请求系统运行状态 = 10 +请求交流配电信息 = 10 +请求电池检测单元信息 = 10 +请求馈线检测单元信息 = 10 +请求绝缘监察单元信息 = 10 +请求整流模块信息 = 10 +请求参数设定信息 = 0 +装置1地址 = 1 +装置1电池数量 = 52 +装置1整流模块数量 = 4 +装置1名称 = gjb +[Port5] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port6] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port7] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port8] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port9] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port10] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port11] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port12] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port13] +Protocol=bypass +CommMode=9600,n,8,1 +WorkMode=RS-232 +[Port14] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port15] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port16] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port17] +Protocol=scadaprotect +NetCommMode=TCP,Server +NetPort=8000 +NetCommAddr=127.0.0.1 +AiNum=0 +DiNum=0 +PiNum=0 +Retry=1 +RetryTime=3 +WaitTime=0 +ykyttimeout=20 +PortType=1 +CheckTime=NO +#@@规约配置 +模板文件名称=scada.csv +[Port18] +Protocol=buban104 +NetCommMode=TCP,Server +NetPort=2404 +NetCommAddr=192.168.111.168 +AiNum=128 +DiNum=256 +PiNum=64 +Retry=1 +RetryTime=3 +WaitTime=0 +ykyttimeout=20 +PortType=1 +CheckTime=UP +#@@规约配置 +站地址=1 +总召唤电度数据=120.00 +召唤初始化数据=300.00 +帧序应答=20.00 +超时时间=3.00 +转发返校超时时间=0.00 +转发是否要求应答=0 +超时发送测试帧=0 +遥控方式=0 +遥测信息体起始地址=1793 +遥信信息体起始地址=1 +遥脉信息体起始地址=3073 +遥控信息体起始地址=2817 +版本号=1 +#@@测点配置--从站 +ProvAi1=1a1,1 +ProvAi1Inc=18 +ProvAi20=2a1,1 +ProvAi21=2a2,1 +ProvAi22=2a3,1 +ProvAi23=2a5,1 +ProvAi24=2a6,1 +ProvAi25=2a7,1 +ProvAi26=2a9,1 +ProvAi27=2a10,1 +ProvAi28=2a11,1 +ProvAi29=2a16,1 +ProvAi30=2a17,1 +ProvAi31=2a1,1 +ProvAi32=3a1,1 +ProvAi32Inc=16 +ProvDi1=2d1,1 +ProvDi2=2d17 +ProvDi3=2d33 +ProvDi4=2d49 +[Port19] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 +[Port20] +Protocol = bypass +CommMode = 9600,n,8,1 +WorkMode = RS-232 + diff --git a/scadaprotect.cpp b/scadaprotect.cpp new file mode 100644 index 0000000..28f5449 --- /dev/null +++ b/scadaprotect.cpp @@ -0,0 +1,2405 @@ +//*************************************************************** +//* scadaprotect.cpp * +//* aaawen 2004.10.19 * +//*************************************************************** + +#ifdef OS_LINUX +#include "baohulib/commport.h" +#include "baohulib/serialport.h" +#else +#include "commport.h" +#include "udpcomm.h" +#include "display.h" +#endif +#include +#include "scadaprotect.h" +#include "buban103.h" + +extern SIO_PARAM_DEF SioParam[]; +extern FUNCTION_CALL *FunCallPtr; +extern BYTE SyncWordEB[]; +extern void *pvconf_handle; +extern void *pvportconf_handle; +extern void *pvdataconf_handle; +extern char pvDataFileName[256]; +extern char IniFilePath[256]; + +const int gActiveConst = 3; +const int gStatusConst = 10; + +/*! + 组织结构:链路(间隔)+装置 +*/ +const char *gpStrScadaProtectConfigInfo[] = +{ + "*******斯凯达内部保护规约开始*******", + "模板文件名称=template.csv", + "*******斯凯达内部规约结束*******", + "", // 结束标志(中间不能含有该空字符串) +}; + +//******************************************************************** +//* 读取配置函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void ScadaProtectReadConfig(int commid) +{ + int i, iMaxPort, iDevId; + char szSection[128], entry[256]; + char szPortConfig[256], szTemplate[256]; + PORTSTATUS sPortStatus; + SCADAPROTECTPORTPARAM *pPortParam; + +#ifdef OS_LINUX + strcpy(szPortConfig, "portconfig.ini"); +#else + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szPortConfig, "%s/portconfig.ini", IniFilePath); +#endif + + SioParam[commid].ExtInfo = HEAP_MALLOC(sizeof(SCADAPROTECTPORTPARAM)); + + if(!SioParam[commid].ExtInfo) + { + sprintf(szSection, "WARN(%04d): commid_%02d ExtInfo=malloc(%d) failed.", + _getpid(), commid, sizeof(SCADAPROTECTPORTPARAM)); + DebugPrint(szSection); + return; + } + + memset(SioParam[commid].ExtInfo, 0, sizeof(SCADAPROTECTPORTPARAM)); + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + + // 只有在SioParam[commid].m_psBaoHu非空时,才会运行到这里 + pPortParam->m_psBaoHu = SioParam[commid].m_psBaoHu; + + iMaxPort = GetMaxPort(); + pPortParam->m_pPrtPortStatus = (PORTSTATUS *)HEAP_MALLOC(iMaxPort*sizeof(PORTSTATUS)); + //memset((void *)pPortParam->m_pPrtPortStatus, 0, GetMaxPort()*sizeof(PORTSTATUS)); + + for(i=0; im_iActiveTimeCnt = 0; + pPortParam->m_iActiveTimeConst = (gActiveConst*1000)/TIMER_CNT; + + pPortParam->m_iStatusTimeCnt = 0; + pPortParam->m_iStatusTimeConst = (gStatusConst*1000)/TIMER_CNT; + + // + sprintf(szSection, "Port%d", commid+1); + strcpy(entry, "模板文件名称"); + GetPrivateProString(szSection, entry, "template.csv", pPortParam->m_chArrayTempletFileName, + sizeof(pPortParam->m_chArrayTempletFileName)-1, szPortConfig); +#ifdef OS_LINUX + sprintf(szTemplate, "inf/%s", pPortParam->m_chArrayTempletFileName); +#else + sprintf(szTemplate, "%s/inf/%s", IniFilePath, pPortParam->m_chArrayTempletFileName); +#endif + InitScadaInfoFromTempletFile(commid, pPortParam, szTemplate, FALSE); + + // wen 2005.06.22 + // 初始化单向链表,链表最大数量为20个 + //SingleListInit(&pPortParam->m_sBaoHuData, 20); + iDevId = commid<<16; + SingleListInitEx(&pPortParam->m_sBaoHuData, 20, iDevId); +} + +//******************************************************************** +//* 读取端口数据函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void ScadaProtectRecvData(int commid, u_char *buf, int len)// 规约读数据处理 +{ + int i; + PROTECTMSGHEAD sMsgHead; + SCADAPROTECTPORTPARAM *pPortParam; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + + for(i=0; im_psBaoHu->m_iRevStatus) + { + case 0: + pPortParam->m_iRecvLen = 0; + case 1: + case 2: + case 3: + case 4: + case 5: + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(buf[i] == SyncWordEB[pPortParam->m_psBaoHu->m_iRevStatus]) + { + pPortParam->m_psBaoHu->m_iRevStatus++; + } + else + { + pPortParam->m_psBaoHu->m_iRevStatus = 50; + // 错误数据增加 + //SioParam[commid].ErrMsgNum++; + } + break; + case 6: + case 7: + case 8: + case 9: // 功能码 + case 10: + case 11: + case 12: + case 13: // 端口号 + case 14: + case 15: + case 16: + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + break; + case 17: // 长 度(长度计算) + pPortParam->m_psBaoHu->m_iRevStatus++; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + memcpy((void *)&sMsgHead, pPortParam->m_achRecvBuf+6, sizeof(PROTECTMSGHEAD)); + SequenceNetToHost((char *)&sMsgHead.MsgLen, sizeof(u_32)); + if(sMsgHead.MsgLen == 0) + { + ScadaProtectProcessData(commid, pPortParam, TRUE); +#ifndef OS_LINUX + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + pPortParam->m_psBaoHu->m_iRevStatus = 0; + } + else + { + pPortParam->m_psBaoHu->m_iNeedRevLength = sMsgHead.MsgLen; + } + break; + case 18:// 正确接收数据 + pPortParam->m_psBaoHu->m_iNeedRevLength--; + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(pPortParam->m_psBaoHu->m_iNeedRevLength > 0) + { + // wen 2006.04.29 修改数据缺少后的数据同步 + if(buf[i] == 0x90) + { + if(pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen-2] == (char)0xeb) + { + pPortParam->m_achRecvBuf[0] = (char)0xEB; + pPortParam->m_achRecvBuf[1] = (char)0x90; + pPortParam->m_psBaoHu->m_iRevStatus = 2; + pPortParam->m_iRecvLen = 2; + } + } + break; + } + + ScadaProtectProcessData(commid, pPortParam, TRUE); +#ifndef OS_LINUX + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + pPortParam->m_psBaoHu->m_iRevStatus = 0; + //pPortParam->m_iRecvLen = 0; + break; + + case 19:// 错误接收数据 + default: + if(buf[i] == 0xEB) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + ScadaProtectProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + + // 从状态1开始 + pPortParam->m_achRecvBuf[0] = buf[i]; + pPortParam->m_psBaoHu->m_iRevStatus = 1; + pPortParam->m_iRecvLen = 1; + } + else + { + pPortParam->m_achRecvBuf[pPortParam->m_iRecvLen++] = buf[i]; + if(pPortParam->m_iRecvLen > 200) + { +#ifndef OS_LINUX + // wen 2004.11.22 增加显示 + if((GetCurPort() == commid) && IsRealDataDisp()) + { + WatchDataPutDispBuf(commid, SDS_SIO_RECV_DATA, + (BYTE *)pPortParam->m_achRecvBuf, pPortParam->m_iRecvLen); + } +#endif + ScadaProtectProcessData(commid, pPortParam, FALSE); + SioParam[commid].ErrMsgNum += pPortParam->m_iRecvLen; + pPortParam->m_iRecvLen = 0; + } + } + break; + } + } + +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "wen: commid = %d, send=%d, recv=%d, error=%d, lost=%d\n", commid, + SioParam[commid].SendCharNum, SioParam[commid].RecvCharNum, + SioParam[commid].ErrMsgNum, SioParam[commid].LostSyncCnt); + DebugPrint(szbuf); +#endif +} + +//******************************************************************** +//* 定时器处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void ScadaProtectTimer(int commid) +{ + RTUMSG rtumsg; + PORTSTATUS sPortStatus; + SCADAPROTECTPORTPARAM *pPortParam; + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + + if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) + { + return; + } + + ReduceTimeOut(pPortParam); + + //1. 发送定值数据,保护模拟量,保护开关量 + if(SingleListHaveData(&pPortParam->m_sBaoHuData) > 0) + { + // wen 2006.05.11 将整个RTUMSG结构压入列表 + //rtumsg.MsgLen = SingleListGetAndDelData(&pPortParam->m_sBaoHuData, rtumsg.MsgData, sizeof(rtumsg.MsgData)); + rtumsg.MsgLen = SingleListGetAndDelData(&pPortParam->m_sBaoHuData, (BYTE *)&rtumsg, sizeof(RTUMSG)); + rtumsg.MsgLen -= sizeof(RTUMSGHEAD); + if(rtumsg.MsgLen > 0) + { + // wen 2006.05.11 在此将繁忙标识清空 + if((rtumsg.PortIdx >= 0) && (rtumsg.PortIdx < GetMaxPort())) + { + sPortStatus.bPortIdle = TRUE; + sPortStatus.mmid = 0xFFFFFFFF; + sPortStatus.timeOut = 0; + SetProtectPortIdle(rtumsg.PortIdx, pPortParam, &sPortStatus); + } + + FormatDataAndSend(commid, (PROTECTMSG *)rtumsg.MsgData); + return; + } + } + + //2. 发送soe数据,保护事件 + if(ProvHaveSoeData(commid) > 0) + { + //printf("scadaprotect have soe data.\n"); + if(MakeSoeDataPacket(commid) == TRUE) + { + return; + } + } + + //3. 定时发送网络活动包和通道状态 + if(pPortParam->m_iActiveTimeConst > 0) + { + pPortParam->m_iActiveTimeCnt++; + if(pPortParam->m_iActiveTimeCnt > pPortParam->m_iActiveTimeConst) + { + pPortParam->m_iActiveTimeCnt = 0; + MakeNetActivePacket(commid); + } + } + if(pPortParam->m_iStatusTimeConst > 0) + { + pPortParam->m_iStatusTimeCnt++; + if(pPortParam->m_iStatusTimeCnt > pPortParam->m_iStatusTimeConst) + { + pPortParam->m_iStatusTimeCnt = 0; + MakeStatusPacket(commid); + } + } + + + //Buban103SendCmdFormPollCmdBuf(commid); +} + +//******************************************************************** +//* 遥控遥调数据处理函数 * +//*参数:int commid : 端口号 * +//* u_char buf : 数据源缓冲区指针 * +//* int len : 数据源长度 * +//******************************************************************** +void ScadaProtectYkYtProcess(int commid, u_char *buf, int len) // 遥控遥调处理 +{ + int portno, ykytpnt; + int iDirect; + //SCADAPROTECTPORTPARAM *pPortParam; + + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分) + // (最高位为1时,为返校命令, 1=控合, 2=控分, 3=失败) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 + + if(IsExtInfoPtr(commid) == FALSE) + { + return; + } + + iDirect = buf[9] & 0x80; + portno = buf[0]+buf[1]*256+buf[2]*65536+buf[3]*16777216; + ykytpnt = buf[4]+buf[5]*256+buf[6]*65536+buf[7]*16777216; +} + +//******************************************************************** +//* 系统退出时规约处理函数 * +//*参数:int commid : 端口号 * +//******************************************************************** +void ScadaProtectExit(int commid) +{ + SCADAPROTECTPORTPARAM *pPortParam; + + if(SioParam[commid].ExtInfo == NULL) + { + return; + } + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + + if(pPortParam->m_pPrtPortStatus != NULL) + { + HEAP_FREE(pPortParam->m_pPrtPortStatus); + pPortParam->m_pPrtPortStatus = NULL; + } + if(pPortParam->m_psProvDev != NULL) + { + HEAP_FREE(pPortParam->m_psProvDev); + pPortParam->m_psProvDev = NULL; + } + + SingleListDelData(&pPortParam->m_sBaoHuData); +} + +// 该函数用来驱动由转发端口下发到实际装置的保护命令 +void ScadaProtectBaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData) +{ + //char szDbg[128]; + //int iProvAddr; + //PROTECTCONTENTHEAD *ptrProHead; + SCADAPROTECTPORTPARAM *pPortParam; + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + // 上行数据 + if(MSGTYPE_BAOHU_SCADADATA == rtumsg->MsgType) + //if(bUpData == TRUE) + { + if(pPortParam->m_psProvDev != NULL) + { + // wen 2006.05.11 将整个RTUMSG结构压入列表 + //SingleListAddData(&pPortParam->m_sBaoHuData, rtumsg->MsgData, rtumsg->MsgLen); + SingleListAddData(&pPortParam->m_sBaoHuData, (BYTE *)rtumsg, rtumsg->MsgLen+sizeof(RTUMSGHEAD)); + } + return; + } +} + +int ScadaProtectGetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB) +{ + return 0; +} +/////////////////////////通用函数接口结束/////////////////////////////// + +///////////////////////////以下为配置函数接口/////////////////////////// +BOOL InitScadaInfoFromTempletFile(int commid, SCADAPROTECTPORTPARAM *psPortParam,\ + char *ptrTemplate, BOOL bMaster) +{ + char *ptr; + char szBuf[512]; + BOOL bVal; + HDSFILE hFile; + enum Param_Type ParamType; + + if(bMaster == TRUE) + { + return FALSE; + } + + hFile = DSOpenFile(ptrTemplate); + if(hFile == NULL) + { + return FALSE; + } + + ParamType = PARAM_NO; + while(TRUE) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(!ptr) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "链路描述") != NULL) + { + //处理链路参数 + ParamType = PARAM_LINK; + } + else if(strstr(ptr, "设备描述") != NULL) + { + ParamType = PARAM_DEV; + } + else if(PARAM_NO == ParamType) + { + continue; + } + + switch(ParamType) + { + case PARAM_LINK: + bVal = GetProvDevNumFromTemplateFileScada(commid, hFile, psPortParam); + if(TRUE == bVal) + { + if(psPortParam->m_iDevNum > 0) + { + // test + //DebugPrint("malloc provDev."); + + psPortParam->m_psProvDev = (SCADAPROVDEVDEF *)HEAP_MALLOC(psPortParam->m_iDevNum*sizeof(SCADAPROVDEVDEF)); + if(psPortParam->m_psProvDev == NULL) + { + psPortParam->m_iDevNum = 0; + } + memset((void *)psPortParam->m_psProvDev, 0, psPortParam->m_iDevNum*sizeof(SCADAPROVDEVDEF)); + } + } + break; + + case PARAM_DEV: + bVal = GetProvDevParamFromTemplateFileScada(commid, hFile, psPortParam); + break; + + default: + break; + } + } + + DSCloseFile(hFile); + return TRUE; +} + +BOOL GetProvDevNumFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam) +{ + char *ptr, *ptrSour, *ptrDest; + char szBuf[512]; + int i, ilen; + BOOL bRetVal; + + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + + if(ptr == NULL) + { + return FALSE; + } + + // test + //DebugPrint(szBuf); + + ptrSour = szBuf; + + if(strstr(ptrSour, "LINK") == NULL) + { + return FALSE; + } + + bRetVal = FALSE; + for(i=0; i<4; i++) + { + if(GetParamItem(ptrSour, &ptrDest) == FALSE) + { + bRetVal = FALSE; + break; + } + *ptrDest = 0; + ilen = strlen(ptrSour); + + switch(i) + { + case 0:// 链路描述 + break; + case 1:// 链路标识 + break; + case 2:// 链路地址 + break; + case 3:// 装置数量 + if(ilen > 0) + { + psPortParam->m_iDevNum = atoi(ptrSour); + bRetVal = TRUE; + } + break; + case 4:// 备用 + break; + case 5:// 备用 + break; + case 6:// 地址偏移 + break; + case 7:// 数据类型 + break; + case 8:// 写入数据库站号 + break; + case 9:// 写入数据库起始点号 + break; + case 10:// 是否判断ASDU号 + break; + case 11:// 是否处理扰动数据 + break; + case 12:// 是否屏蔽未配置事件 + break; + case 13:// 一类数据问询次数(该项不可达,在循环外处理) + break; + } + ptrSour = ptrDest+1; + } + + return bRetVal; +} + +BOOL GetProvDevParamFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam) +{ + char *ptr, *ptrSour, *ptrDest; + char szBuf[512]; + int i, j, ilen, iNum; + int iAiNum, iAiStart, iDiStart; + int iPiStart, iYkStart, iPntNo; + BOOL bRetVal; + enum Param_Type ParamType; + + iAiStart = 0; + iDiStart = 0; + iPiStart = 0; + iYkStart = 0; + iAiNum = 0; + ParamType = PARAM_NO; + for(i=0; im_iDevNum;) + { + ptr = DSfgets(szBuf, sizeof(szBuf), hFile); + if(ptr == NULL) + { + break; + } + + // test + //DebugPrint(szBuf); + + if(strstr(ptr, "设备描述") != NULL) + { + i++; + iAiNum = 0; + ParamType = PARAM_NO; + continue; + } + + if(strstr(ptr, "链路描述") != NULL) + { + break; + } + + ptrSour = ptr; + for(j=0; j<8; j++) + { + if(GetParamItem(ptrSour, &ptrDest) == FALSE) + { + bRetVal = FALSE; + break; + } + *ptrDest = 0; + ilen = strlen(ptrSour); + + switch(j) + { + case 0:// 设备描述 + break; + case 1:// 设备型号 + break; + case 2:// 设备地址 + break; + case 3:// 转发地址 + if(PARAM_NO != ParamType) + { + break; + } + if(ilen > 0) + { + psPortParam->m_psProvDev[i].m_iProvAddr = atoi(ptrSour); + } + break; + case 4:// 端口号&状态站号&状态点号 + if(PARAM_NO != ParamType) + { + break; + } + if(ilen > 0) + { + psPortParam->m_psProvDev[i].m_iRealCommid = atoi(ptrSour); + if(GetParamItemEx(ptrSour, &ptr, "&") == FALSE) + { + psPortParam->m_psProvDev[i].m_iStatusStn = 0; + psPortParam->m_psProvDev[i].m_iStatusPnt = 0; + break; + } + ptrSour = ptr+1; + if(strlen(ptrSour) > 0) + { + psPortParam->m_psProvDev[i].m_iStatusStn = atoi(ptrSour); + if(GetParamItemEx(ptrSour, &ptr, "&") == FALSE) + { + psPortParam->m_psProvDev[i].m_iStatusStn = 0; + psPortParam->m_psProvDev[i].m_iStatusPnt = 0; + break; + } + ptrSour = ptr+1; + if(strlen(ptrSour) > 0) + { + psPortParam->m_psProvDev[i].m_iStatusPnt = atoi(ptrSour); + } + } + } + break; + case 5:// 备用 + break; + case 6:// 数量 + if(ilen > 0) + { + iNum = atoi(ptrSour); + } + break; + case 7:// 数据类型 + if(iNum <= 0) + { + break; + } + if(ilen > 0) + { + if(strcmp(ptrSour, "YC") == 0) + { + ParamType = PARAM_YC; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YX") == 0) + { + ParamType = PARAM_YX; + psPortParam->m_psProvDev[i].m_sYxInfo.m_iPntNum = iNum; + psPortParam->m_psProvDev[i].m_sYxInfo.m_iStartPntNo = iDiStart; + psPortParam->m_psProvDev[i].m_sYxInfo.m_iStnNo = 0; + psPortParam->m_psProvDev[i].m_sYxInfo.m_psDataInfo = NULL; + iDiStart += iNum; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YM") == 0) + { + ParamType = PARAM_YM; + iPntNo = 0; + } + else if(strcmp(ptrSour, "YK") == 0) + { + ParamType = PARAM_YK; + iPntNo = 0; + } + else if(strcmp(ptrSour, "SYNCTIME") == 0) + { + ParamType = PARAM_SYNCTIME; + iPntNo = 0; + } + else if(strcmp(ptrSour, "ASDU10") == 0) + { + ParamType = PARAM_ASDU10; + iPntNo = 0; + } + } + break; + default: + break; + } + ptrSour = ptrDest+1; + } + + switch(ParamType) + { + case PARAM_YC: + break; + case PARAM_YX: + break; + case PARAM_YM: + break; + case PARAM_YK: + break; + case PARAM_SYNCTIME: + break; + case PARAM_ASDU10: + break; + default: + break; + } + } + return bRetVal; +} + +int FindProtectDevFromPntNoScada(SCADAPROTECTPORTPARAM *psPortParam, int iPntNo, int itype) +{ + int i, ipnt; + BOOL bRetVal; + DBORIENTATION *pDataUnit; + + bRetVal = FALSE; + if(psPortParam->m_psProvDev == NULL) + { + return -1; + } + + //printf("psPortParam->m_iDevNum = %d\n", psPortParam->m_iDevNum); + + for(i=0; im_iDevNum; i++) + { + switch(itype) + { + case DI_PNT_TYPE: + pDataUnit = &psPortParam->m_psProvDev[i].m_sYxInfo; + break; + case AI_PNT_TYPE: + case PI_PNT_TYPE: + default: + pDataUnit = NULL; + break; + } + if(pDataUnit == NULL) + { + continue; + } + + //printf("pDataUnit->m_iStartPntNo=%d, pDataUnit->m_iPntNum=%d\n", + // pDataUnit->m_iStartPntNo, pDataUnit->m_iPntNum); + + ipnt = iPntNo - pDataUnit->m_iStartPntNo; + if((ipnt >= 0) && (ipnt < pDataUnit->m_iPntNum)) + { + break; + } + } + + if(i >= psPortParam->m_iDevNum) + { + return -1; + } + else + { + return i; + } +} +/////////////////////////////配置函数接口结束/////////////////////////// + + +void ScadaProtectProvMakeYkYtCommand(int commid, u_char *buf, int len) +{ + // buf[0] --- 端口号(=commid) + // buf[1] + // buf[2] + // buf[3] + // buf[4] --- 控点号 + // buf[5] + // buf[6] + // buf[7] + // buf[8] --- 操作类型(遥控:1=选择,2=执行,3=取消,7=直控; + // 遥调:4=选择,5=执行,6=取消,8=急停) + // buf[9] --- 控制状态(1=分到合,2=合到分, 0=失败) + // (最高位为1时,为返校命令) + // 在转发遥控数据点中,只保留了要转发的控点号,实际的端口号应该是该转发点的端口 + // 该转发点并没有指定虚拟的转发控点,则控点和转发点的点号一致。 +} + +///////////////////////以下为规约处理函数接口/////////////////////////// +//*******************************************************************************/ +//* 将客户端到前置机所有的报文从网络字节顺序转换成主机字节顺序函数 */ +//*参数:RTUMSG* hostmsg:转换后的主机字节顺序报文 */ +//* ORTUMSG* userdata:转换前的网络字节顺序报文 */ +//*返回值:无 */ +//*******************************************************************************/ +void AllNetToHostByteSequence(PROTECTMSG *userdata) +{ + u_32 iOffset; + pPROTECTCONTENTHEAD ptrContent; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + SequenceNetToHost((char *)&userdata->MsgType, sizeof(u_32)); + SequenceNetToHost((char *)&userdata->PortNumber, sizeof(u_32)); + SequenceNetToHost((char *)&userdata->MsgLen, sizeof(u_32)); + switch(userdata->MsgType) + { + case pPFV_PROTECT_BYPASS://保护机到前置机保护数据 + ptrContent = (pPROTECTCONTENTHEAD)(userdata->MsgData); + //转换保护地址 + SequenceNetToHost((char *)&ptrContent->uAddr, sizeof(u_32)); + //转换保护操作功能码 + SequenceNetToHost((char *)&ptrContent->uFuncCode, sizeof(u_32)); + //操作用户 + SequenceNetToHost((char *)&ptrContent->ummid, sizeof(u_32)); + //保留字节 + SequenceNetToHost((char *)&ptrContent->uReserved, sizeof(u_32)); + //定值区号 + //ptrContent->cFixNo; + //CPU 号 + //ptrContent->cCPUNo; + iOffset = sizeof(PROTECTCONTENTHEAD); + switch(ptrContent->uFuncCode) + { + case hREADFIX://读取定值 + case hREADPAI:// 读取保护模拟量 + case hREADPDI:// 读取保护开关量 + case hQUERYFAULT:// 读取指定故障报告 + case hQUERYSELFCHECK:// 读取指定的自检报告 + break; + case hREADFIXNO://读取定值区号 + case hREADPWAVE:// 读取保护波形数据 + break; + case hWRITEALLFIX:// 修改保护定值 + // 起始序号 + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + for(; iOffsetMsgLen;) + { + // 数据类型 + switch(userdata->MsgData[iOffset++] & 0x7F) + { + case DATATYPE_AI: + // 数据值长度(占用位数) + iOffset++; + // 数值 + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + break; + case DATATYPE_DI: + // 数据值长度(占用位数) + iOffset++; + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + break; + case DATATYPE_STRING: + // 数据值长度(占用字节数) + // 数值 + iOffset += userdata->MsgData[iOffset] + 1; + break; + default: +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机下发写定值报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + return; + } + } + break; + case hWRITESPECIALFIX:// 修改指定的保护定值 + for(;iOffsetMsgLen;) + { + // 定值序号 + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + // 数据类型 + switch(userdata->MsgData[iOffset++] & 0x7F) + { + case DATATYPE_AI: + // 数据值长度(占用位数) + iOffset++; + // 数值 + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + break; + case DATATYPE_DI: + // 数据值长度(占用位数) + iOffset++; + SequenceNetToHost((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + break; + case DATATYPE_STRING: + // 数据值长度(占用字节数) + // 数值 + iOffset += userdata->MsgData[iOffset] + 1; + break; + default: +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机下发写指定定值报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + return; + } + } + break; + case hWRITEFIXNO:// 修改保护定值区 + break; + case hRESETPROTECT:// 保护信号复归 + break; + case hCHECKTIME:// 单个装置对时 + break; + case hBROADCASTCHECKTIME:// 保护装置广播对时 + break; + case hCANCEL:// 保护操作取消 + break; + } + break; + case fPFV_NETACTIVE://网络测试包 + break; + default: + break; + } +} + +//*******************************************************************************/ +//* 将前置机到客户机所有的报文从主机字节顺序转换成网络字节顺序函数 */ +//*参数:RTUMSG* userdata:转换前的主机字节顺序报文 */ +//* ORTUMSG* hostmsg:转换后的网络字节顺序报文 */ +//*返回值:无 */ +//*******************************************************************************/ +void AllHostToNetByteSequence(PROTECTMSG *userdata) +{ + u_short u_shortLen; + u_32 uDataLen, datatype, msgtype, uFuncCode; + u_32 iOffset; + pPROTECTCONTENTHEAD ptrContent; +#ifdef _DEBUG_MSG_ + char szbuf[512]; +#endif + + uDataLen = userdata->MsgLen; + msgtype = userdata->MsgType; + SequenceHostToNet((char *)&userdata->MsgType, sizeof(u_32)); + SequenceHostToNet((char *)&userdata->PortNumber, sizeof(u_32)); + SequenceHostToNet((char *)&userdata->MsgLen, sizeof(u_32)); + + switch(msgtype) + { + case fPFV_PROTECT_BYPASS_ACK://前置机到保护机保护数据 + ptrContent = (pPROTECTCONTENTHEAD)(userdata->MsgData); + uFuncCode = ptrContent->uFuncCode; + //转换保护地址 + SequenceHostToNet((char *)&ptrContent->uAddr, sizeof(u_32)); + //转换保护操作功能码 + SequenceHostToNet((char *)&ptrContent->uFuncCode, sizeof(u_32)); + //操作用户 + SequenceHostToNet((char *)&ptrContent->ummid, sizeof(u_32)); + //保留字节 + SequenceHostToNet((char *)&ptrContent->uReserved, sizeof(u_32)); + //定值区号 + //ptrContent->cFixNo; + //CPU 号 + //ptrContent->cCPUNo; + iOffset = sizeof(PROTECTCONTENTHEAD); + switch(uFuncCode) + { + case hREADINGDATA:// 数据申请中 + break; + case hFIXDATAWITHNO:// 定值数据带序号 + // 定值类型 + datatype = userdata->MsgData[iOffset++]; + + for(;iOffsetMsgData[iOffset], sizeof(WORD)); + iOffset += sizeof(WORD); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + // 定值数据类型 + switch(userdata->MsgData[iOffset] & 0x7F) + { + case DATATYPE_AI: + case DATATYPE_DI: + iOffset++; + if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + break; + case DATATYPE_STRING: + iOffset++; + // 数据长度(占用字节数) + // 数值 + if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + break; + default: + userdata->MsgLen = 0; + return; + } + break; + case ITEM_ATTR_UNIT:// 量 纲 + case ITEM_ATTR_DESCRIPTION:// 描 述 + // 数据长度(占用字节数) + //userdata->MsgData[iOffset]; + // 数值 + if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + + break; + case ITEM_ATTR_RATE:// 参 比 + case ITEM_ATTR_LIST:// 列 表 + default: + iOffset = uDataLen; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机上行读取定值报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + break; + } + } + break; + case hPAIDATAWITHNO: // 保护模拟量数据带序号 + break; + case hPDIDATAWITHNO: // 保护开关量数据带序号 + break; + case hFIXDATA:// 定值数据 + // 定值类型 + datatype = userdata->MsgData[iOffset++]; + + // 起始序号 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + + for(;iOffsetMsgData[iOffset] & 0x7F) + { + case DATATYPE_AI: + case DATATYPE_DI: + iOffset++; + // 数值 + if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + + break; + case DATATYPE_STRING: + iOffset++; + // 数据长度(占用字节数) + // 数值 + if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + + break; + default: + userdata->MsgLen = 0; + return; + } + break; + case ITEM_ATTR_UNIT:// 量 纲 + case ITEM_ATTR_DESCRIPTION:// 描 述 + // 数据长度(占用字节数) + // 数值 + if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + } + + break; + case ITEM_ATTR_RATE:// 参 比 + case ITEM_ATTR_LIST:// 列 表 + default: + iOffset = uDataLen; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机上行读取定值报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + break; + } + } + break; + case hREADDATAEND:// 数据申请结束 + break; + case hNORESPONSE:// 数据申请无响应 + break; + case hSYSTEMBUSY:// 数据处理繁忙,稍后重试 + break; + case hFIXNODATA:// 定值区号数据 + break; + case hPAIDATA:// 保护模拟量数据 + // 模拟量类型 + datatype = userdata->MsgData[iOffset++]; + + // 起始序号 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + for(;iOffsetMsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + } + break; + case ITEM_ATTR_UNIT:// 量 纲 + case ITEM_ATTR_DESCRIPTION:// 描 述 + // 数据长度(占用字节数) + // 数值 + if((iOffset + userdata->MsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + } + break; + case ITEM_ATTR_RATE:// 参 比 + case ITEM_ATTR_LIST:// 列 表 + default: + iOffset = uDataLen; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机上行读取保护模拟量报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + } + break; + case hPDIDATA:// 保护开关量数据 + // 开关量类型 + datatype = userdata->MsgData[iOffset++]; + + // 起始序号 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + for(; iOffsetMsgData[iOffset] + 1) < MAX_RTU_MSG_SIZE) + { + iOffset += userdata->MsgData[iOffset] + 1; + } + else + { + userdata->MsgLen = 0; + } + break; + case ITEM_ATTR_MINMAXSTEP:// 量 程 + case ITEM_ATTR_PRECISION:// 精 度 + case ITEM_ATTR_FIGURE:// 因 子 + case ITEM_ATTR_RATE:// 参 比 + case ITEM_ATTR_LIST:// 列 表 + default: + iOffset = uDataLen; +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "保护机上行读取保护开关量报文格式有错误,无效的数据类型"); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + } + break; + case hPWAVEDATASTART:// 保护波行数据上送开始 + break; + case hPWAVEDATA:// 保护波行数据 + /* + //起始序号 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //采样个数 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //转换年 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(WORD)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //转换月 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(WORD)); + iOffset += sizeof(WORD); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //转换日 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //转换时 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换分 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //转换秒 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换微秒 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //采样时间间隔 + if((iOffset + sizeof(float)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + for(;iOffsetMsgData[iOffset], sizeof(float)); + iOffset += sizeof(float); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + } + */ + break; + case hPWAVEDATAEND:// 保护波行数据上送结束 + break; + case hPEVENTDATAWITHID:// 带索引号的事件报告数据 + //转换年 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换月 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换日 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换时 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换分 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换秒 + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //转换微秒 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + for(;iOffsetMsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //备注长度 + if(userdata->MsgData[iOffset] > 0) + { + iOffset += userdata->MsgData[iOffset]+1; + } + else + { + iOffset++; + } + } + break; + case hPEVENTDATAWITHSTRING:// 字符串事件报告数据 + for(; iOffsetMsgData[iOffset]; + if((iOffset + sizeof(u_short)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_short)); + iOffset += sizeof(u_short); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + //字符串 + if((iOffset + u_shortLen) < MAX_RTU_MSG_SIZE) + { + iOffset += u_shortLen; + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset + u_shortLen); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + } + break; + case hWRITEFIXACK:// 保护定值确认 + break; + case hWRITEFIXNAK:// 保护定值不确认 + break; + case hWRITEFIXNOACK:// 定值区修改确认 + break; + case hWRITEFIXNONAK:// 定值区修改不确认 + break; + } + break; + case fPFV_NETACTIVE://网络测试包 + break; + case fPFV_STATUS://前置机状态包 + iOffset = 0; + //前置机A状态 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + + //前置机B状态 + if((iOffset + sizeof(u_32)) < MAX_RTU_MSG_SIZE) + { + SequenceHostToNet((char *)&userdata->MsgData[iOffset], sizeof(u_32)); + iOffset += sizeof(u_32); + } + else + { +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "AllHostToNetByteSequence函数内存拷贝长度(=%d)超出范围, 可能引起内存段错误", iOffset); + DebugPrint(szbuf); +#endif + userdata->MsgLen = 0; + break; + } + break; + + default: + break; + } +} + +void ScadaProtectProcessData(int commid, SCADAPROTECTPORTPARAM *psPortParam, BOOL bProcess) +{ + PROTECTMSG msg; + SCADAPROTECTPORTPARAM *pPortParam; + + /* + if(FALSE == GetPortParamPtr(commid, &pPortParam)) + { + return; + } + */ + pPortParam = psPortParam; + + if(TRUE == bProcess) + { + memcpy((void *)&msg, psPortParam->m_achRecvBuf+6, pPortParam->m_iRecvLen-6); + AllNetToHostByteSequence(&msg); + + // 主站数据处理 + if(PROTOCOL_MASTER == pPortParam->m_psBaoHu->PortType) + { + return; + } + + // 主站数据处理 + switch(msg.MsgType) + { + case pPFV_PROTECT_BYPASS:// 保护指令处理 + ScadaProtectByPassData(commid, pPortParam, &msg); + break; + case fPFV_PROTECT_BYPASS_ACK: // 上行保护数据处理 + break; + case fPFV_NETACTIVE:// 网络活动包 + break; + default: + break; + } + } +} + +void ReduceTimeOut(SCADAPROTECTPORTPARAM *psPortParam) +{ + int i, iMaxPort; + + if(psPortParam->m_pPrtPortStatus == NULL) + { + return; + } + + iMaxPort = GetMaxPort(); + for(i=0; im_pPrtPortStatus[i].timeOut > 0) + { + psPortParam->m_pPrtPortStatus[i].timeOut--; + + if(psPortParam->m_pPrtPortStatus[i].timeOut <= 0) + { + psPortParam->m_pPrtPortStatus[i].mmid = 0xFFFFFFFF; + psPortParam->m_pPrtPortStatus[i].bPortIdle = TRUE; + } + } + } +} + +BOOL IsProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam) +{ + if((commid < 0) || (commid > GetMaxPort())) + { + return TRUE; + } + + if(psPortParam->m_pPrtPortStatus == NULL) + { + return TRUE; + } + + return psPortParam->m_pPrtPortStatus[commid].bPortIdle; +} + +BOOL GetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus) +{ + if((commid < 0) || (commid > GetMaxPort())) + { + return FALSE; + } + + if(psPortParam->m_pPrtPortStatus == NULL) + { + return FALSE; + } + + pStatus->mmid = psPortParam->m_pPrtPortStatus[commid].mmid; + pStatus->timeOut = psPortParam->m_pPrtPortStatus[commid].timeOut; + pStatus->bPortIdle = psPortParam->m_pPrtPortStatus[commid].bPortIdle; + + return TRUE; +} + +BOOL SetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus) +{ + if((commid < 0) || (commid > GetMaxPort())) + { + return FALSE; + } + + if(psPortParam->m_pPrtPortStatus == NULL) + { + return FALSE; + } + + // wen 2005.06.22 在uclinux系统中,初始化时全部为0 + /* + if(psPortParam->m_pPrtPortStatus[commid].bPortIdle == FALSE) + { + if(psPortParam->m_pPrtPortStatus[commid].mmid != pStatus->mmid) + { + return FALSE; + } + } + + psPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; + psPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; + psPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; + */ + + //printf("Idle1(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, + // pStatus->bPortIdle, pStatus->mmid, pStatus->timeOut); + + psPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; + psPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; + psPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; + + //printf("Idle2(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, + // psPortParam->m_pPrtPortStatus[commid].bPortIdle, + // psPortParam->m_pPrtPortStatus[commid].mmid, + // psPortParam->m_pPrtPortStatus[commid].timeOut); + + return TRUE; +} + +BOOL SetProtectPortIdleEx(int commid, int iBaoHuCommid, PORTSTATUS *pStatus) +{ + SCADAPROTECTPORTPARAM *pPortParam; + + if((iBaoHuCommid < 0) || (iBaoHuCommid > GetMaxPort())) + { + return FALSE; + } + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[iBaoHuCommid].ExtInfo; + + if(pPortParam->m_pPrtPortStatus == NULL) + { + return FALSE; + } + + if((commid < 0) || (commid > GetMaxPort())) + { + return FALSE; + } + + //printf("Idle1(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, + // pStatus->bPortIdle, pStatus->mmid, pStatus->timeOut); + + pPortParam->m_pPrtPortStatus[commid].bPortIdle = pStatus->bPortIdle; + pPortParam->m_pPrtPortStatus[commid].mmid = pStatus->mmid; + pPortParam->m_pPrtPortStatus[commid].timeOut = pStatus->timeOut; + + //printf("Idle2(port%d): Idle=%d, mmid=%d, timeout=%d\n", commid+1, + // pPortParam->m_pPrtPortStatus[commid].bPortIdle, + // pPortParam->m_pPrtPortStatus[commid].mmid, + // pPortParam->m_pPrtPortStatus[commid].timeOut); + + return TRUE; +} + +void SendResponsetoMMI(int commid, int mmid, u_32 ResponseType, PROTECTMSG *pmsg) +{ + PROTECTMSG mmimsg; + pPROTECTCONTENTHEAD ptrProHead, pSourProHead; + + memset((void*)&mmimsg, 0, sizeof(PROTECTMSG)); + mmimsg.MsgType = fPFV_PROTECT_BYPASS_ACK; + ptrProHead = (pPROTECTCONTENTHEAD)mmimsg.MsgData; + if(pmsg != NULL) + { + pSourProHead = (pPROTECTCONTENTHEAD)pmsg->MsgData; + mmimsg.PortNumber = pmsg->PortNumber; + + //memcpy(mmimsg.MsgData, rtumsg->MsgData, 10); + ptrProHead->cCPUNo = pSourProHead->cCPUNo; + ptrProHead->cFixNo = pSourProHead->cFixNo; + ptrProHead->uAddr = pSourProHead->uAddr; + ptrProHead->uFuncCode = pSourProHead->uFuncCode; + ptrProHead->ummid = pSourProHead->ummid; + ptrProHead->uReserved = pSourProHead->uReserved; + } + + switch(ResponseType) + { + case hREADINGDATA: // 数据交互开始 + case hREADDATAEND: // 数据交互结束 + case hSYSTEMBUSY: // 数据交互繁忙 + case hNORESPONSE: // 数据申请无响应 + // 操作用户 + ptrProHead->ummid = mmid; + + // 功能码 + ptrProHead->uFuncCode = ResponseType; + + // 保留位 + mmimsg.MsgLen = sizeof(PROTECTCONTENTHEAD); + break; + } + + if(mmimsg.MsgLen > 0) + { + // 发送至本端口 + //SendDataToPort(commid, (char *)&mmimsg, sizeof(PROTECTMSGHEAD)+mmimsg.MsgLen); + FormatDataAndSend(commid, &mmimsg); + } +} + +// 将103规约格式转换成scada内部格式,发送到指定的端口 +BOOL ScadaProtectConvertToScadaFrameAndSend(int commid) +{ + // SendDataToPort(commid, (char *)&mmimsg, sizeof(PROTECTMSGHEAD)+mmimsg.MsgLen); + return TRUE; +} + +// 转换成103规约格式,发送到指定的端口 +BOOL ScadaProtectConvertTo103AndSend(int commid, PROTECTMSG *pmsg) +{ + PROTECTCONTENTHEAD *ptrProHead; + + ptrProHead = (PROTECTCONTENTHEAD *)pmsg->MsgData; + + switch(ptrProHead->uFuncCode) + { + // 读取定值 + case hREADFIX: + break; + + // 读取定值区号 + case hREADFIXNO: + break; + + // 读取保护模拟量 + case hREADPAI: + break; + + // 读取保护开关量 + case hREADPDI: + break; + + // 读取保护波形数据 + case hREADPWAVE: + break; + + // 读取指定故障报告 + case hQUERYFAULT: + break; + + // 读取指定的自检报告 + case hQUERYSELFCHECK: + break; + + // 修改保护定值 + case hWRITEALLFIX: + break; + + // 修改指定的保护定值 + case hWRITESPECIALFIX: + break; + + // 保护定值确认 + case hWRITEFIXACK: + break; + + // 保护定值不确认 + case hWRITEFIXNAK: + break; + + // 修改保护定值区 + case hWRITEFIXNO: + break; + + // 定值区修改确认 + case hWRITEFIXNOACK: + break; + + // 定值区修改不确认 + case hWRITEFIXNONAK: + break; + + // 保护信号复归 + case hRESETPROTECT: + break; + + // 单个装置对时 + case hCHECKTIME: + break; + + // 保护装置广播对时 + case hBROADCASTCHECKTIME: + break; + + // 保护操作取消 + case hCANCEL: + break; + } + + return TRUE; +} + +void ScadaProtectByPassData(int commid, SCADAPROTECTPORTPARAM *psPortParam, PROTECTMSG *pmsg) +{ + int mmid, port; + RTUMSG rtumsg; + PORTSTATUS sPortStatus; + PROTECTCONTENTHEAD *ptrProHead; + SCADAPROTECTPORTPARAM *pPortParam; + + pPortParam = psPortParam; + + ptrProHead = (PROTECTCONTENTHEAD *)pmsg->MsgData; + + port = pmsg->PortNumber; + mmid = 0; + + if(ptrProHead->uFuncCode == hCANCEL) + { + SendResponsetoMMI(commid, mmid, hREADDATAEND, pmsg); + sPortStatus.bPortIdle = TRUE; + sPortStatus.mmid = 0xFFFFFFFF; + sPortStatus.timeOut = 0; + SetProtectPortIdle(port, pPortParam, &sPortStatus); + return; + } + + if(GetProtectPortIdle(port, pPortParam, &sPortStatus) == FALSE) + { + return; + } + + // wen 2005.06.22 Debug + //DispPrtPortStatus(commid, pPortParam); + + if(sPortStatus.bPortIdle == FALSE) + { + // 数据交互繁忙 + SendResponsetoMMI(commid, mmid, hSYSTEMBUSY, pmsg); + return; + } + + if((sPortStatus.mmid != 0xffffffff) + && (mmid != (int)sPortStatus.mmid)) + { + // 数据交互繁忙 + SendResponsetoMMI(commid, mmid, hSYSTEMBUSY, pmsg); + return; + } + + rtumsg.MsgLen = sizeof(PROTECTMSGHEAD)+pmsg->MsgLen; + rtumsg.PortIdx = commid; + rtumsg.MsgType = MSGTYPE_BAOHU_SCADACMD; + memcpy(rtumsg.MsgData, (void *)pmsg, rtumsg.MsgLen); + //PutBaohuDataToPort(&rtumsg); + + SendProtectCmdToDev(port, &rtumsg); + + sPortStatus.bPortIdle = FALSE; + sPortStatus.mmid = mmid; + sPortStatus.timeOut = OPERPROTECTTIMEOUT*1000/TIMER_CNT; + SetProtectPortIdle(port, pPortParam, &sPortStatus); +} + +BOOL FormatDataAndSend(int commid, PROTECTMSG *pmsg) +{ + int iDataLen; + char buf[4096]; + + iDataLen = 6+sizeof(PROTECTMSGHEAD)+pmsg->MsgLen; + if(iDataLen > sizeof(buf)) + { + return FALSE; + } + + AllHostToNetByteSequence(pmsg); + + memcpy(buf, SyncWordEB, 6); + memcpy(buf+6, (void *)pmsg, iDataLen-6); + SendDataToPort(commid, buf, iDataLen); + + return TRUE; +} + +void MakeInteractionCmd(int commid, int sourcommid, u_32 ResponseFunc, PROTECTCONTENTHEAD *pSourHead, BOOL bBoardCast) +{ + PROTECTMSG msg; + pPROTECTCONTENTHEAD ptrProHead; +#ifdef _DEBUG_MSG_ + char szbuf[256]; +#endif + + msg.MsgLen = 0; + memset((void*)&msg, 0, sizeof(PROTECTMSG)); + msg.MsgType = fPFV_PROTECT_BYPASS_ACK; + msg.PortNumber = sourcommid; + + ptrProHead = (pPROTECTCONTENTHEAD)msg.MsgData; + // 广播命令 + if(bBoardCast == TRUE) + { + ptrProHead->ummid = 0xffffffff; + } + + ptrProHead->uFuncCode = ResponseFunc; + ptrProHead->uAddr = pSourHead->uAddr; + ptrProHead->ummid = pSourHead->ummid; + ptrProHead->cCPUNo = pSourHead->cCPUNo; + ptrProHead->cFixNo = pSourHead->cFixNo; + ptrProHead->uReserved = 0; + + switch(ResponseFunc) + { + case hREADINGDATA: // 数据申请中 + case hPWAVEDATASTART: // 保护波行数据上送开始 + case hREADDATAEND: // 数据申请结束 + case hPWAVEDATAEND: // 保护波行数据上送结束 + case hWRITEFIXNAK: // 保护定值不确认 + case hWRITEFIXNONAK: // 定值区修改不确认 + case hNORESPONSE: // 数据申请无响应 + msg.MsgLen = sizeof(PROTECTCONTENTHEAD); + break; + default: +#ifdef _DEBUG_MSG_ + sprintf(szbuf, "端口%d 保护应答无效的功能码=%d!!!\n", commid, ResponseFunc); + DebugPrint(szbuf); +#endif + break; + } + + if(msg.MsgLen > 0) + { + // 发送至本端口 + //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); + FormatDataAndSend(commid, &msg); + } +} + +void MakeNetActivePacket(int commid) +{ + PROTECTMSG msg; + + msg.PortNumber = commid; + msg.MsgType = fPFV_NETACTIVE; + msg.MsgLen = 0; + + //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); + FormatDataAndSend(commid, &msg); +} + +void MakeStatusPacket(int commid) +{ + u_32 *puData; + PROTECTMSG msg; + + msg.PortNumber = commid; + msg.MsgType = fPFV_STATUS; + puData = (u_32 *)msg.MsgData; + + *puData = 1; + //SequenceHostToNet((char *)puData, sizeof(u_32)); + *(puData+1) = 0; + //SequenceHostToNet((char *)(puData+1), sizeof(u_32)); + msg.MsgLen = sizeof(u_32) * 2; + + //SendDataToPort(commid, (char *)&msg, sizeof(PROTECTMSGHEAD)+msg.MsgLen); + FormatDataAndSend(commid, &msg); +} + +BOOL MakeSoeDataPacket(int commid) +{ + WORD *pwValue; + u_32 *puValue; + int iDevNo, iOffset; + SOE_DEF sSoeData; + char szExtend[128]; + PROTECTMSG msg; + PROTECTCONTENTHEAD *pProHead; + SCADAPROTECTPORTPARAM *pPortParam; + + pPortParam = (SCADAPROTECTPORTPARAM *)SioParam[commid].ExtInfo; + + msg.MsgType = fPFV_PROTECT_BYPASS_ACK; + + ProvAndDelGetSoeData(commid, &sSoeData); + + iDevNo = FindProtectDevFromPntNoScada(pPortParam, sSoeData.iPntNo, DI_PNT_TYPE); + + // Debug + //printf("commid=%d sSoeData.iPntNo=%d, iDevNo=%d\n", commid, sSoeData.iPntNo, iDevNo); + + if(iDevNo >= 0) + { + msg.PortNumber = pPortParam->m_psProvDev[iDevNo].m_iRealCommid-1; + pProHead = (PROTECTCONTENTHEAD *)msg.MsgData; + pProHead->ummid = 0xFFFFFFFF; + pProHead->uAddr = pPortParam->m_psProvDev[iDevNo].m_iProvAddr; + pProHead->cCPUNo = (char)0xFF; + pProHead->cFixNo = (char)0xFF; + pProHead->uFuncCode = hPEVENTDATAWITHID; + pProHead->uReserved = 0; + iOffset = sizeof(PROTECTCONTENTHEAD); + pwValue = (WORD *)&msg.MsgData[iOffset]; + *pwValue = sSoeData.SoeTime.Year; + *(pwValue+1) = sSoeData.SoeTime.Month; + *(pwValue+2) = sSoeData.SoeTime.Day; + *(pwValue+3) = sSoeData.SoeTime.Hour; + *(pwValue+4) = sSoeData.SoeTime.Min; + *(pwValue+5) = sSoeData.SoeTime.Sec; + iOffset += sizeof(WORD)*6; + puValue = (u_32 *)&msg.MsgData[iOffset]; + *puValue = sSoeData.SoeTime.mSec; + iOffset += sizeof(u_32); + pwValue = (WORD *)&msg.MsgData[iOffset]; + // 修改序号为fun+inf + //*pwValue = sSoeData.iPntNo - pPortParam->m_psProvDev[iDevNo].m_sYxInfo.m_iStartPntNo + 1; + *pwValue = (WORD)(((sSoeData.u8ProvFun<<8) + sSoeData.u8ProvInf) & 0x0000FFFF); + if((*pwValue) == 0) + { + *pwValue = sSoeData.iPntNo - pPortParam->m_psProvDev[iDevNo].m_sYxInfo.m_iStartPntNo + 1; + } + + iOffset += sizeof(WORD); + + // <<< 修改 + // 含有故障序号和相对时间 + //if(sSoeData.u8Type == 2) + //{ + // sprintf(szExtend, "<相对时间[%d],故障序号[%d]>", sSoeData.wRelativeTime, sSoeData.wFaultNo); + // msg.MsgData[iOffset] = strlen(szExtend); + // memcpy((void *)&msg.MsgData[iOffset+1], szExtend, msg.MsgData[iOffset]); + // iOffset += msg.MsgData[iOffset]+1; + //} + //else + //{ + // msg.MsgData[iOffset++] = 0; + //} + + if(sSoeData.bStatus == 1) + { + strcpy(szExtend, "动作"); + } + else + { + strcpy(szExtend, "恢复"); + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.10.25 增加扩充字符串,用来解析保护事件中的故障参数 + // 含有故障序号和相对时间 + //if(sSoeData.u8Type == 2) + //{ + // sprintf(szExtend, "%s <相对时间[%d],故障序号[%d]>", szExtend, sSoeData.wRelativeTime, sSoeData.wFaultNo); + //} + if(sSoeData.u8Type == 2) + { + sprintf(szExtend, "%s <相对时间[%d],故障序号[%d]>", szExtend, sSoeData.wRelativeTime, sSoeData.wFaultNo); + } + else if(sSoeData.u8Type == 3) + { + sprintf(szExtend, "%s <%s>", szExtend, sSoeData.szMsgEx); + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + msg.MsgData[iOffset] = strlen(szExtend); + memcpy((void *)&msg.MsgData[iOffset+1], szExtend, msg.MsgData[iOffset]); + iOffset += msg.MsgData[iOffset]+1; + // >>> 完成 + + msg.MsgLen = iOffset; + FormatDataAndSend(commid, &msg); + //发送soe数据 + return TRUE; + } + + return FALSE; +} +//===========================数据处理函数结束========================= + +//===========================调试函数开始========================= +void DispPrtPortStatus(int commid, SCADAPROTECTPORTPARAM *psPortParam) +{ + int i, iMaxPort; + char szDbg[128]; + + iMaxPort = GetMaxPort(); + sprintf(szDbg, ">>>commid=%d, MaxPort=%d, PrtPortStatus:", commid, iMaxPort); + DebugPrint(szDbg); + for(i=0; im_pPrtPortStatus[i].bPortIdle, + psPortParam->m_pPrtPortStatus[i].mmid, + psPortParam->m_pPrtPortStatus[i].timeOut); + DebugPrint(szDbg); + } + strcpy(szDbg, "<<FEND) +*/ +#define pPFV_PROTECT_BYPASS 1 +/*! + 保护数据包应答(FEND->PROTECT) +*/ +#define fPFV_PROTECT_BYPASS_ACK 2 +/*! + 通道状态包(FEND->PROTECT) +*/ +#define fPFV_STATUS 3 +/*! + 网络活动包(FEND<->PROTECT) +*/ +#define fPFV_NETACTIVE 0xF0 + +//指令包操作码 +/*! + 读取定值 +*/ +#define hREADFIX 0x01 +/*! + 读取定值区号 +*/ +#define hREADFIXNO 0x07 +/*! + 读取保护模拟量 +*/ +#define hREADPAI 0x09 +/*! + 读取保护开关量 +*/ +#define hREADPDI 0x0b +/*! + 读取保护波形数据 +*/ +#define hREADPWAVE 0x0d +/*! + 读取指定故障报告 +*/ +#define hQUERYFAULT 0x11 +/*! + 读取指定的自检报告 +*/ +#define hQUERYSELFCHECK 0x12 +/*! + 修改保护定值 +*/ +#define hWRITEALLFIX 0x15 +/*! + 修改指定的保护定值 +*/ +#define hWRITESPECIALFIX 0x16 +/*! + 保护定值确认 +*/ +#define hWRITEFIXACK 0x17 +/*! + 保护定值不确认 +*/ +#define hWRITEFIXNAK 0x18 +/*! + 修改保护定值区 +*/ +#define hWRITEFIXNO 0x19 +/*! + 定值区修改确认 +*/ +#define hWRITEFIXNOACK 0x1a +/*! + 定值区修改不确认 +*/ +#define hWRITEFIXNONAK 0x1b +/*! + 保护信号复归 +*/ +#define hRESETPROTECT 0x1c +/*! + 单个装置对时 +*/ +#define hCHECKTIME 0x1d +/*! + 保护装置广播对时 +*/ +#define hBROADCASTCHECKTIME 0x1e +/*! + 读取保护装置状态 +*/ +#define hSTATUS 0x1f +/*! + 读取菜单单元值 +*/ +#define hCOMMAND 0x20 +/*! + 读取扰动参数的命令 +*/ +#define hDISTCOMMAND 0x21 +/*! + 保护操作取消 +*/ +#define hCANCEL 0xFF + +//应答包操作码 +/*! + 数据申请中 +*/ +#define hREADINGDATA 0x02 +/*! + 定值数据 +*/ +#define hFIXDATA 0x03 +/*! + 数据申请结束 +*/ +#define hREADDATAEND 0x04 +/*! + 数据申请无响应 +*/ +#define hNORESPONSE 0x05 +/*! + 数据处理繁忙,稍后重试 +*/ +#define hSYSTEMBUSY 0x06 +/*! + 定值区号数据 +*/ +#define hFIXNODATA 0x08 +/*! + 保护模拟量数据 +*/ +#define hPAIDATA 0x0a +/*! + 保护开关量数据 +*/ +#define hPDIDATA 0x0c +/*! + 保护波行数据上送开始 +*/ +#define hPWAVEDATASTART 0x0e +/*! + 保护波行数据 +*/ +#define hPWAVEDATA 0x0f +/*! + 保护波行数据上送结束 +*/ +#define hPWAVEDATAEND 0x10 +/*! + 带索引号的事件报告数据 +*/ +#define hPEVENTDATAWITHID 0x13 +/*! + 字符串事件报告数据 +*/ +#define hPEVENTDATAWITHSTRING 0x14 +/*! + 保护定值确认 +*/ +#define hWRITEFIXACK 0x17 +/*! + 保护定值不确认 +*/ +#define hWRITEFIXNAK 0x18 +/*! + 定值区修改确认 +*/ +#define hWRITEFIXNOACK 0x1a +/*! + 定值区修改不确认 +*/ +#define hWRITEFIXNONAK 0x1b +/*! + 定值数据带序号 +*/ +#define hFIXDATAWITHNO 0x22 +/*! + 保护模拟量数据带序号 +*/ +#define hPAIDATAWITHNO 0x23 +/*! + 保护开关量数据带序号 +*/ +#define hPDIDATAWITHNO 0x24 + +// 数据项目属性 +/*! + 实际值 +*/ +#define ITEM_ATTR_REALVALUE 1 +/*! + 缺省值 +*/ +#define ITEM_ATTR_DEFAULTVALUE 2 +/*! + 量 程 +*/ +#define ITEM_ATTR_MINMAXSTEP 3 +/*! + 备 用 +*/ +#define ITEM_ATTR_STANDBY 4 +/*! + 精 度 +*/ +#define ITEM_ATTR_PRECISION 5 +/*! + 因 子 +*/ +#define ITEM_ATTR_FIGURE 6 +/*! + 参 比 +*/ +#define ITEM_ATTR_RATE 7 +/*! + 列 表 +*/ +#define ITEM_ATTR_LIST 8 +/*! + 量 纲 +*/ +#define ITEM_ATTR_UNIT 9 +/*! + 描 述 +*/ +#define ITEM_ATTR_DESCRIPTION 10 + +/*! + 保护操作超时时间(秒) +*/ +#define OPERPROTECTTIMEOUT 15 + +// 是pc机系统还是嵌入式系统 +#ifdef PC_MACHINE +#ifdef OS_WINDOWS + #pragma pack (push,1) +#else// OS_UNIX + #pragma pack(1) +#endif //OS_UNIX +#endif + +typedef struct tagPROTECTCONTENTHEAD +{ + u_32 ummid __attribute__ ((packed));// 操作用户 + u_32 uAddr __attribute__ ((packed));// 保护地址 + char cFixNo __attribute__ ((packed));// 定值区号 + char cCPUNo __attribute__ ((packed));// CPU号 + u_32 uFuncCode __attribute__ ((packed));// 操作功能码 + u_32 uReserved __attribute__ ((packed));// 保留 +}PROTECTCONTENTHEAD, *pPROTECTCONTENTHEAD; + +typedef struct +{ + u_32 MsgType __attribute__ ((packed));// 信息类型 + u_32 PortNumber __attribute__ ((packed));// 信息端口号 + u_32 MsgLen __attribute__ ((packed));// 信息长度 + //u_char MsgData[1]; // 信息数据 +}PROTECTMSGHEAD; + +typedef struct +{ + u_32 MsgType __attribute__ ((packed));// 信息类型 + u_32 PortNumber __attribute__ ((packed));// 信息端口号 + u_32 MsgLen __attribute__ ((packed));// 信息长度 + u_char MsgData[MAX_RTU_MSG_SIZE] __attribute__ ((packed));// 信息数据 +}PROTECTMSG; + +// 是pc机系统还是嵌入式系统 +#ifdef PC_MACHINE +#ifdef OS_WINDOWS + #pragma pack (pop) +#else// OS_UNIX + #pragma pack (0) +#endif //OS_UNIX +#endif + +typedef struct +{ + BOOL bPortIdle; // 端口保护操作空闲标识 + u_32 timeOut; // 保护操作超时时间 + u_32 mmid; // 保护操作用户 +} PORTSTATUS, *pPORTSTATUS; + +typedef struct tagSCADAPROVDEVDEF +{ + /*! + \brief 装置的实际端口号 + */ + i_32 m_iRealCommid; + /*! + \brief 装置的转发地址(唯一确定一个装置) + */ + i_32 m_iProvAddr; + /*! + \brief 转发SOE数据参数 + \note + 用于历史记录的转发事件(应该是没有作用,已经遗弃) + */ + DEVPROVSOE m_sProvSoe; + + i_32 m_iStatusStn; + i_32 m_iStatusPnt; + + DBORIENTATION m_sYxInfo; +}SCADAPROVDEVDEF; + +typedef struct tagSCADAPROTECTPORTPARAM +{ + /*! + \var SCADAPROTECTPORTPARAM::m_achRecvBuf + \brief 接收数据缓冲区 + \note + 缓冲区最大不超过 MAX_RTU_MSG_SIZE+12(包头) bytes\n + */ + char m_achRecvBuf[MAX_RTU_MSG_SIZE+12]; + + /*! + \var SCADAPROTECTPORTPARAM::m_iRecvLen + \brief 接收数据长度 + */ + int m_iRecvLen; + + /*! + \var SCADAPROTECTPORTPARAM::m_iRecvLen + \brief 网络活动包的发送时间 + */ + int m_iActiveTimeCnt; + int m_iActiveTimeConst; + + /*! + \var SCADAPROTECTPORTPARAM::m_iRecvLen + \brief 通道状态包的发送时间 + */ + int m_iStatusTimeCnt; + int m_iStatusTimeConst; + + /*! + 保护装置数量 + */ + i_32 m_iDevNum; + + SCADAPROVDEVDEF *m_psProvDev; + + SINGLELIST m_sBaoHuData; + + char m_chArrayTempletFileName[256]; + + PORTSTATUS *m_pPrtPortStatus; + /*! + \brief 该规约的端口数据指针 + */ + SIO_PARAM_BAOHU_DEF *m_psBaoHu; +}SCADAPROTECTPORTPARAM, *pSCADAPROTECTPORTPARAM; + +/////////////////////////以下为通用函数接口/////////////////////////// +/*! + \brief 读取配置函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void ScadaProtectReadConfig(int commid); // 初始化处理 +/*! + \brief 读取端口数据函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void ScadaProtectRecvData(int commid, u_char *buf, int len);// 规约读数据处理 +/*! + \brief 规约数据处理定时器函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void ScadaProtectTimer(int commid); // 定时器处理 +/*! + \brief 遥控遥调数据处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + \param buf -- 数据源缓冲区指针 + \param len -- 数据源长度 + */ +void ScadaProtectYkYtProcess(int commid, u_char *buf, int len); // 遥控遥调处理 +/*! + \brief 系统下发对时函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +//void ScadaProtectSendSystemTime(int commid); // 系统对时 +/*! + \brief 系统退出时规约处理函数 + \param commid -- 端口号 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void ScadaProtectExit(int commid); // 规约退出 +/*! + \brief 保护命令处理函数 + \param commid -- 端口号 + \param rtumsg -- 下发的保护命令指针 + \note + 取值范围:0 -- MaxSerialPortNum + MaxNetPortNum -1\n + */ +void ScadaProtectBaoHuCmdProcess(int commid, RTUMSG *rtumsg, BOOL bUpData); +/*! + \brief 取保护数据库指针函数 + \param commid -- 端口号 + \param iProvAddr -- 统一编排的保护转发地址 + \param ppBaoHuDB -- 存放保护数据指针的指针 + \retval -- 返回该装置保护数据组数 + */ +int ScadaProtectGetBaohuDataBase(int commid, int iProvAddr, GROUPDEF **ppBaoHuDB); +/////////////////////////通用函数接口结束/////////////////////////////// + +/////////////////////////以下为通用函数支持接口///////////////////////// +void ScadaProtectProvMakeYkYtCommand(int commid, u_char *buf, int len); +/////////////////////////通用函数支持接口结束/////////////////////////// + +///////////////////////////以下为配置函数接口/////////////////////////// +BOOL InitScadaInfoFromTempletFile(int commid, SCADAPROTECTPORTPARAM *psPortParam,\ + char *ptrTemplate, BOOL bMaster); +BOOL GetProvDevNumFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam); +BOOL GetProvDevParamFromTemplateFileScada(int commid, HDSFILE hFile, SCADAPROTECTPORTPARAM *psPortParam); +int FindProtectDevFromPntNoScada(SCADAPROTECTPORTPARAM *psPortParam, int iPntNo, int itype); +/////////////////////////////配置函数接口结束/////////////////////////// + +///////////////////////以下为规约处理函数接口/////////////////////////// +void ReduceTimeOut(SCADAPROTECTPORTPARAM *psPortParam); +BOOL IsProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam); +BOOL GetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus); +BOOL SetProtectPortIdle(int commid, SCADAPROTECTPORTPARAM *psPortParam, PORTSTATUS *pStatus); +BOOL SetProtectPortIdleEx(int commid, int iBaoHuCommid, PORTSTATUS *pStatus); +void SendResponsetoMMI(int commid, int mmid, u_32 ResponseType, PROTECTMSG *pmsg); +//将客户机报文所有的数据从网络字节循序转换成主机字节顺序函数 +void AllNetToHostByteSequence(PROTECTMSG *userdata); +//将客户机报文所有的数据从主机字节顺序转换成网络字节顺序函数 +void AllHostToNetByteSequence(PROTECTMSG *userdata); +BOOL ScadaProtectConvertToScadaFrameAndSend(int commid); +BOOL ScadaProtectConvertTo103AndSend(int commid, PROTECTMSG *pmsg); +//数据处理函数总入口 +void ScadaProtectProcessData(int commid, SCADAPROTECTPORTPARAM *psPortParam, BOOL bProcess); + +void ScadaProtectByPassData(int commid, SCADAPROTECTPORTPARAM *psPortParam, PROTECTMSG *pmsg); +BOOL FormatDataAndSend(int commid, PROTECTMSG *pmsg); +void MakeInteractionCmd(int commid, int sourcommid, u_32 ResponseFunc, PROTECTCONTENTHEAD *pSourHead, BOOL bBoardCast); +void MakeNetActivePacket(int commid); +void MakeStatusPacket(int commid); +BOOL MakeSoeDataPacket(int commid); +/////////////////////////规约处理函数接口结束/////////////////////////// + +/////////////////////////以下为调试函数接口///////////////////////////// +void DispPrtPortStatus(int commid, SCADAPROTECTPORTPARAM *psPortParam); +///////////////////////////调试函数接口结束///////////////////////////// +#endif // !defined(_SCADABAOHU_H_200506020948__INCLUDED_) diff --git a/tcphost.cpp b/tcphost.cpp new file mode 100644 index 0000000..4233fb2 --- /dev/null +++ b/tcphost.cpp @@ -0,0 +1,3218 @@ +/************************************************************************************ + * + * Copyright (C) 2002-2003 SCADA Control Technology Co., Ltd. All rights reserved. + * + * $Source: /opt/CVS_ROOT_PGC_EX2000/commserver/windows/widgets/tcphost.cpp,v $ + * + * $Author: zhuzhenhua $ + * + * $Date: 2006/08/07 03:16:49 $ + * + * $Revision: 1.3 $ + * + * $State: Exp $ + * + * $Name: $ + * + * $Locker: $ + * + * $Log: tcphost.cpp,v $ + * Revision 1.3 2006/08/07 03:16:49 zhuzhenhua + * no message + * + * Revision 1.2 2006/07/31 07:18:24 huyizhong + * no message + * + * Revision 1.1.1.1 2006/07/05 07:31:44 jehu + * no message + * + * Revision 1.12 2006/06/16 06:17:41 administrator + * 修改变位遥信点号为word类型而不是dword类型的bug + * + * Revision 1.11 2006/05/26 10:38:03 administrator + * 增加32位模拟量传送 + * + * Revision 1.10 2006/04/30 07:25:51 administrator + * 不连接服务器,也可以做主备运转 + * + * Revision 1.9 2006/04/28 06:28:59 administrator + * no message + * + * Revision 1.8 2006/04/26 05:59:27 administrator + * 如果为并列运行方式下,所以装置都是下发机 + * + * Revision 1.7 2006/04/22 07:48:22 administrator + * 可以屏蔽网络连接的错误信息,支持端口通讯时不切换主备机及网络连接成功的算法 + * + * Revision 1.6 2006/01/19 09:53:57 Administrator + * bug修正 + * + * Revision 1.5 2006/01/17 06:14:44 Administrator + * 增加对时、装置并列运行以及端口号偏移 + * + * Revision 1.4 2005/11/30 09:49:29 Administrator + * 厦门出差时的修改 + * + * Revision 1.3 2005/11/18 03:49:23 Administrator + * 增加施耐德modbus规约 + * + * Revision 1.2 2005/10/20 06:55:46 Administrator + * 新增前置机功能 + * + * Revision 1.1 2005/10/12 06:03:45 Administrator + * 增加前置机功能 + * + * + **************************************************************************************/ +//*************************************************************** +//* tcphost.cpp * +//* Liangchu Lee 1999.12.20 * +//*************************************************************** +#include "commport.h" +#include "tcphost.h" +#include "basetype.h" + +extern HOST_IP_ADDR HostIpAddr; +extern char IniFilePath[256]; + +BYTE SyncHead[6] = {0xeb, 0x90, 0xeb, 0x90, 0xeb, 0x90}; + +int SystemTimeFlag; +int SystemTimeMode; + +// 暂时不进行配置,在需要模拟盘接入时,在打开该接口 +int gMapOutputPort=0; // 模拟盘输出端口 +int gMapSaveDataPort=0; // 模拟盘请求数据缓冲端口 + +//int SystemLoginFalg; + +TCP_LINK_DEF HostLink[MAX_HOST]; +TCP_RCV_DATA_BUF HostRevBuf[MAX_HOST]; +TCP_SEND_DATA_BUF HostSendBuf[MAX_HOST]; + +FEND_DEF FendMsg; + +int Host_Socket_Port; + +int HostWSAStartupErr = FALSE; + +HOSTMSG gRtuChangeMsg[RTUCHANGMSGNUM]; +BOOL GetConfigName(char *szFileName, int iFileNameLen, int IsPortConfig) +{ +#ifdef OS_LINUX + if(IsPortConfig) + { + strcpy(szFileName, "portconfig.ini"); + } + else + { + strcpy(szFileName, "config.ini"); + } +#else + //GetCurrentDirectory(sizeof(szDir), szDir); + if(IsPortConfig) + { + sprintf(szFileName, "%s/portconfig.ini", IniFilePath); + } + else + { + sprintf(szFileName, "%s/config.ini", IniFilePath); + } +#endif + + return TRUE; +} + +BOOL IsWouldBlock() +{ + BOOL bRetVal; + + bRetVal = FALSE; +#ifdef OS_LINUX + if(EINPROGRESS == errno) + { + bRetVal = TRUE; + } +#else + if(WSAEWOULDBLOCK == WSAGetLastError()) + { + bRetVal = TRUE; + } +#endif + + return bRetVal; +} + +BOOL IsWouldBlockEx(int neterrno) +{ + BOOL bRetVal; + + bRetVal = FALSE; +#ifdef OS_LINUX + if(EINPROGRESS == neterrno) + { + bRetVal = TRUE; + } +#else + if(WSAEWOULDBLOCK == neterrno) + { + bRetVal = TRUE; + } +#endif + + return bRetVal; +} + +int GetNetErrorNo() +{ +#ifdef OS_LINUX + return errno; +#else + return WSAGetLastError(); +#endif +} + +void CloseNetSocket(SOCKET sock) +{ +#ifdef OS_LINUX + close(sock); +#else + closesocket(sock); +#endif +} + +void ULongToIPString(char *ipstr, u_long ipulong) +{ + struct sockaddr_in server; + + ipstr[0] = 0; + if(ipulong == 0) + { + return; + } + +#ifdef OS_LINUX + server.sin_addr.s_addr = ipulong; +#else + SwapByteSequence((char *)&ipulong, sizeof(u_long)); + server.sin_addr.s_addr = ipulong; +#endif + strcpy(ipstr, inet_ntoa(server.sin_addr)); + + DebugPrint(ipstr); +} + +void MakeNetNameplateMsgToHost(HOSTMSG *rtumsg) +{ + rtumsg->MsgType = iNETNAMEPLATE; + rtumsg->PortNumber = 0; + rtumsg->MsgLen = 3; + rtumsg->MsgData[0] = FEND_TYPE; + + *(short*)&rtumsg->MsgData[1] = (short)FendMsg.FendIdx; +} + +void SendNetNameplateMsgToHost(int flag) +{ + static int timecnt = 0; + HOSTMSG rtumsg; + int i; + + timecnt++; + if((timecnt == (3000/TIMER_CNT)) || flag) + { + timecnt = 0; + MakeNetNameplateMsgToHost(&rtumsg); + + for(i = 0; i < MAX_HOST; i++) + { + SendDataToHostSendBuf(i, (u_char*)&rtumsg, rtumsg.MsgLen+sizeof(HOSTMSGHEAD), flag); + } + } +} + +void SendNetActiveMsgToHost(void) +{ + static int timecnt = 0; + HOSTMSG rtumsg; + int i; + + timecnt++; + if(timecnt >= (1000/TIMER_CNT)) + { + timecnt = 0; + rtumsg.MsgType = iNETTESTMSG; + rtumsg.PortNumber = 0; + rtumsg.MsgLen = 0; + + for(i = 0; i < MAX_HOST; i++) + { + SendDataToHostSendBuf(i, (u_char*)&rtumsg, rtumsg.MsgLen+sizeof(HOSTMSGHEAD), FALSE); + } + } + SendNetNameplateMsgToHost(FALSE); +} + +void InitSetTcpIpAddr(void) +{ + int i; + char ipaddr[4][32], ipaddrmask[4][32]; + char szbuf[256], InitFileName[256]; + + GetConfigName(InitFileName, sizeof(InitFileName), 0); + + GetPrivateProString("前置机", "前置机A地址1", "", ipaddr[0], 30, InitFileName); + GetPrivateProString("前置机", "前置机A地址2", "", ipaddr[1], 30, InitFileName); + GetPrivateProString("前置机", "前置机B地址1", "", ipaddr[2], 30, InitFileName); + GetPrivateProString("前置机", "前置机B地址2", "", ipaddr[3], 30, InitFileName); + + GetPrivateProString("前置机", "前置机A地址1掩码", "", ipaddrmask[0], 30, InitFileName); + GetPrivateProString("前置机", "前置机A地址2掩码", "", ipaddrmask[1], 30, InitFileName); + GetPrivateProString("前置机", "前置机B地址1掩码", "", ipaddrmask[2], 30, InitFileName); + GetPrivateProString("前置机", "前置机B地址2掩码", "", ipaddrmask[3], 30, InitFileName); + + //DebugPrint("InitSetTcpIpAddr Begin..."); + for(i = 0; i < 4; i++) + { + FendMsg.SetTcpIpAddr[i][0] = 0x00; + if(strlen((char*)ipaddr[i]) == 0) + { + continue; + } + + if(CheckTcpIpAddr((char*)ipaddr[i]) == FALSE) + { + sprintf(szbuf, "前置机%C地址%d = %s 错误!!!", + (i < 2) ? 'A' : 'B', (i % 2) + 1, ipaddr[i]); + DebugPrint(szbuf); + } + else + { + strcpy((char*)FendMsg.SetTcpIpAddr[i], (char*)ipaddr[i]); + } + + //DebugPrint(FendMsg.SetTcpIpAddr[i]); + } + + //DebugPrint("InitSetTcpIpAddr End."); + + //SystemTimeFlag = GetPrivateProInt("对时", "对时", 1, InitFileName); + SystemTimeMode = GetPrivateProInt("对时", "对时方式", 1, InitFileName); + if(SystemTimeMode == 0) + { + SystemTimeFlag = 0; + } + else + { + SystemTimeFlag = 1; + } +} + +int FindFendIdx(void) +{ + int i, retval; + + retval = -1; + for(i = 0; i < MAX_ADDR; i++) + { + if(strlen(FendMsg.TcpIpAddr[i]) == 0) + { + continue; + } + + if(CmpString2(FendMsg.TcpIpAddr[i], FendMsg.SetTcpIpAddr[0]) + || CmpString2(FendMsg.TcpIpAddr[i], FendMsg.SetTcpIpAddr[1])) + { + retval = 0; + break; + } + + if(CmpString2(FendMsg.TcpIpAddr[i], FendMsg.SetTcpIpAddr[2]) + || CmpString2(FendMsg.TcpIpAddr[i], FendMsg.SetTcpIpAddr[3])) + { + retval = 1; + break; + } + } + return retval; +} + +void FindCurrentFend(void) +{ + FendMsg.FendIdx = FindFendIdx(); + if(FendMsg.FendIdx < 0) + { + if(CmpString2(FendMsg.Name, "HOSTA") || CmpString2(FendMsg.Name, "FENDA")) + { + FendMsg.FendIdx = 0; + } + else if(CmpString2(FendMsg.Name, "HOSTB") || CmpString2(FendMsg.Name, "FENDB")) + { + FendMsg.FendIdx = 1; + } + else + { + FendMsg.FendIdx = (FendMsg.Name[strlen(FendMsg.Name)-1] - 'A') ? 1 : 0; // 0 -- a, 1 -- b + } + } +} + +BOOL InitFendMsgEx(void) +{ + int i, j; + struct hostent *test; + char InitFileName[256]; + + GetConfigName(InitFileName, sizeof(InitFileName), 0); + + for(j = 0; j < MAX_FEND; j++) + { + FendMsg.FendExistFlag[j] = FALSE; + FendMsg.FendExistCnt[j] = 0; + FendMsg.LinkStatus[j] = FALSE; + FendMsg.LinkCnt[j] = 0; + FendMsg.SendTxdDataFlag[j] = FALSE; + } + for(j = 0; j < MAX_ADDR; j++) + { + FendMsg.AllIpAddr[j] = 0; + FendMsg.HostIpAddr[j] = 0; + FendMsg.BroadCastAddr[j] = 0; + } + + InitSetTcpIpAddr(); + + FendMsg.EnableLink = GetPrivateProInt("前置机", "允许前置机连接", 1, InitFileName); + FendMsg.EnableLink = FendMsg.EnableLink ? 1 : 0; + + FendMsg.LinkFlag = GetPrivateProInt("前置机", "前置机连接", 2, InitFileName) % 3; + FendMsg.LinkFlag = 2; + + // wen 2006.01.14 增加装置的起始厂站号的偏移 + FendMsg.iPortOffset = GetPrivateProInt("前置机", "起始厂站号", 0, InitFileName); + if(FendMsg.iPortOffset < 0) + { + FendMsg.iPortOffset = 0; + } + // wen 2006.01.14 增加并列运行方式 + FendMsg.iRunMode = GetPrivateProInt("前置机", "运行方式", 0, InitFileName) % 2; + if(FendMsg.iRunMode < 0) + { + FendMsg.iRunMode = RUN_MODE_STANDBY; + } + + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + FendMsg.iPortMask = GetPrivateProInt("前置机", "主备切换端口屏蔽字", 0, InitFileName); + + // wen 2006.05.20 32bit传送模拟量数据 + FendMsg.iSendAiof32Bit = GetPrivateProInt("前置机", "遥测数据32位传送", 0, InitFileName); + if(FendMsg.iSendAiof32Bit > 0) + { + FendMsg.iSendAiof32Bit = 1; + } + else + { + FendMsg.iSendAiof32Bit = 0; + } + + gethostname(FendMsg.Name, 100); + test = gethostbyname(FendMsg.Name); + + for(i=0, j=0; (ih_addr_list[i]; + if(addr == NULL) + { + break; + } + + inaddr = *((struct in_addr *)test->h_addr_list[i]); + + // 判断是否前置机IP地址(针对于ds-3116的3地址的情况) + if(false == CheckIsFendIpAddr(ntohl(inaddr.s_addr))) + { + continue; + } + + strcpy(FendMsg.TcpIpAddr[i], inet_ntoa(*addr)); + FendMsg.AllIpAddr[i] = ntohl(inaddr.s_addr); + + if(IN_CLASSA(FendMsg.AllIpAddr[i])) //A类地址 + { + FendMsg.HostIpAddr[i] = FendMsg.AllIpAddr[i] & IN_CLASSA_NET; + FendMsg.BroadCastAddr[i] = FendMsg.HostIpAddr[i] | IN_CLASSA_HOST; + } + else if(IN_CLASSB(FendMsg.AllIpAddr[i])) //B类地址 + { + FendMsg.HostIpAddr[i] = FendMsg.AllIpAddr[i] & IN_CLASSB_NET; + FendMsg.BroadCastAddr[i] = FendMsg.HostIpAddr[i] | IN_CLASSB_HOST; + } + else if(IN_CLASSC(FendMsg.AllIpAddr[i])) //C类地址 + { + FendMsg.HostIpAddr[i] = FendMsg.AllIpAddr[i] & IN_CLASSC_NET; + FendMsg.BroadCastAddr[i] = FendMsg.HostIpAddr[i] | IN_CLASSC_HOST; + } + } + + for(i = 0; i < (int)strlen(FendMsg.Name); i++) + { + FendMsg.Name[i] = toupper(FendMsg.Name[i]); + } + + return TRUE; +} + +BOOL InitHostWSAStartup(void) +{ + int i, j; +#ifdef OS_WINDOWS + WSADATA WSAData; +#endif + char szbuf[256]; + static BOOL bInitFinished = FALSE; + char InitFileName[256]; + + GetConfigName(InitFileName, sizeof(InitFileName), 0); + + // wen 2002.08.01 初始化时,应该关闭网络在初始化 + if(bInitFinished) + { + CloseHost(); + } + else + { + bInitFinished = TRUE; + } + +#ifdef OS_WINDOWS + if(WSAStartup(MAKEWORD(2, 1), (LPWSADATA)&WSAData) != 0) + { + WSAGetLastError(); + HostWSAStartupErr = TRUE; + return FALSE; + } +#endif; + + //InitFendMsg(); + InitFendMsgEx(); + + for(i = 0; i < MAX_HOST; i++) + { + HostRevBuf[i].MsgCnt = 0; + HostRevBuf[i].Front = 0; + HostRevBuf[i].Rear = 0; + + HostSendBuf[i].MsgLen = 0; + + HostLink[i].InitOk = FALSE; + HostLink[i].InitFlag = FALSE; + + HostLink[i].ExistFlag = FALSE; + HostLink[i].CommFlag = FALSE; + HostLink[i].Status = 2; + HostLink[i].StatusCnt = 0; + + HostLink[i].VersionFalgByte = 0; + HostLink[i].RevHostStatusMsg = 0; + + HostLink[i].NetNameplateFalg = FALSE; + HostLink[i].SocketId = INVALID_SOCKET; + } + + Host_Socket_Port = GetPrivateProInt("网络设置", "主机网络端口", 7119, InitFileName); + GetPrivateProString("主机地址", "主机A地址1", "", (char*)HostLink[0].TcpIpAddr[0], 30, InitFileName); + GetPrivateProString("主机地址", "主机A地址2", "", (char*)HostLink[0].TcpIpAddr[1], 30, InitFileName); + GetPrivateProString("主机地址", "主机B地址1", "", (char*)HostLink[1].TcpIpAddr[0], 30, InitFileName); + GetPrivateProString("主机地址", "主机B地址2", "", (char*)HostLink[1].TcpIpAddr[1], 30, InitFileName); + + for(i=0, j=0; i < 4; i++) + { + if(strlen((char*)HostLink[i/2].TcpIpAddr[i%2]) == 0) + { + continue; + } + + if(CheckTcpIpAddr((char*)HostLink[i/2].TcpIpAddr[i%2]) == FALSE) + { + sprintf(szbuf, "主机%c地址%d = %s 错误!!!", + ((i < 2) ? 'A' : 'B'), ((i % 2) + 1), HostLink[i/2].TcpIpAddr[i%2]); + DebugPrint(szbuf); + + //sprintf(szbuf, "i=%d, j=%d", i, j); + //DebugPrint(szbuf); + continue; + } + j++; + } + FendMsg.EnableLink = (j) ? FendMsg.EnableLink : 0; + + FindCurrentFend(); + + HostWSAStartupErr = FALSE; + return TRUE; +} + +void LinkOneHost(int hostid) +{ + struct sockaddr_in sa; + int retval, len, tmp_len; + char tmp_buf[256]; + u_long largp = 1L; //非阻塞模式 + + /* + if((!SystemLoginFalg) && RESTRICTED_USER) + { + return; + } + */ + + // wen 2002.01.24 + //if(HostLink[hostid].Status == 2) return; + + if(HostLink[hostid].InitOk == TRUE) + { + return; + } + + if(HostLink[hostid].InitFlag == TRUE) + { + return; + } + + if(CheckTcpIpAddr((char*)HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx]) == FALSE) + { + HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx][0] = 0x00; + + if(CheckTcpIpAddr((char*)HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx ? 0 : 1])) + HostLink[hostid].CurLinkIdx = HostLink[hostid].CurLinkIdx ? 0 : 1; + + return; + } + + HostLink[hostid].InitLinkCnt++; + + HostLink[hostid].InitLinkCnt = 0; + + HostLink[hostid].InitFlag = TRUE; + + if((HostLink[hostid].SocketId = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + { +#ifdef OS_LINUX + retval = errno; +#else + retval = WSAGetLastError(); +#endif + + HostLink[hostid].InitFlag = FALSE; + HostLink[hostid].InitOk = FALSE; + return; + } + +#ifdef OS_LINUX + // wen 2005.07.08 将socket设置为非阻塞模式 + retval = fcntl(HostLink[hostid].SocketId, F_GETFL, 0); + fcntl(HostLink[hostid].SocketId, F_SETFL, retval|O_NONBLOCK); +#else + retval = ioctlsocket(HostLink[hostid].SocketId, FIONBIO, (u_long FAR *)&largp); + if(SOCKET_ERROR == retval) + { + retval = WSAGetLastError(); + sprintf(tmp_buf, "wen: ioctlsocket设置非阻塞模式错误, SocketError=%d, SocketId = %d", retval, HostLink[hostid].SocketId); + DebugPrint(tmp_buf); + return; + } +#endif + + if(ShmGetDispHostLinkFlag()) + { + sprintf(tmp_buf, "【socket=%d】前置机连接主机%c(%s:%d)!!!", HostLink[hostid].SocketId, + hostid+'A', (char *)HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx], Host_Socket_Port); + DebugPrint((char*)tmp_buf); + } + + retval = MAX_NET_BUF; + len = sizeof(retval); + setsockopt(HostLink[hostid].SocketId, SOL_SOCKET, SO_RCVBUF, (char*)&retval, len); + setsockopt(HostLink[hostid].SocketId, SOL_SOCKET, SO_SNDBUF, (char*)&retval, len); + + len = 4; + tmp_buf[0] = 1; + + retval = setsockopt(HostLink[hostid].SocketId, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, len); + retval = getsockopt(HostLink[hostid].SocketId, SOL_SOCKET, SO_KEEPALIVE, tmp_buf, &len); + + tmp_len = 1; + retval = setsockopt(HostLink[hostid].SocketId, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp_len, len); + + memset((char *)&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons((WORD)Host_Socket_Port); + sa.sin_family = PF_INET; + sa.sin_addr.s_addr = inet_addr((char*)HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx]); + + retval = connect((SOCKET)HostLink[hostid].SocketId, (struct sockaddr *)&sa, sizeof(sa)); + if(retval != 0) + { + // wen 2005.10.21 修改网络错误判断 + retval = GetNetErrorNo(); + if(IsWouldBlockEx(retval) == FALSE) + //if(IsWouldBlock() == FALSE) + { + HostLink[hostid].InitFlag = FALSE; + HostLink[hostid].InitOk = FALSE; + CloseHostSocket(HostLink[hostid].SocketId, 0); + + // wen 2002.04.05 + if(ShmGetDispHostLinkFlag()) + { + sprintf(tmp_buf, "与主机%c(%s:%d)网络连接错误,错误号 = %d !!!", + hostid + 'A', (char *)HostLink[hostid].TcpIpAddr[HostLink[hostid].CurLinkIdx], Host_Socket_Port, retval); + DebugPrint((char*)tmp_buf); + } + } + } + //else + //{ + // HostConnect(HostLink[hostid].SocketId, 0); + //} +} + +void HostConnect(SOCKET socket, WORD error) +{ + int id; + char szbuf[256]; + + for(id = 0; id < MAX_HOST; id++) + { + if(socket == HostLink[id].SocketId) + { + HostLink[id].InitFlag = FALSE; + HostLink[id].iNoWriteNum = 0; + + if(error) + { + if(ShmGetDispHostLinkFlag()) + { + sprintf(szbuf, "与主机%c(%s:%d)网络连接失败,错误号 = %d !!!", + id+'A', (char *)HostLink[id].TcpIpAddr[HostLink[id].CurLinkIdx], Host_Socket_Port, error); + DebugPrint((char*)szbuf); + } + + HostLink[id].InitOk = FALSE; + CloseHostSocket(HostLink[id].SocketId, 0); + break; + } + + HostLink[id].InitOk = TRUE; + + if(ShmGetDispHostLinkFlag()) + { + sprintf(szbuf, "与主机%c(%s:%d)网络连接成功 !!!", + id+'A', (char *)HostLink[id].TcpIpAddr[HostLink[id].CurLinkIdx], Host_Socket_Port); + DebugPrint((char*)szbuf); + } + + //HostSendBuf[id].MsgLen = 0; + // wen 2002.07.10 确保首先发送以下帧 + ClearSendBuffer(id); + ClearRecvBuffer(id); + + SendNetNameplateMsgToHost(TRUE); + SendNetNameplateMsgToHost(TRUE); + SendHostSendBufToHost(); + } + } +} + +void LinkToHost(void) +{ + int i; + static int cnt = 0; + //char szbuf[256]; + + if(HostWSAStartupErr) + { + return; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.30 将该段代码提前,如果不连接服务器,也可以做主备运转 + for(i = 0; i < MAX_FEND; i++) + { + FendMsg.LinkCnt[i]++; + FendMsg.FendExistCnt[i]++; + if(FendMsg.LinkCnt[i] > 10000 / TIMER_CNT) + { + FendMsg.LinkCnt[i]--; + FendMsg.LinkStatus[i] = FALSE; + } + if(FendMsg.FendExistCnt[i] > 10000 / TIMER_CNT) + { + FendMsg.FendExistCnt[i]--; + FendMsg.FendExistFlag[i] = FALSE; + } + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(FendMsg.EnableLink == 0) + { + return; + } + + for(i = 0; i < MAX_HOST; i++) + { + if(HostLink[i].InitOk == TRUE) + { + HostLink[i].StatusCnt++; + // wen 2002.01.24 + //if(HostLink[i].StatusCnt > (5000/TIMER_CNT)) + if(HostLink[i].StatusCnt > (10000/TIMER_CNT)) + { + // wen 2005.07.21 修改冗余代码 + //sprintf(szbuf, "【socket=%d】接收主机%c数据超时关闭!!!", + // HostLink[i].SocketId, i + 'A'); + //DebugPrint((char*)szbuf); + //HostLink[i].StatusCnt = 0; + CloseHostSocket(HostLink[i].SocketId, OVER_TIME_CLOSE_NET); + } + } + } + + SendNetActiveMsgToHost(); + + switch(FendMsg.LinkFlag) + { + case 0: + case 1: + LinkOneHost(FendMsg.LinkFlag); + break; + + case 2: + for(i = 0; i < MAX_HOST; i++) + { + LinkOneHost(i); + } + break; + + default: + break; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.30 将该段代码提前,如果不连接服务器,也可以做主备运转 + /* + for(i = 0; i < MAX_FEND; i++) + { + FendMsg.LinkCnt[i]++; + FendMsg.FendExistCnt[i]++; + if(FendMsg.LinkCnt[i] > 10000 / TIMER_CNT) + { + FendMsg.LinkCnt[i]--; + FendMsg.LinkStatus[i] = FALSE; + } + if(FendMsg.FendExistCnt[i] > 10000 / TIMER_CNT) + { + FendMsg.FendExistCnt[i]--; + FendMsg.FendExistFlag[i] = FALSE; + } + } + */ + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + cnt++; + if((cnt * TIMER_CNT) < 3000) + { + return; + } + cnt = 0; + + switch(FendMsg.LinkStatus[1]*2 + FendMsg.LinkStatus[0]) + { + case 3: // 两前置机都处于连机状态 + for(i = 0; i < MAX_HOST; i++) + { + if(HostLink[i].Status == 0) + { + //SendSwitch(i); + } + } + break; + + case 1: // 仅前置机 A 处于连机状态 + //SendSwitch(0); + break; + + case 2: // 仅前置机 B 处于连机状态 + //SendSwitch(1); + break; + + default: + break; + } +} + +void CloseHostSocket(SOCKET socket, int flag) +{ + int i; + char szbuf[256]; + + for(i = 0; i < MAX_HOST; i++) + { + if((HostLink[i].SocketId == socket) && (HostLink[i].SocketId != INVALID_SOCKET)) + { + CloseNetSocket(HostLink[i].SocketId); + + HostSendBuf[i].MsgLen = 0; + + HostLink[i].InitOk = FALSE; + HostLink[i].InitFlag = FALSE; + HostLink[i].ExistFlag = FALSE; + HostLink[i].CommFlag = FALSE; + HostLink[i].Status = 2; + HostLink[i].StatusCnt = 0; + HostLink[i].VersionFalgByte = 0; + HostLink[i].RevHostStatusMsg = 0; + + if(CheckTcpIpAddr((char*)HostLink[i].TcpIpAddr[HostLink[i].CurLinkIdx ? 0 : 1])) + { + HostLink[i].CurLinkIdx = HostLink[i].CurLinkIdx ? 0 : 1; + } + + if(ShmGetDispHostLinkFlag()) + { + switch(flag) + { + case HOST_CLOSE_NET: + sprintf(szbuf, "【socket=%d】主机主动关闭与主机 %c 的网络连接!!!", + HostLink[i].SocketId, i + 'A'); + DebugPrint((char*)szbuf); + break; + case OVER_TIME_CLOSE_NET: + sprintf(szbuf, "【socket=%d】网络定时超时关闭与主机 %c 的网络连接!!!", + HostLink[i].SocketId, i + 'A'); + DebugPrint((char*)szbuf); + break; + case FEND_CLOSE_NET: + sprintf(szbuf, "【socket=%d】前置机关闭与主机 %c 的网络连接!!!", + HostLink[i].SocketId, i + 'A'); + DebugPrint((char*)szbuf); + break; + case ERROR_CLOSE_NET: + sprintf(szbuf, "【socket=%d】网络错误后关闭与主机 %c 的网络连接!!!", + HostLink[i].SocketId, i + 'A'); + DebugPrint((char*)szbuf); + break; + default: + sprintf(szbuf, "【socket=%d】其他情况关闭与主机 %c 的网络连接!!!", + HostLink[i].SocketId, i + 'A'); + DebugPrint((char*)szbuf); + break; + } + } + + HostLink[i].SocketId = INVALID_SOCKET; + } + } +} + +void CloseHost(void) +{ + int i; + + for(i = 0; i < MAX_HOST; i++) + { + CloseHostSocket(HostLink[i].SocketId, FEND_CLOSE_NET); + } +} + +void PutDataToHostRevBuf(int hostid, char *buf, int len) +{ + int j; + char *ptr, szbuf[256]; + + if(HostRevBuf[hostid].MsgCnt == 0) + { + HostRevBuf[hostid].Front = 0; + HostRevBuf[hostid].Rear = 0; + } + + ptr = buf; + if((MAX_NET_BUF - HostRevBuf[hostid].MsgCnt) > len) + { + j = MAX_NET_BUF - HostRevBuf[hostid].Rear; + if(j >= len) + { + memmove((char*)&HostRevBuf[hostid].MsgData[HostRevBuf[hostid].Rear], ptr, len); + HostRevBuf[hostid].Rear += len; + HostRevBuf[hostid].Rear %= MAX_NET_BUF; + } + else + { + sprintf(szbuf, "主机%c接收暂存缓冲区分半存储!!!", 'A'+hostid); + DebugPrint((char*)szbuf); + + memmove((char*)&HostRevBuf[hostid].MsgData[HostRevBuf[hostid].Rear], ptr, j); + HostRevBuf[hostid].Rear += j; + HostRevBuf[hostid].Rear %= MAX_NET_BUF; + memmove((char*)HostRevBuf[hostid].MsgData, ptr, len - j); + HostRevBuf[hostid].Rear += (len-j); + HostRevBuf[hostid].Rear %= MAX_NET_BUF; + } + HostRevBuf[hostid].MsgCnt += len; + } + else + { + sprintf(szbuf, "主机%c接收暂存缓冲区溢出!!!", 'A'+hostid); + DebugPrint((char*)szbuf); + } +} + +BOOL ReadHost(int hostid) +{ + int retval, errorcode; + char msgbuf[MAX_NET_BUF]; + BOOL bRetVal; + + bRetVal = FALSE; + if(HostLink[hostid].InitOk) + { + retval = recv(HostLink[hostid].SocketId, msgbuf, MAX_NET_BUF, 0); + if(retval > 0) + { + PutDataToHostRevBuf(hostid, (char*)msgbuf, retval); + HostLink[hostid].StatusCnt = 0; + bRetVal = TRUE; + } + else + { +#ifdef OS_LINUX + if(retval == 0) + { + errorcode = 0; + } + else + { + errorcode = errno; + } +#else + errorcode = WSAGetLastError(); +#endif + if(ShmGetDispHostLinkFlag()) + { + sprintf(msgbuf, "recv(HostLink[%d].SocketId=%d) = %d(errno=%d)", + hostid, HostLink[hostid].SocketId, retval, errorcode); + DebugPrint(msgbuf); + } + } + } + + return bRetVal; +} + +int GetHostMsgFormHostRevBuf(HOSTMSG *hmsg, int hostid) +{ + int status; + int msglen, msgidx; + int front, cnt; + BYTE buf[32]; + char szbuf[256]; + ORTUMSG * msg; + + front = HostRevBuf[hostid].Front; + cnt = HostRevBuf[hostid].MsgCnt; + status = 0; + + while (cnt) + { + switch(status) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + if(HostRevBuf[hostid].MsgData[front] == SyncHead[status]) + { + status++; + } + else + { + status = 0; + } + + front = (front + 1) % MAX_NET_BUF; + cnt--; + + if(status == 0) + { + HostRevBuf[hostid].Front = front; + HostRevBuf[hostid].MsgCnt = cnt; + } + break; + + case 6: + case 7: + case 8: + case 9: + buf[status-6] = HostRevBuf[hostid].MsgData[front]; + status++; + front = (front + 1) % MAX_NET_BUF; + cnt--; + if(status == 10) + { + msg = (ORTUMSG*)&buf; + hmsg->MsgType = msg->MsgType; + hmsg->PortNumber = msg->PortNumber; + hmsg->MsgLen = SequenceHostToRtuWord((WORD)msg->MsgLen); + hmsg->EMsgLen = 0; + + msglen = hmsg->MsgLen; + if(msglen == 0) + { + HostRevBuf[hostid].Front = front; + HostRevBuf[hostid].MsgCnt = cnt; + return TRUE; + } + if(msglen > (MAX_RTU_MSG_SIZE - 12)) + { + sprintf(szbuf, "接收主机%c信息包超长 Len = %d!", 'A'+hostid, msglen); + DebugPrint((char*)szbuf); + + status = 0; + HostRevBuf[hostid].Front = front; + HostRevBuf[hostid].MsgCnt = cnt; + } + } + msgidx = 0; + break; + + case 10: + hmsg->MsgData[msgidx++] = HostRevBuf[hostid].MsgData[front]; + front = (front + 1) % MAX_NET_BUF; + cnt--; + msglen--; + + if(msglen == 0) + { + HostRevBuf[hostid].Front = front; + HostRevBuf[hostid].MsgCnt = cnt; + return TRUE; + } + + if(msgidx < 6) + { + break; + } + + if(memcmp((char*)&hmsg->MsgData[msgidx-6], (char*)SyncHead, 6) == 0) + { + sprintf(szbuf, "接收主机%c 信息包失步! ", 'A'+ hostid); + DebugPrint((char*)szbuf); + + status = 0; + HostRevBuf[hostid].Front = front; + HostRevBuf[hostid].MsgCnt = cnt; + } + break; + + default: + status = 0; + break; + } + } + return FALSE; +} + +BOOL ReadDataFormHost(SOCKET socket) +{ + BOOL bRetVal; + int i, hostid; + WORD sum; + char szbuf[256]; + HOSTMSG hostmsg; + DAY_TIME DateTime; + SYSTEMTIME *pTime; + + bRetVal = TRUE; + for(hostid = 0; hostid < MAX_HOST; hostid++) + { + if(HostLink[hostid].SocketId == socket) + { + bRetVal = ReadHost(hostid); + break; + } + } + + if(bRetVal == FALSE) + { + return bRetVal; + } + + if(hostid >= MAX_HOST) + { + return FALSE; + } + + while(GetHostMsgFormHostRevBuf(&hostmsg, hostid)) + { + if(FALSE == AllDataRtuToHostByteSequence(&hostmsg)) + { + sprintf(szbuf, "接收主机%c数据格式错误!!!", 'A'+ hostid); + DebugPrint((char*)szbuf); + continue; + } + + if(HostLink[hostid].VersionFalgByte & CHECK_VERSION_FLAG) + { + sum = hostmsg.MsgData[hostmsg.MsgLen - 2] + hostmsg.MsgData[hostmsg.MsgLen - 1] * 256; + sum = SequenceRtuToHostWord(sum); + + if(sum != CalCheckout((u_char*)hostmsg.MsgData, hostmsg.MsgLen - 2)) + { + sprintf(szbuf, "接收主机%c信息校验码错误!!!", 'A'+ hostid); + DebugPrint((char*)szbuf); + continue; + } + hostmsg.MsgLen -= 2; + } + + switch(hostmsg.MsgType) + { + case hHOSTSTATUS: + for(i = 0; i < MAX_HOST; i++) + { + HostLink[i].Status = (*(int*)&hostmsg.MsgData[i*sizeof(int)]) % 3; + } + // wen 2002.01.24 + HostLink[hostid].RevHostStatusMsg = TRUE; + break; + + case hNETTESTMSG: + break; + + case hTIMEINFORM: + if((HostLink[0].Status == 0) && (HostLink[1].Status == 0)) + { + continue; + } + + if(HostLink[hostid].Status) + { + continue; + } + + if(SystemTimeFlag && (SystemTimeMode == 1)) + { + //SetLocalTime((SYSTEMTIME*)hostmsg.MsgData); + pTime = (SYSTEMTIME*)hostmsg.MsgData; + if(pTime->wSecond > 5) + { + break; + } + DateTime.Year = pTime->wYear; + DateTime.Month = (BYTE)pTime->wMonth; + DateTime.Day = (BYTE)pTime->wDay; + DateTime.Hour = (BYTE)pTime->wHour; + DateTime.Min = (BYTE)pTime->wMinute; + DateTime.Sec = (BYTE)pTime->wSecond; + DateTime.mSec = pTime->wMilliseconds; + SetLocalTimeEx(&DateTime); + } + break; + + // wen 2003.10.24 增加动态数据库修改的同步(郑州农科) + //case hRELOADDBSTN:// 重新装入数据库站信息 + // 启动线程拷贝站信息数据并替换该站的数据类型的句柄(如:模拟量,开关量,电度量和离线量) + // break; + + // wen 2003.10.24 增加动态数据库修改的同步(郑州农科) + //case hRELOADDBPOINT:// 重新装入数据库点信息 + // 直接设置点信息 + // break; + + default: // hMAPANDATA,hMAPDIDATA,hBYPASSCMD,hYKYTCMD etc. + if((HostLink[0].Status == 0) && (HostLink[1].Status == 0)) + { + continue; + } + + // wen 2002.04.05 + // 主备服务器数据都发送(针对可能无应答的服务器) + //if(HostLink[hostid].Status) + // continue; + + HostDataProce(&hostmsg); + break; + } + } + + return bRetVal; +} + +int SendHost(int hostid); + +int SendDataToHostSendBuf(int hostid, u_char *buf, int len, BOOL bInsert) +{ + int imsgLen; + HOSTMSG *revmsg; + ORTUMSG msg; + char szbuf[256]; + + if(HostLink[hostid].InitOk == FALSE) + { + return 0; + } + + if(!bInsert) + { + if(HostLink[hostid].RevHostStatusMsg != TRUE) + { + return 0; + } + + if(HostLink[hostid].NetNameplateFalg == FALSE) + { + MakeNetNameplateMsgToHost((HOSTMSG *)buf); + HostLink[hostid].NetNameplateFalg = TRUE; + } + } + + revmsg = (HOSTMSG*)buf; + + // wen 2002.08.01 数据帧格式错误,长度大于总长度 + if(revmsg->MsgLen > len) + { + sprintf(szbuf, "发送到主机%c缓冲区数据帧格式错误:帧长度:%d 字节", 'A'+hostid, revmsg->MsgLen); + DebugPrint((char*)szbuf); + return 0; + } + + // wen 2002.07.11 给判断多留一些空间 + //imsgLen = msg.MsgLen + sizeof(ORTUMSGHEAD); + imsgLen = revmsg->MsgLen + sizeof(ORTUMSGHEAD); + // 6bytes同步头+2bytes校验+12bytes空闲字节 + //if((MAX_NET_BUF - HostSendBuf[hostid].MsgLen) < (msg.MsgLen+6)) + if((MAX_NET_BUF - HostSendBuf[hostid].MsgLen) < (imsgLen+20)) + { + if(SendHost(hostid) == FALSE) + { + return 0; + } + + // wen 2002.08.01 数据发送以后,缓冲区长度任然不足 + if((MAX_NET_BUF - HostSendBuf[hostid].MsgLen) < (imsgLen+20)) + { + sprintf(szbuf, "主机%c发送缓冲区溢出!!!", 'A'+hostid); + DebugPrint((char*)szbuf); + return 0; + } + } + + /* + msg.MsgType = (BYTE)revmsg->MsgType; + msg.MsgLen = revmsg->MsgLen; + msg.PortNumber = (BYTE)revmsg->PortNumber; + memmove((char*)msg.MsgData, (char*)revmsg->MsgData, revmsg->MsgLen); + */ + + if(FALSE == AllDataHostToRtuByteSequence(revmsg, &msg)) + { + sprintf(szbuf, "向主机%c发送数据格式错误!!!", 'A'+ hostid); + DebugPrint((char*)szbuf); + return 0; + } + + if(HostLink[hostid].VersionFalgByte & CHECK_VERSION_FLAG) + { + *(WORD*)&msg.MsgData[imsgLen] = SequenceHostToRtuWord(CalCheckout(msg.MsgData, imsgLen)); + imsgLen += 2; + msg.MsgLen = SequenceHostToRtuWord((WORD)imsgLen); + } + + memmove((char*)&HostSendBuf[hostid].MsgData[HostSendBuf[hostid].MsgLen], (char*)SyncHead, 6); + HostSendBuf[hostid].MsgLen += 6; + memmove((char*)&HostSendBuf[hostid].MsgData[HostSendBuf[hostid].MsgLen], (char*)&msg, imsgLen); + HostSendBuf[hostid].MsgLen += imsgLen; + + // wen 2002.08.01 数据缓冲区长度过长(永远也不会到达) + if(HostSendBuf[hostid].MsgLen > MAX_NET_BUF) + { + sprintf(szbuf, "主机%c缓冲区长度越限:长度:%d 字节", + 'A'+hostid, HostSendBuf[hostid].MsgLen); + DebugPrint((char*)szbuf); + HostSendBuf[hostid].MsgLen = 0; + return 0; + } + + return len; +} + +void SendDataToAllHostSendBuf(u_char *buf, int len) +{ + int i; + + for(i = 0; i < MAX_HOST; i++) + { + SendDataToHostSendBuf(i, buf, len, FALSE); + } +} + +int SendHost(int hostid) +{ + int retval, neterror; + char szbuf[256]; + struct timeval timeout; + fd_set fdset_wr; + + if(HostLink[hostid].InitOk == FALSE) + { + HostSendBuf[hostid].MsgLen = 0; + return TRUE; + } + + if(HostLink[hostid].SocketId == INVALID_SOCKET) + { + HostSendBuf[hostid].MsgLen = 0; + return TRUE; + } + + if(HostSendBuf[hostid].MsgLen == 0) + { + return TRUE; + } + + FD_ZERO(&fdset_wr); + FD_SET(HostLink[hostid].SocketId, &fdset_wr); + + memset((char*)&timeout, 0, sizeof(struct timeval)); + // wen 2005.07.08 设置超时等待时间(这样会丢失数据吗?) + //timeout.tv_usec = 200; + retval = select(HostLink[hostid].SocketId+1, (fd_set*)0, &fdset_wr, (fd_set*)0, &timeout); + if(retval == 0) + { + // wen 2005.10.21 累计值超限关闭socket + HostLink[hostid].iNoWriteNum++; + if(HostLink[hostid].iNoWriteNum > MAX_NO_WRITE_NUM) + { + sprintf(szbuf, "主机%c SOCKET不可写标记累计超过限值", 'A'+hostid); + DebugPrint((char*)szbuf); + CloseHostSocket(HostLink[hostid].SocketId, OVER_TIME_CLOSE_NET); + + HostLink[hostid].iNoWriteNum = 0; + } + return TRUE; + } + + if(retval != -1) + { + // 首先判断socket写标识正常否 + if(FD_ISSET(HostLink[hostid].SocketId, &fdset_wr)) + { + HostLink[hostid].iNoWriteNum = 0; + retval = send(HostLink[hostid].SocketId, + (char*)HostSendBuf[hostid].MsgData, + HostSendBuf[hostid].MsgLen, 0); + + if(SOCKET_ERROR == retval) + { + neterror = GetNetErrorNo(); + if(IsWouldBlockEx(neterror) == TRUE) + { + if(ShmGetDispHostLinkFlag()) + { + sprintf(szbuf, "【socket=%d】发送主机%c网络可能阻塞", + HostLink[hostid].SocketId, 'A'+hostid); + DebugPrint((char*)szbuf); + } + } + else + { + if(ShmGetDispHostLinkFlag()) + { + sprintf(szbuf, "发送主机%c缓冲区网络出错:%d,请求:%d 字节", + 'A'+hostid, neterror, HostSendBuf[hostid].MsgLen); + DebugPrint((char*)szbuf); + } + CloseHostSocket(HostLink[hostid].SocketId, ERROR_CLOSE_NET); + return FALSE; + } + } + else + { + HostSendBuf[hostid].MsgLen -= retval; + if(HostSendBuf[hostid].MsgLen > 0) + { + if(ShmGetDispHostLinkFlag()) + { + sprintf(szbuf, "【socket=%d】发送主机%c缓冲区出错! 剩余:%d 字节,发送:%d 字节", + HostLink[hostid].SocketId, 'A'+hostid, HostSendBuf[hostid].MsgLen, retval); + DebugPrint((char*)szbuf); + } + memmove(HostSendBuf[hostid].MsgData, HostSendBuf[hostid].MsgData+retval, HostSendBuf[hostid].MsgLen); + } + else + { + //sprintf(szbuf, "【socket=%d】发送主机%c缓冲区! 发送:%d 字节", + // HostLink[hostid].SocketId, 'A'+hostid, retval); + //DebugPrint((char*)szbuf); + HostSendBuf[hostid].MsgLen = 0; + } + } + } + else + { + CloseHostSocket(HostLink[hostid].SocketId, ERROR_CLOSE_NET); + return FALSE; + } + } + else + { + CloseHostSocket(HostLink[hostid].SocketId, ERROR_CLOSE_NET); + return FALSE; + } + + return TRUE; +} + +void SendHostSendBufToHost(void) +{ + int i; + + // wen 2003.06.11 增加变化数据的发送 + SendRtuChangeDataToHost(); + + for(i = 0; i < MAX_HOST; i++) + { + SendHost(i); + } +} + +void ClearSendBuffer(int hostid) +{ + HostSendBuf[hostid].MsgLen = 0; +} + +void ClearRecvBuffer(int hostid) +{ + HostRevBuf[hostid].MsgCnt = 0; + HostRevBuf[hostid].Front = 0; + HostRevBuf[hostid].Rear = 0; +} + +void HostDataProceWithSignalYkYt(HOSTMSG *hmsg) +{ + BOOL bFailed; + char buf[64]; + int port, ykytpnt; + SIO_PARAM_DEF *pSioParam; + + pSioParam = GetSioParamPtr(); + + // wen 2006.01.14 增加端口偏移 + //port = hmsg->PortNumber; + port = hmsg->PortNumber - FendMsg.iPortOffset; + if(port < 0 ) + { + return; + } + + bFailed = TRUE; + if((hmsg->MsgLen != 5) && (hmsg->MsgLen != 7)) + { + bFailed = FALSE; + } + else if((hmsg->MsgData[3] < 1) || (hmsg->MsgData[3] > 8)) + { + bFailed = FALSE; + } + else if((hmsg->MsgData[4] < 1) || (hmsg->MsgData[4] > 2)) + { + bFailed = FALSE; + } + + ykytpnt = *((short *)&hmsg->MsgData[1]); + if((bFailed == FALSE) || (pSioParam[port].m_psBaoHu == NULL)) + { + buf[0] = (BYTE)ykytpnt; + buf[1] = 0; + buf[2] = 0; + SetYkYtAckData(port, buf); + return; + } + + memset(buf, 0, sizeof(buf)); + buf[0] = port; + buf[4] = (BYTE)ykytpnt; + buf[8] = hmsg->MsgData[3]; + buf[9] = (hmsg->MsgData[4] == 1) ? 1 : 2; + + SendYkYtCommand(port, buf, 10); +} + +//*************************************************************** +//* 主机数据处理 * +//*************************************************************** +void HostDataProce(HOSTMSG *hostmsg) +{ + int port, iReLoadDefCnt=0; + HOSTMSG msg; + + switch(hostmsg->MsgType) + { + case hYKYTCMD: + if(((hostmsg->MsgLen % 5) != 0) + && ((hostmsg->MsgLen % 7) != 0)) + { + break; + } + + if(hostmsg->MsgLen >= 10) // 多条遥调遥控命令 + { + //ProLen = 0; + //memmove((char*)&MultiYkYtMsg, (char*)hostmsg, hostmsg->MsgLen+sizeof(HOSTMSGHEAD)); + //MultiYkYtFlag = TRUE; + //MultiYkYtSelectProce(); + //MultiYkYtFlag = FALSE; + } + else // 单条遥调遥控命令 + { + HostDataProceWithSignalYkYt(hostmsg); + } + break; + + case hBYPASSCMD: + switch(hostmsg->MsgData[1]) + { + case 0x0d: + case 0x0e: + case 0x11: + //SendDataToPort(hostmsg->PortNumber, (char*)hostmsg->MsgData, hostmsg->MsgLen, CLEAR_INPUT_BUF); + break; + case 0x1a: + //SendDataToPort(hostmsg->PortNumber, (char*)hostmsg->MsgData, hostmsg->MsgLen, CLEAR_INPUT_BUF); + break; + default: + //SendDataToPort(hostmsg->PortNumber, (char*)hostmsg->MsgData, hostmsg->MsgLen, CLEAR_INPUT_BUF); + break; + } + break; + + case hMAPANDATA: + case hMAPDIDATA: + //FormHostMapDataProce(hostmsg); + break; + + case hDATA_OUTPUT_CTRL: + //hostmsg->PortNumber = hostmsg->MsgData[1]; + //MakeRsLinks22DataCtrlCommand(hostmsg); + + hostmsg->PortNumber = hostmsg->MsgData[1]; + port = hostmsg->PortNumber; + //selidx = PortParam[port].CurrentPortSel; + //switch(PortParam[port].CommPort[selidx].RtuType) + //{ + // case RSLINKS22DDE: + // MakeRsLinks22DataCtrlCommand(hostmsg); + // break; + // case DISA2000: + // Disa2000AoCommand(hostmsg); + // break; + //} + break; + + case hRELOADDATABASE: + msg.MsgType = hRELOADDATABASE; + msg.PortNumber = 0; + msg.MsgLen = 1; + msg.EMsgLen = 0; + msg.MsgData[0] = FALSE; + + if(iReLoadDefCnt * TIMER_CNT / 1000 > 60) + { + iReLoadDefCnt = 0; + //ReLoadPortDefine(); + msg.MsgData[0] = TRUE; + } + SendDataToAllHostSendBuf((u_char*)&msg, msg.MsgLen+sizeof(HOSTMSGHEAD)); + break; + + case hMAPALLOP: + //HostMapOpProc(hostmsg); + break; + + // 数据库信息修改 + case NET_PROFILE_UPDATE: + //ModifyDBProc(hostmsg); + break; + } +} + +//*************************************************************** +//* 发送变化数据到主机 * +//*************************************************************** +void SendRtuChangeDataToHost(void) +{ + int i; + +#ifdef FEND_STANDBY_NOSEND + // wen 2003.01.07 前置机为备用机时,不发送变化数据给服务器 + if(!IsSendDatatoPort(-1)) + return; +#endif + + for(i = 0; i < RTUCHANGMSGNUM; i++) + { + gRtuChangeMsg[i].EMsgLen = 0; + + if(gRtuChangeMsg[i].MsgLen) + { + SendDataToAllHostSendBuf((u_char*)&gRtuChangeMsg[i], gRtuChangeMsg[i].MsgLen + sizeof(HOSTMSGHEAD)); + gRtuChangeMsg[i].MsgLen = 0; + } + } +} + +//*************************************************************** +//* 发送端口统计到主机数据 * +//*************************************************************** +void SendPortStatisticsToHost(void) +{ + /* + int i, portnum; + HOSTMSG MsgBuf; + + portnum = DEFAULT_MAX_PORT_NUM; + + MsgBuf.MsgType = WUXI_ZHUANFA_AI_TO_HOST; + MsgBuf.PortNumber = MaxPortNum-1; + + MsgBuf.MsgLen = portnum *20 + 2; + MsgBuf.EMsgLen = 0; + + *(short*)&MsgBuf.MsgData[0] = 0; + + for(i = 0; i < portnum; i++) + { + + *(float*)&MsgBuf.MsgData[20*i+2] = (float)PortParam[i].MsgNum; + *(float*)&MsgBuf.MsgData[20*i+6] = (float)PortParam[i].ErrMsgNum; + *(float*)&MsgBuf.MsgData[20*i+10] = (float)PortParam[i].LostSyncCnt; + *(float*)&MsgBuf.MsgData[20*i+14] = (float)((PortParam[i].MsgNum != 0) ? + (float)PortParam[i].ErrMsgNum / (float)PortParam[i].MsgNum : 0.0); + *(float*)&MsgBuf.MsgData[20*i+18] = (float)((PortParam[i].UpTime || PortParam[i].DownTime) ? + (float)PortParam[i].UpTime/(float)(PortParam[i].UpTime + PortParam[i].DownTime) : 0.0); + } + SendDataToAllHostSendBuf((u_char*)&MsgBuf, MsgBuf.MsgLen + sizeof(RTUMSGHEAD)); + */ +} + +//*************************************************************** +//* 发送端口状态到主机数据 * +//*************************************************************** +void SendPortStatusToHost(int flag) +{ + int i, portnum; + HOSTMSG MsgBuf; + SIO_PARAM_DEF *pSioParam; + + pSioParam = GetSioParamPtr(); + portnum = DEFAULT_MAX_PORT_NUM; + + MsgBuf.MsgType = iLINESTATUS; + MsgBuf.PortNumber = 0; + MsgBuf.MsgLen = portnum*2; + MsgBuf.EMsgLen = 0; + for(i = 0; i < portnum; i++) + { + // 将端口状态复位 + pSioParam[i].LineCommCnt++; + if ( (((long)pSioParam[i].LineCommCnt*TIMER_CNT)/1000) > 60 ) + { + pSioParam[i].LineCommCnt = 0; + pSioParam[i].Status = FALSE; + } + + // wen 2006.01.14 增加端口偏移 + //MsgBuf.MsgData[i*2] = (BYTE)i; + MsgBuf.MsgData[i*2] = (BYTE)(i+FendMsg.iPortOffset); + + MsgBuf.MsgData[i*2+1] = flag ? (pSioParam[i].Status & 0x01) : 0x00; + } + SendDataToAllHostSendBuf((u_char*)&MsgBuf, MsgBuf.MsgLen + sizeof(HOSTMSGHEAD)); + + //SendPortStatisticsToHost(); +} + +// wen 2003.01.08 前置机向服务器发送全数据时,提取数据值时,应 +// 该判断该值的有效性。这样就不会发生遥信误报警的情况。 +//*************************************************************** +//* 送端口全数据到主机 * +//*************************************************************** +void SendPortAllDataToHost(void) +{ + //static int test=0; + char szDbg[256]; + BOOL bSendFlag; + int i; + static int sendport = 0, count = 0; + HOSTMSG SendAllDataBuf; + AI_DEF aipntmsg; + DI_DEF dipntmsg; + PI_DEF pipntmsg; + SIO_PARAM_DEF *pSioParam; + + //if (WaittingFlag == TRUE) + // return; + + //if (DisbaleWriteAllDataToHostFlag) + // return; + +#ifdef FEND_STANDBY_NOSEND + // wen 2003.01.07 前置机为备用机时,不发送全数据给服务器 + // 可以省去,因为备用机不做数据处理,其端口状态 PortParam[sendport].Status + // 也不会变为TRUE + if(!IsSendDatatoPort(-1)) + return; +#endif + + count++; + if(count * TIMER_CNT < 1000) + { + return; + } + count = 0; + + pSioParam = GetSioParamPtr(); + + //if(test == 0) + //{ + // DebugPrint(">>>Enter SendAllData."); + // test = 1; + //} + //else + //{ + // DebugPrint("<<PortType) + { + // 端口由停运---转为-->正常,需要有1 分钟来刷行该端口数据 + // 否则发送上去的全数据会由于没有完全刷新而出现报警混乱。 + // 最严重的后果是遥信报警反复,即我们所说的误报。 + //if(pSioParam[sendport].iDelaySendAllData < (60000/TIMER_CNT)) + if(pSioParam[sendport].iDelaySendAllData < 60) + { + pSioParam[sendport].iDelaySendAllData++; + } + else + { + bSendFlag = TRUE; + break; + } + } + } + } + else + { + pSioParam[sendport].iDelaySendAllData = 0; + } + + sendport = (sendport + 1) % DEFAULT_MAX_PORT_NUM; + } + + // test + if(pSioParam[sendport].iDelaySendAllData == 60) + { + sprintf(szDbg, "SendAllData port=%d iDelaySendAllData=%d, bSendFlag=%d, status=%d", + sendport, pSioParam[sendport].iDelaySendAllData, bSendFlag, pSioParam[sendport].Status); + DebugPrint(szDbg); + pSioParam[sendport].iDelaySendAllData++; + } + + sendport = sendport % DEFAULT_MAX_PORT_NUM; + //if((i >= DEFAULT_MAX_PORT_NUM) || (FALSE == bSendFlag)) + if(FALSE == bSendFlag) + { + return; + } + + // test + //sprintf(szDbg, "SendAllData from port=%d", sendport); + //DebugPrint(szDbg); + + // wen 2005.06.20 传送32bit模拟量数据 + if(FendMsg.iSendAiof32Bit) + { + // 发送全遥测 + SendAllDataBuf.MsgType = PGC3_AI32ALLDATA; + + // wen 2006.01.14 增加端口偏移 + //SendAllDataBuf.PortNumber = sendport; + SendAllDataBuf.PortNumber = sendport+FendMsg.iPortOffset; + + SendAllDataBuf.MsgLen = 0; + SendAllDataBuf.EMsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = 0; + SendAllDataBuf.MsgLen += sizeof(short); + + for(i = 0; i < pSioParam[sendport].m_psBaoHu->AiNum; i++) + { + if ((MAX_RTU_MSG_SIZE - SendAllDataBuf.MsgLen) < 8) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = i; + SendAllDataBuf.MsgLen += sizeof(short); + } + + if(GetPntMsg(sendport, i, (void *)&aipntmsg, AI_PNT_TYPE, PNT_ALL_MSG) == FALSE) + { + aipntmsg.RawValue = 0; + } + + *(long*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = (long)aipntmsg.RawValue; + SendAllDataBuf.MsgLen += sizeof(long); + } + if(SendAllDataBuf.MsgLen > sizeof(long)) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + } + } + else + { + // 发送全遥测 + SendAllDataBuf.MsgType = iAIALLDATA; + + // wen 2006.01.14 增加端口偏移 + //SendAllDataBuf.PortNumber = sendport; + SendAllDataBuf.PortNumber = sendport+FendMsg.iPortOffset; + + SendAllDataBuf.MsgLen = 0; + SendAllDataBuf.EMsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = 0; + SendAllDataBuf.MsgLen += sizeof(short); + + for(i = 0; i < pSioParam[sendport].m_psBaoHu->AiNum; i++) + { + if ((MAX_RTU_MSG_SIZE - SendAllDataBuf.MsgLen) < 8) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = i; + SendAllDataBuf.MsgLen += sizeof(short); + } + + if(GetPntMsg(sendport, i, (void *)&aipntmsg, AI_PNT_TYPE, PNT_ALL_MSG) == FALSE) + { + aipntmsg.RawValue = 0; + } + + //if(abs(aipntmsg.RawValue&0x0000ffff) < aipntmsg.Dead) + //{ + // pntmsg.RawValue = 0; + //} + + //if(i == 1) + //{ + // sprintf(szDbg, "SendAllData pnt%d val=%d", i+1, (short)aipntmsg.RawValue); + // DebugPrint(szDbg); + //} + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = (short)aipntmsg.RawValue; + SendAllDataBuf.MsgLen += sizeof(short); + } + if(SendAllDataBuf.MsgLen > sizeof(short)) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + } + } + + // 发送全遥信 + SendAllDataBuf.MsgType = iDIALLDATA; + + // wen 2006.01.14 增加端口偏移 + //SendAllDataBuf.PortNumber = sendport; + SendAllDataBuf.PortNumber = sendport+FendMsg.iPortOffset; + + SendAllDataBuf.MsgLen = 0; + SendAllDataBuf.EMsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = 0; + SendAllDataBuf.MsgLen += sizeof(short); + + for(i = 0; i < pSioParam[sendport].m_psBaoHu->DiNum; i++) + { + if ((MAX_RTU_MSG_SIZE - SendAllDataBuf.MsgLen) < 8) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = i; + SendAllDataBuf.MsgLen += sizeof(short); + } + + if(GetPntMsg(sendport, i, (void *)&dipntmsg, DI_PNT_TYPE, PNT_STATUS) == FALSE) + { + dipntmsg.Status = 0; + } + + SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = dipntmsg.Status & 0x01; + SendAllDataBuf.MsgLen += sizeof(char); + } + if (SendAllDataBuf.MsgLen > sizeof(short)) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + } + + /* + // 发送全离线遥信 + SendAllDataBuf.MsgType = iODALLDATA; + + // wen 2006.01.14 增加端口偏移 + //SendAllDataBuf.PortNumber = sendport; + SendAllDataBuf.PortNumber = sendport+FendMsg.iPortOffset; + + SendAllDataBuf.MsgLen = 0; + SendAllDataBuf.EMsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = 0; + SendAllDataBuf.MsgLen += sizeof(short); + + for(i = 0; i < min(PortParam[sendport].RevOdNum, MAX_OD_NUM); i++) + { + if ((MAX_RTU_MSG_SIZE - SendAllDataBuf.MsgLen) < 8) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(RTUMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = i; + SendAllDataBuf.MsgLen += sizeof(short); + } + + if (GetPntMsg(sendport, i, &pntmsg, OD_PNT_TYPE, PNT_STATUS) == FALSE) + pntmsg.Status = 0; + + SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = pntmsg.Status & 0x01; + SendAllDataBuf.MsgLen += sizeof(char); + } + if (SendAllDataBuf.MsgLen > sizeof(short)) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(RTUMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + } + */ + + // 发送全电度 + SendAllDataBuf.MsgType = iPIALLDATA; + + // wen 2006.01.14 增加端口偏移 + //SendAllDataBuf.PortNumber = sendport; + SendAllDataBuf.PortNumber = sendport+FendMsg.iPortOffset; + + SendAllDataBuf.MsgLen = 0; + SendAllDataBuf.EMsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = 0; + SendAllDataBuf.MsgLen += sizeof(short); + + for(i = 0; i < pSioParam[sendport].m_psBaoHu->PiNum; i++) + { + if((MAX_RTU_MSG_SIZE - SendAllDataBuf.MsgLen) < 8) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + + *(short*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = i; + SendAllDataBuf.MsgLen += sizeof(short); + } + + if(GetPntMsg(sendport, i, (void *)&pipntmsg, PI_PNT_TYPE, PNT_RAWVALUE) == FALSE) + { + pipntmsg.RawValue = 0; + } + + *(u_long*)&SendAllDataBuf.MsgData[SendAllDataBuf.MsgLen] = pipntmsg.RawValue; + SendAllDataBuf.MsgLen += sizeof(long); + } + if(SendAllDataBuf.MsgLen > sizeof(short)) + { + SendDataToAllHostSendBuf((u_char*)&SendAllDataBuf, SendAllDataBuf.MsgLen + sizeof(HOSTMSGHEAD)); + SendAllDataBuf.MsgLen = 0; + } + + sendport = (sendport + 1) % DEFAULT_MAX_PORT_NUM; +} + +//*************************************************************** +//* 填充 SOE 数据缓冲区 * +//*************************************************************** +void SetSoeData(int commidex, SOE_DEF *pSoeData) +{ + int commid; + + // wen 2006.01.14 增加端口偏移 + commid = commidex + FendMsg.iPortOffset; + + gRtuChangeMsg[SOEMSGNO].MsgType = iSOEDATA; + gRtuChangeMsg[SOEMSGNO].EMsgLen = 0; + + if((gRtuChangeMsg[SOEMSGNO].PortNumber != commid) + && gRtuChangeMsg[SOEMSGNO].MsgLen ) + { + SendDataToAllHostSendBuf((u_char*)&gRtuChangeMsg[SOEMSGNO], gRtuChangeMsg[SOEMSGNO].MsgLen + sizeof(HOSTMSGHEAD)); + gRtuChangeMsg[SOEMSGNO].MsgLen = 0; + } + gRtuChangeMsg[SOEMSGNO].PortNumber = commid; + + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = LOBYTE(pSoeData->iPntNo); // point low + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = HIBYTE(pSoeData->iPntNo); // point high + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = pSoeData->bStatus; // Status + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = LOBYTE(pSoeData->SoeTime.mSec); // ms low + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = HIBYTE(pSoeData->SoeTime.mSec); // ms high + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = (BYTE)pSoeData->SoeTime.Sec; // sec + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = (BYTE)pSoeData->SoeTime.Min; // min + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = (BYTE)pSoeData->SoeTime.Hour; // hour + gRtuChangeMsg[SOEMSGNO].MsgData[gRtuChangeMsg[SOEMSGNO].MsgLen++] = (BYTE)pSoeData->SoeTime.Day; // day +} + +//*************************************************************** +//* 填充 遥控遥调返校 数据缓冲区 * +//*************************************************************** +void SetYkYtAckData( int portno, char *buf ) +{ + int port; + + // wen 2006.01.14 增加端口偏移 + //port = portno; + port = portno+FendMsg.iPortOffset; + + gRtuChangeMsg[YKYTACKNO].MsgType = iACKDATA; + gRtuChangeMsg[YKYTACKNO].EMsgLen = 0; + + if((gRtuChangeMsg[YKYTACKNO].PortNumber != port) + && gRtuChangeMsg[YKYTACKNO].MsgLen ) + { + SendDataToAllHostSendBuf((u_char*)&gRtuChangeMsg[YKYTACKNO], gRtuChangeMsg[YKYTACKNO].MsgLen + sizeof(HOSTMSGHEAD)); + gRtuChangeMsg[YKYTACKNO].MsgLen = 0; + } + gRtuChangeMsg[YKYTACKNO].PortNumber = port; + + gRtuChangeMsg[YKYTACKNO].MsgData[gRtuChangeMsg[YKYTACKNO].MsgLen++] = buf[0];// Point Low + gRtuChangeMsg[YKYTACKNO].MsgData[gRtuChangeMsg[YKYTACKNO].MsgLen++] = buf[1];// Point High + gRtuChangeMsg[YKYTACKNO].MsgData[gRtuChangeMsg[YKYTACKNO].MsgLen++] = buf[2];// 返校码 +} + +void SelectHostSocketEvent(void) +{ + struct timeval timeout; + int i, inum, nfds; + fd_set fdset_ro, fdset_wr, fdset_ex; + + inum = 0; + nfds = 0; + FD_ZERO(&fdset_ro); + FD_ZERO(&fdset_wr); + FD_ZERO(&fdset_ex); + for(i=0; i 0) + { + memset((char*)&timeout, 0, sizeof(struct timeval)); + // wen 2005.07.08 设置超时等待时间 + //timeout.tv_usec = 200; + if(select(nfds+1, &fdset_ro, &fdset_wr, &fdset_ex, &timeout) < 1) + { + return; + } + + for(i=0; i>> %02d:%02d:%02d.%03d\n", + // sm.Hour, sm.Min, sm.Sec, sm.mSec); + //DebugPrint(szDbg); + + // 连接 + LinkToHost(); + + // 连接是否成功以及对有效端口数据接收 + //SelectHostSocketEvent(); + SelectHostSocketEventEx(); + + // 发送数据 + SendHostSendBufToHost(); + + // 发送端口状态 + SendPortStatusToHost(1); + + // 发送全数据 + SendPortAllDataToHost(); + + // 2006.01.13 增加前置机到服务器的对时功能 + SendSystemTimeToHost(); +} + +//*************************************************************** +//* 向主机请求模拟量 * +//*************************************************************** +void MapAnPointToHost(int iMapOutPort, int iMapSavePort) +{ + int i; + HOSTMSG MapPointBuf; + PROV_AI_PNT *pProvAi; + SIO_PARAM_DEF *pSioParam; + + if((iMapOutPort < 1) || (iMapSavePort < 1)) + { + return; + } + + pSioParam = GetSioParamPtr(); + + MapPointBuf.MsgType = iANPOINT; + MapPointBuf.PortNumber = 0; + MapPointBuf.MsgLen = 0; + + pProvAi = (PROV_AI_PNT *)pSioParam[iMapOutPort].m_psBaoHu->AiPtr; + for(i = 0; i < pSioParam[iMapOutPort].m_psBaoHu->AiNum; i++) + { + if(pProvAi[i].Enable == 0) + { + continue; + } + + MapPointBuf.MsgData[MapPointBuf.MsgLen++] = (u_char)pProvAi[i].wType; + MapPointBuf.MsgData[MapPointBuf.MsgLen++] = (u_char)pProvAi[i].PortNo; + *(short*)&MapPointBuf.MsgData[MapPointBuf.MsgLen] = pProvAi[i].PntNo; + MapPointBuf.MsgLen += 2; + } + + SendDataToAllHostSendBuf((u_char*)&MapPointBuf, MapPointBuf.MsgLen + sizeof(HOSTMSGHEAD)); +} + +//*************************************************************** +//* 向主机请求状态量 * +//*************************************************************** +void MapDiPointToHost(int iMapOutPort, int iMapSavePort) +{ + int i; + HOSTMSG MapPointBuf; + PROV_DI_PNT *pProvDi; + SIO_PARAM_DEF *pSioParam; + + if((iMapOutPort < 1) || (iMapSavePort < 1)) + { + return; + } + + pSioParam = GetSioParamPtr(); + + MapPointBuf.MsgType = iDIPOINT; + MapPointBuf.PortNumber = 0; + MapPointBuf.MsgLen = 0; + + pProvDi = (PROV_DI_PNT *)pSioParam[iMapOutPort].m_psBaoHu->DiPtr; + for(i = 0; i < pSioParam[iMapOutPort].m_psBaoHu->DiNum; i++) + { + if(pProvDi[i].Enable == 0) + { + continue; + } + + // 主机离线量点为 'X' 类型 + MapPointBuf.MsgData[MapPointBuf.MsgLen++] = (u_char)(pProvDi[i].wType == 'o' ? 'x' : pProvDi[i].wType); + MapPointBuf.MsgData[MapPointBuf.MsgLen++] = (u_char)pProvDi[i].PortNo; + *(short*)&MapPointBuf.MsgData[MapPointBuf.MsgLen] = pProvDi[i].PntNo; + MapPointBuf.MsgLen += 2; + } + + SendDataToAllHostSendBuf((u_char*)&MapPointBuf, MapPointBuf.MsgLen + sizeof(HOSTMSGHEAD)); +} + +//*************************************************************** +//* 主机模拟盘数据处理 * +//*************************************************************** +void FormHostMapDataProce(int iMapOutPort, int iMapSavePort, HOSTMSG *msg) +{ + int i, j, iDataNum; + float anval; + AI_DEF aipmsg; + DI_DEF dipmsg; + PROV_AI_PNT *pProvAi; + PROV_DI_PNT *pProvDi; + SIO_PARAM_DEF *pSioParam; + + if((iMapOutPort < 1) || (iMapSavePort < 1)) + { + return; + } + + pSioParam = GetSioParamPtr(); + if(msg->MsgType == hMAPANDATA) + { + pProvAi = (PROV_AI_PNT *)pSioParam[iMapOutPort].m_psBaoHu->AiPtr; + iDataNum = pSioParam[iMapOutPort].m_psBaoHu->AiNum; + for(i=j=0; (i < iDataNum) && ((j+4) <= (int)msg->MsgLen); i++) + { + if(pProvAi[i].Enable == 0) + { + continue; + } + + anval = *(float*)&msg->MsgData[j]; + j += 4; + aipmsg.RawValue = (int)(anval * pProvAi[i].fFactor); + SetPntMsg(iMapSavePort-1, i, (void *)&aipmsg, AI_PNT_TYPE, PNT_RAWVALUE); + } + } + else if(msg->MsgType == hMAPDIDATA) + { + pProvDi = (PROV_DI_PNT *)pSioParam[iMapOutPort].m_psBaoHu->DiPtr; + iDataNum = pSioParam[iMapOutPort].m_psBaoHu->DiNum; + for(i=j=0; (i < iDataNum) && (j < (int)msg->MsgLen); i++, j++) + { + if(pProvDi[i].Enable == 0) + { + continue; + } + + dipmsg.Status = (msg->MsgData[j] & 0x01); + SetPntMsg(iMapSavePort-1, i, (void *)&dipmsg, DI_PNT_TYPE, PNT_STATUS); + } + } +} + +int GetFendTxdFlag(void) +{ + // wen 2006.04.26 如果为并列运行,则下发标识为真 + if(RUN_MODE_ALLHOT == FendMsg.iRunMode) + { + return TRUE; + } + + return FendMsg.SendTxdDataFlag[FendMsg.FendIdx]; +} + +int CheckIsFendIpAddr(u_long addr) +{ + int i; + bool bRetVal; + u_long uFendAddr; + + bRetVal = false; + for(i=0; iRawValue; + pRtuChangeMsg[AIMSGNO].MsgLen += sizeof(long); + break; + } + + // 传送16bit模拟量数据 + aiptr = (AI_DEF *)pntmsg; + pRtuChangeMsg[AIMSGNO].MsgType = iAIDATA; + pRtuChangeMsg[AIMSGNO].EMsgLen = 0; + if((pRtuChangeMsg[AIMSGNO].PortNumber != commid) + && pRtuChangeMsg[AIMSGNO].MsgLen) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[AIMSGNO], pRtuChangeMsg[AIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[AIMSGNO].MsgLen = 0; + } + pRtuChangeMsg[AIMSGNO].PortNumber = commid; + + if ((MAX_RTU_MSG_SIZE - pRtuChangeMsg[AIMSGNO].MsgLen) < 12) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[AIMSGNO], pRtuChangeMsg[AIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[AIMSGNO].MsgLen = 0; + } + + *(short*)&(pRtuChangeMsg[AIMSGNO].MsgData[pRtuChangeMsg[AIMSGNO].MsgLen]) = point; + pRtuChangeMsg[AIMSGNO].MsgLen += sizeof(short); + *(short*)&(pRtuChangeMsg[AIMSGNO].MsgData[pRtuChangeMsg[AIMSGNO].MsgLen]) = (short)(aiptr->RawValue & 0x0000ffff); + pRtuChangeMsg[AIMSGNO].MsgLen += sizeof(short); + + // test + //if(point == 1) + //{ + // sprintf(szDbg, "AIChange: pnt=%d val=%d", point, (short)(aiptr->RawValue & 0x0000ffff)); + // DebugPrint(szDbg); + //} + break; + + case DI_PNT_TYPE: + diptr = (DI_DEF *)pntmsg; + //if(PortParam[port].SoeInsertFlag) + // MakeSoeData(port, point, pntmsg->Status & 0x01); + + pRtuChangeMsg[DIMSGNO].MsgType = iDIDATA; + pRtuChangeMsg[DIMSGNO].EMsgLen = 0; + if ((pRtuChangeMsg[DIMSGNO].PortNumber != commid) + && pRtuChangeMsg[DIMSGNO].MsgLen) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[DIMSGNO], pRtuChangeMsg[DIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[DIMSGNO].MsgLen = 0; + } + pRtuChangeMsg[DIMSGNO].PortNumber = commid; + + if ((MAX_RTU_MSG_SIZE - pRtuChangeMsg[DIMSGNO].MsgLen) < 12) + { + SendDataToAllHostSendBuf((u_char *)&pRtuChangeMsg[DIMSGNO], pRtuChangeMsg[DIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[DIMSGNO].MsgLen = 0; + } + + *(short*)&(pRtuChangeMsg[DIMSGNO].MsgData[pRtuChangeMsg[DIMSGNO].MsgLen]) = point; + pRtuChangeMsg[DIMSGNO].MsgLen += sizeof(short); + pRtuChangeMsg[DIMSGNO].MsgData[pRtuChangeMsg[DIMSGNO].MsgLen] = diptr->Status & 0x01; + pRtuChangeMsg[DIMSGNO].MsgLen += sizeof(BYTE); + break; + + case OD_PNT_TYPE: + /* + pRtuChangeMsg[ODMSGNO].MsgType = iODDATA; + pRtuChangeMsg[ODMSGNO].EMsgLen = 0; + if ((pRtuChangeMsg[ODMSGNO].PortNumber != commid) + && pRtuChangeMsg[ODMSGNO].MsgLen) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[ODMSGNO], pRtuChangeMsg[ODMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[ODMSGNO].MsgLen = 0; + } + pRtuChangeMsg[ODMSGNO].PortNumber = commid; + + if ((MAX_RTU_MSG_SIZE - pRtuChangeMsg[ODMSGNO].MsgLen) < 12) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[ODMSGNO], pRtuChangeMsg[ODMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[ODMSGNO].MsgLen = 0; + } + + *(short*)&(pRtuChangeMsg[ODMSGNO].MsgData[pRtuChangeMsg[ODMSGNO].MsgLen]) = point; + pRtuChangeMsg[ODMSGNO].MsgLen += sizeof(short); + pRtuChangeMsg[ODMSGNO].MsgData[pRtuChangeMsg[ODMSGNO].MsgLen] = pntmsg->Status & 0x01; + pRtuChangeMsg[ODMSGNO].MsgLen += sizeof(BYTE); + */ + break; + + case PI_PNT_TYPE: + piptr = (PI_DEF *)pntmsg; + pRtuChangeMsg[PIMSGNO].MsgType = iPIDATA; + pRtuChangeMsg[PIMSGNO].EMsgLen = 0; + if ((pRtuChangeMsg[PIMSGNO].PortNumber != commid) + && pRtuChangeMsg[PIMSGNO].MsgLen) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[PIMSGNO], pRtuChangeMsg[PIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[PIMSGNO].MsgLen = 0; + } + pRtuChangeMsg[PIMSGNO].PortNumber = commid; + + if ((MAX_RTU_MSG_SIZE - pRtuChangeMsg[PIMSGNO].MsgLen) < 12) + { + SendDataToAllHostSendBuf((u_char*)&pRtuChangeMsg[PIMSGNO], pRtuChangeMsg[PIMSGNO].MsgLen + sizeof(RTUMSGHEAD)); + pRtuChangeMsg[PIMSGNO].MsgLen = 0; + } + + *(short*)&(pRtuChangeMsg[PIMSGNO].MsgData[pRtuChangeMsg[PIMSGNO].MsgLen]) = point; + pRtuChangeMsg[PIMSGNO].MsgLen += sizeof (short); + *(u_long*)&(pRtuChangeMsg[PIMSGNO].MsgData[pRtuChangeMsg[PIMSGNO].MsgLen]) = piptr->RawValue; + pRtuChangeMsg[PIMSGNO].MsgLen += sizeof (long); + break; + } + + //WriteProvChangeData(pntmsg, type); +} + +// 判断该端口是否下发数据 +BOOL IsSendDatatoPort(int port) +{ + FEND_DEF *pFendMsg; + SIO_PARAM_DEF *pSioParam; + //char szDbg[256]; + //static int test=0; + BOOL bReturn = TRUE; + +#ifdef PC_MACHINE // 该条件仅仅在windows模拟环境中有效 +#if (FEND_OTHERDEV_DS3116 == 1) + return TRUE; +#endif +#endif + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.01.14 增加并列运行方式 + /* + pFendMsg = GetFendMsgPtr(); + if(port < 0) + { + if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == FALSE) + { + bReturn = FALSE; + } + } + else + { + pSioParam = GetSioParamPtr(); + switch(pSioParam[port].iForceSendFlag) + { + case 1:// 强制下发 + //bReturn = TRUE; + break; + case 2:// 强制不下发 + bReturn = FALSE; + break; + case 0:// 正常情况下 + default: + // 本前置机不属于主前置机 + if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == FALSE) + { + bReturn = FALSE; + } + break; + } + } + */ + //================================================================================ + pFendMsg = GetFendMsgPtr(); + if(port < 0) + { + if(RUN_MODE_ALLHOT == pFendMsg->iRunMode) + { + bReturn = TRUE; + } + else if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == FALSE) + { + bReturn = FALSE; + } + } + else + { + pSioParam = GetSioParamPtr(); + switch(pSioParam[port].iForceSendFlag) + { + case 1:// 强制下发 + //bReturn = TRUE; + break; + case 2:// 强制不下发 + bReturn = FALSE; + break; + case 0:// 正常情况下 + default: + // 本前置机不属于主前置机 + if(RUN_MODE_ALLHOT == pFendMsg->iRunMode) + { + bReturn = TRUE; + } + else if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == FALSE) + { + bReturn = FALSE; + } + break; + } + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + // 两个地方调用,时钟周期为20ms,20×200=4000ms÷2=2s + //if(test == 200) + //{ + // sprintf(szDbg, "port=%d, SendTxd=%d", port, bReturn); + // DebugPrint(szDbg); + // test = 0; + //} + //else + //{ + // test++; + //} + + return bReturn; +} + +TCP_LINK_DEF *GetHostLinkPtr() +{ + return HostLink; +} + +FEND_DEF *GetFendMsgPtr() +{ + return &FendMsg; +} + +HOSTMSG *GetRtuChangeMsgPtr() +{ + return gRtuChangeMsg; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 增加字节顺序转换函数 +BOOL AllDataHostToRtuByteSequence(HOSTMSG *hmsg, ORTUMSG *pSendMsg) +{ + int i; + BOOL bRetVal; + WORD *pWord, *pwSour; + int *piSour, *piDest; + long *plSour, *plDest; + float *pfSour, *pfDest; + SYSTEMTIME *pTime; + + bRetVal = TRUE; + switch(hmsg->MsgType) + { + case iREQUESTHOSTSTATUS:// 请求主机状态 + bRetVal = FALSE; + break; + + case iTIMEINFORM: // 前置机对时 + pTime = (SYSTEMTIME*)hmsg->MsgData; + pWord = (WORD *)pSendMsg->MsgData; + pWord[0] = SequenceHostToRtuWord(pTime->wYear); + pWord[1] = SequenceHostToRtuWord(pTime->wMonth); + pWord[2] = SequenceHostToRtuWord(pTime->wDay); + pWord[3] = SequenceHostToRtuWord(pTime->wHour); + pWord[4] = SequenceHostToRtuWord(pTime->wMinute); + pWord[5] = SequenceHostToRtuWord(pTime->wSecond); + pWord[6] = SequenceHostToRtuWord(pTime->wMilliseconds); + break; + + case iAIDATA: // 变化遥测 + case iAIALLDATA: // 遥测全数据 + pWord = (WORD *)pSendMsg->MsgData; + pwSour = (WORD *)hmsg->MsgData; + for(i=0; iMsgLen; i+=2) + { + if((i+2) > hmsg->MsgLen) + { + break; + } + + pWord[i/2] = SequenceHostToRtuWord(pwSour[i/2]); + } + break; + + // wen 2006.05.20 32bit传送模拟量数据(和电度量传送格式一致) + case PGC3_AI32DATA: // 变化32位遥测数据 + for(i=0; iMsgLen; i+=6) + { + if((i+6) > hmsg->MsgLen) + { + break; + } + pWord = (WORD *)&pSendMsg->MsgData[i]; + pwSour = (WORD *)&hmsg->MsgData[i]; + *pWord = SequenceHostToRtuWord(*pwSour); + + plDest = (long *)&pSendMsg->MsgData[i+2]; + plSour = (long *)&hmsg->MsgData[i+2]; + *plDest = SequenceHostToRtulong(*plSour); + } + break; + case PGC3_AI32ALLDATA: // 遥测32位全数据 + pWord = (WORD *)&pSendMsg->MsgData; + pwSour = (WORD *)&hmsg->MsgData; + *pWord = SequenceHostToRtuWord(*pwSour); + + plDest = (long *)&pSendMsg->MsgData[2]; + plSour = (long *)&hmsg->MsgData[2]; + for(i=2; iMsgLen; i+=4) + { + if((i+4) > hmsg->MsgLen) + { + break; + } + + plDest[(i-2)/4] = SequenceHostToRtulong(plSour[(i-2)/4]); + } + break; + + case iDIDATA: // 变化遥信 + case iODDATA: // 离线遥信数据 + for(i=0; iMsgLen; i+=3) + { + if((i+3) > hmsg->MsgLen) + { + break; + } + pWord = (WORD *)&pSendMsg->MsgData[i]; + pwSour = (WORD *)&hmsg->MsgData[i]; + + // wen 2006.05.20 修改遥信变化数据字节转换的bug,应该为WORD类型 + //*pWord = SequenceHostToRtuDWord(*pwSour); + *pWord = SequenceHostToRtuWord(*pwSour); + pSendMsg->MsgData[i+2] = hmsg->MsgData[i+2]; + } + break; + + case iPIDATA: // 变化电度 + for(i=0; iMsgLen; i+=6) + { + if((i+6) > hmsg->MsgLen) + { + break; + } + pWord = (WORD *)&pSendMsg->MsgData[i]; + pwSour = (WORD *)&hmsg->MsgData[i]; + *pWord = SequenceHostToRtuWord(*pwSour); + + plDest = (long *)&pSendMsg->MsgData[i+2]; + plSour = (long *)&hmsg->MsgData[i+2]; + *plDest = SequenceHostToRtulong(*plSour); + } + break; + + case iSOEDATA: // SOE 数据 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iACKDATA: // 遥控遥调返校 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case WUXI_ZHUANFA_AI_TO_HOST: + pfDest = (float *)pSendMsg->MsgData; + pfSour = (float *)hmsg->MsgData; + for(i=0; iMsgLen; i+=4) + { + if((i+4) > hmsg->MsgLen) + { + break; + } + + *pfDest = SequenceHostToRtufloat(*pfSour); + } + break; + + case WUXI_ZHUANFA_PI_TO_HOST: + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iODALLDATA: // 离线遥信全数据 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iWUFANGYKYTREQ: // 五防遥控遥调请求 + for(i=0; iMsgLen; i+=8) + { + if((i+8) > hmsg->MsgLen) + { + break; + } + + pWord = (WORD *)&pSendMsg->MsgData[i]; + pwSour = (WORD *)&hmsg->MsgData[i]; + pWord[0] = SequenceHostToRtuWord(pwSour[0]); + pWord[1] = SequenceHostToRtuWord(pwSour[1]); + + piDest = (int *)&pSendMsg->MsgData[i+4]; + piSour = (int *)&hmsg->MsgData[i+4]; + *piDest = SequenceHostToRtuint(*piSour); + } + break; + + case iDIALLDATA: // 遥信全数据 + pWord = (WORD *)&pSendMsg->MsgData; + pwSour = (WORD *)&hmsg->MsgData; + *pWord = SequenceHostToRtuWord(*pwSour); + + memcpy(&pSendMsg->MsgData[2], &hmsg->MsgData[2], hmsg->MsgLen-2); + break; + + case iPIALLDATA: // 电度全数据 + pWord = (WORD *)&pSendMsg->MsgData; + pwSour = (WORD *)&hmsg->MsgData; + *pWord = SequenceHostToRtuWord(*pwSour); + + plDest = (long *)&pSendMsg->MsgData[2]; + plSour = (long *)&hmsg->MsgData[2]; + for(i=2; iMsgLen; i+=4) + { + if((i+4) > hmsg->MsgLen) + { + break; + } + + plDest[(i-2)/4] = SequenceHostToRtulong(plSour[(i-2)/4]); + } + break; + + case iBYPASSDATA: // 直通数据 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iODPOINT: // 读离线量点数据 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iANPOINT: // 读模拟量点数据 + case iDIPOINT: // 读数字量点数据 + for(i=0; iMsgLen; i+=4) + { + if((i+4) > hmsg->MsgLen) + { + break; + } + pSendMsg->MsgData[i] = hmsg->MsgData[i]; + pSendMsg->MsgData[i+1] = hmsg->MsgData[i+1]; + + pWord = (WORD *)&pSendMsg->MsgData[i+2]; + pwSour = (WORD *)&hmsg->MsgData[i+2]; + *pWord = SequenceHostToRtuWord(*pwSour); + } + break; + + case iLINESTATUS: // 端口线路状态 + memcpy(pSendMsg->MsgData, hmsg->MsgData, hmsg->MsgLen); + break; + + case iNETTESTMSG: // 网络状态包 + break; + + case iNETNAMEPLATE: // 网络标示包 + pSendMsg->MsgData[0] = hmsg->MsgData[0]; + pWord = (WORD *)&pSendMsg->MsgData[1]; + pwSour = (WORD *)&hmsg->MsgData[1]; + *pWord = SequenceHostToRtuWord(*pwSour); + break; + + default: + bRetVal = FALSE; + break; + } + + if(bRetVal == TRUE) + { + pSendMsg->MsgType = (BYTE)hmsg->MsgType; + pSendMsg->PortNumber = (BYTE)hmsg->PortNumber; + pSendMsg->MsgLen = SequenceHostToRtuWord(hmsg->MsgLen); + } + + return bRetVal; +} + +BOOL AllDataRtuToHostByteSequence(HOSTMSG *hmsg) +{ + int i; + BOOL bRetVal; + SYSTEMTIME *pTime; + + bRetVal = TRUE; + switch(hmsg->MsgType) + { + case hHOSTSTATUS: // 主机状态 + for(i = 0; i < MAX_HOST; i++) + { + SequenceRtuToHost((char *)&hmsg->MsgData[i*sizeof(int)], sizeof(int)); + } + break; + + case NET_PROFILE_UPDATE: // 主机下发更改数据库指令 + break; + + case hTIMEINFORM: // 主机对时 + pTime = (SYSTEMTIME*)hmsg->MsgData; + pTime->wYear = SequenceRtuToHostWord(pTime->wYear); + pTime->wMonth = SequenceRtuToHostWord(pTime->wMonth); + pTime->wDay = SequenceRtuToHostWord(pTime->wDay); + pTime->wHour = SequenceRtuToHostWord(pTime->wHour); + pTime->wMinute = SequenceRtuToHostWord(pTime->wMinute); + pTime->wSecond = SequenceRtuToHostWord(pTime->wSecond); + pTime->wMilliseconds = SequenceRtuToHostWord(pTime->wMilliseconds); + break; + + case hYKYTCMD: // 遥控遥调命令 + if(hmsg->MsgLen >= 10) // 多条遥调遥控命令 + { + // ??? 多帧的结构 + SequenceRtuToHost((char *)&hmsg->MsgData[1], 2); + } + else + { + // 遥控遥调反校失败 + SequenceRtuToHost((char *)&hmsg->MsgData[1], 2); + } + break; + + case hBYPASSCMD: // 直通数据 + break; + + case hMAPANDATA: // 模拟量点数据 + for(i=0; i<(int)hmsg->MsgLen; i+=4) + { + SequenceRtuToHost((char *)&hmsg->MsgData[i], sizeof(float)); + } + break; + + case hMAPDIDATA: // 数字量点数据 + break; + + case hDATA_OUTPUT_CTRL: // 数据输出控制 + break; + + case hRELOADDATABASE: // 重新装入数据库 + break; + + case hNETTESTMSG: // 网络状态包 + break; + + case hMAPALLOP: // 模拟盘全盘操作 + switch( hmsg->MsgData[0] ) + { + case 0: // 全屏操作 + SequenceRtuToHost((char *)&hmsg->MsgData[1], sizeof(DWORD)); + break; + + case 1: // 单点遥测操作 + SequenceRtuToHost((char *)&hmsg->MsgData[1], sizeof(WORD)); + SequenceRtuToHost((char *)&hmsg->MsgData[3], sizeof(float)); + break; + + case 2: // 单点遥信操作 + SequenceRtuToHost((char *)&hmsg->MsgData[1], sizeof(WORD)); + break; + } + break; + + default: + bRetVal = FALSE; + break; + } + + return bRetVal; +} +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void SendSystemTimeToHost(void) +{ + static WORD tmpm = 0; + DAY_TIME CurTime; + HOSTMSG rtumsg; + + if((SystemTimeFlag == 0) || (SystemTimeMode != 3)) + { + return; + } + + GetLocalTimeEx(&CurTime); + + if(CurTime.Sec) + { + return; + } + + if(tmpm == CurTime.Min) + { + return; + } + + tmpm = CurTime.Min; + + *(WORD*)&rtumsg.MsgData[0] = CurTime.Year; + *(WORD*)&rtumsg.MsgData[2] = CurTime.Month; + *(WORD*)&rtumsg.MsgData[4] = 0; + *(WORD*)&rtumsg.MsgData[6] = CurTime.Day; + *(WORD*)&rtumsg.MsgData[8] = CurTime.Hour; + *(WORD*)&rtumsg.MsgData[10] = CurTime.Min; + *(WORD*)&rtumsg.MsgData[12] = CurTime.Sec; + *(WORD*)&rtumsg.MsgData[14] = CurTime.mSec; + + rtumsg.MsgType = iTIMEINFORM; + rtumsg.PortNumber = 0; + rtumsg.MsgLen = 16; + + SendDataToAllHostSendBuf( (u_char*)&rtumsg, rtumsg.MsgLen + sizeof(HOSTMSGHEAD)); +} \ No newline at end of file diff --git a/tcphost.h b/tcphost.h new file mode 100644 index 0000000..a654cc9 --- /dev/null +++ b/tcphost.h @@ -0,0 +1,299 @@ +/************************************************************************************ + * + * Copyright (C) 2002-2003 SCADA Control Technology Co., Ltd. All rights reserved. + * + * $Source: /opt/CVS_ROOT_PGC_EX2000/commserver/windows/widgets/tcphost.h,v $ + * + * $Author: jehu $ + * + * $Date: 2006/07/05 07:31:44 $ + * + * $Revision: 1.1.1.1 $ + * + * $State: Exp $ + * + * $Name: $ + * + * $Locker: $ + * + * $Log: tcphost.h,v $ + * Revision 1.1.1.1 2006/07/05 07:31:44 jehu + * no message + * + * Revision 1.5 2006/05/26 10:38:03 administrator + * 增加32位模拟量传送 + * + * Revision 1.4 2006/04/22 07:49:26 administrator + * 可以屏蔽网络连接的错误信息,支持端口通讯时不切换主备机及网络连接成功的算法 + * + * Revision 1.2 2006/01/17 06:14:53 Administrator + * 增加对时、装置并列运行以及端口号偏移 + * + * Revision 1.1 2005/10/20 06:20:34 Administrator + * 新增前置机功能 + * + * Revision 1.1 2005/10/12 06:03:46 Administrator + * 增加前置机功能 + * + * + **************************************************************************************/ +//*************************************************************** +//* TcpHost.h * +//* Liangchu Lee 1999.12.20 * +//*************************************************************** + +#ifndef __TCPHOST_H_ICL__ +#define __TCPHOST_H_ICL__ + +#include "common.h" + +// 另外一个前置机装置是pc还是ds-3116 +#define FEND_OTHERDEV_DS3116 1 + +#define HOST_CLOSE_NET 1 +#define OVER_TIME_CLOSE_NET 2 +#define FEND_CLOSE_NET 3 +#define ERROR_CLOSE_NET 4 + +#define CHECK_VERSION_FLAG 1 + +// 运行方式是主备方式 +#define RUN_MODE_STANDBY 0 +// 并列方式,同时运行 +#define RUN_MODE_ALLHOT 1 + +//**************** 端口数据类型 ************************ +#define iCOMM_DATA 0x10 // RTU数据包类型 + +//************ 前置机 --> 主机 数据类型 **************** +#define iREQUESTHOSTSTATUS 0x14 // 请求主机状态 +#define iTIMEINFORM 0x2c // 前置机对时 +#define iAIDATA 0x31 // 变化遥测 +#define iDIDATA 0x32 // 变化遥信 +#define iPIDATA 0x33 // 变化电度 +#define iSOEDATA 0x34 // SOE 数据 +#define iACKDATA 0x35 // 遥控遥调返校 + +#define WUXI_ZHUANFA_AI_TO_HOST 0x36 +#define WUXI_ZHUANFA_DI_TO_HOST iDIALLDATA +#define WUXI_ZHUANFA_PI_TO_HOST 0x37 + +#define iODDATA 0x38 // 离线遥信数据 +#define iODALLDATA 0x39 // 离线遥信全数据 +#define iWUFANGYKYTREQ 0x3d // 五防遥控遥调请求 + +#define iAIALLDATA 0x40 // 遥测全数据 +#define iDIALLDATA 0x41 // 遥信全数据 +#define iPIALLDATA 0x42 // 电度全数据 +// wen 2006.05.20 32bit传送模拟量数据 +#define PGC3_AI32DATA 0x45 // 变化32位遥测数据 +#define PGC3_AI32ALLDATA 0x46 // 遥测32位全数据 + +#define iBYPASSDATA 0x50 // 直通数据 + +#define iODPOINT 0x81 // 读离线量点数据 +#define iANPOINT 0x82 // 读模拟量点数据 +#define iDIPOINT 0x83 // 读数字量点数据 +#define iLINESTATUS 0x84 // 端口线路状态 +#define iNETTESTMSG 0xf0 // 网络状态包 +#define iNETNAMEPLATE 0xef // 网络标示包 + +//************ 主机 --> 前置机 数据类型 **************** +#define hHOSTSTATUS 0x15 // 主机状态 +#define NET_PROFILE_UPDATE 0x1B // 主机下发更改数据库指令 +#define hTIMEINFORM 0x2c // 主机对时 +#define hYKYTCMD 0x35 // 遥控遥调命令 +#define hBYPASSCMD 0x50 // 直通数据 +#define hMAPANDATA 0x82 // 模拟量点数据 +#define hMAPDIDATA 0x83 // 数字量点数据 +#define hDATA_OUTPUT_CTRL 0x85 // 数据输出控制 +#define hRELOADDATABASE 0x86 // 重新装入数据库 +#define hNETTESTMSG 0xf0 // 网络状态包 +#define hMAPALLOP 0xf4 // 模拟盘全盘操作 + + +//*********************数据缓冲区************************ +#define AIMSGNO 0 +#define DIMSGNO 1 +#define SOEMSGNO 2 +#define YKYTACKNO 3 +#define ODMSGNO 4 +#define PIMSGNO 5 +#define RTUCHANGMSGNUM 6 + +//****************************************************** + +typedef struct tagTCP_SEND_DATA_BUF +{ + int MsgLen __attribute__ ((packed)); + BYTE MsgData[MAX_NET_BUF] __attribute__ ((packed)); +} TCP_SEND_DATA_BUF; + +typedef struct tagTCP_RCV_DATA_BUF +{ + int MsgCnt __attribute__ ((packed));// 信息内容计数 + int Front __attribute__ ((packed));// 信息取数指针 + int Rear __attribute__ ((packed));// 信息存入指针 + BYTE MsgData[MAX_NET_BUF] __attribute__ ((packed));// 信息数据 +} TCP_RCV_DATA_BUF; + +typedef struct tagFEND_DEF +{ + char Name[MAX_MACHINE_NAME_LEN] __attribute__ ((packed)); + int FendIdx __attribute__ ((packed)); + int LinkFlag __attribute__ ((packed)); + int EnableLink __attribute__ ((packed)); + char SetTcpIpAddr[MAX_FEND*MAX_ADDR][TCPIP_ADDR_LEN] __attribute__ ((packed)); + char TcpIpAddr[MAX_ADDR][TCPIP_ADDR_LEN] __attribute__ ((packed)); + u_long HostIpAddr[MAX_ADDR] __attribute__ ((packed)); + u_long AllIpAddr[MAX_ADDR] __attribute__ ((packed)); + u_long BroadCastAddr[MAX_ADDR] __attribute__ ((packed)); + int LinkStatus[MAX_FEND] __attribute__ ((packed)); + int LinkCnt[MAX_FEND] __attribute__ ((packed)); + + int FendExistFlag[MAX_FEND] __attribute__ ((packed)); + int FendExistCnt[MAX_FEND] __attribute__ ((packed)); + + int SendTxdDataFlag[MAX_FEND] __attribute__ ((packed)); + + // wen 2006.01.14 增加装置的起始厂站号的偏移 + int iPortOffset __attribute__ ((packed)); + int iRunMode __attribute__ ((packed)); + + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + int iPortMask __attribute__ ((packed)); + + // wen 2006.05.20 32bit传送模拟量数据 + int iSendAiof32Bit __attribute__ ((packed)); +} FEND_DEF; + +typedef struct tagTCP_LINK_DEF +{ + u_char InitFlag __attribute__ ((packed));// 初始化标志 + u_char InitOk __attribute__ ((packed));// 初始化成功标志 + long InitLinkCnt __attribute__ ((packed));// 初始化计数 + + char ExistFlag __attribute__ ((packed));// 存在标志 + u_char CommFlag __attribute__ ((packed));// 通讯标志 + u_char Status __attribute__ ((packed));// 工作状态 + long StatusCnt __attribute__ ((packed));// 状态计数 + SOCKET SocketId __attribute__ ((packed));// 连接号 + + u_char LinkType __attribute__ ((packed));// 连接类型 + + char CurLinkIdx __attribute__ ((packed)); + u_char TcpIpAddr[MAX_ADDR][TCPIP_ADDR_LEN] __attribute__ ((packed));// Tcp/Ip 地址 + + u_char VersionFalgByte __attribute__ ((packed));// 服务器版本号标志 + int RevHostStatusMsg __attribute__ ((packed));// 接收主机广播信息 + + char NetNameplateFalg __attribute__ ((packed)); + + int iNoWriteNum __attribute__ ((packed)); +} TCP_LINK_DEF; + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 兼容老系统的RTUMSG结构 +typedef struct tagORTUMSGHEAD +{ + u_char MsgType __attribute__ ((packed));// 信息类型 + u_char PortNumber __attribute__ ((packed));// 信息端口号 + short MsgLen __attribute__ ((packed));// 信息长度 +} ORTUMSGHEAD; + +typedef struct tagORTUMSG +{ + u_char MsgType __attribute__ ((packed));// 信息类型 + u_char PortNumber __attribute__ ((packed));// 信息端口号 + short MsgLen __attribute__ ((packed));// 信息长度 + u_char MsgData[MAX_RTU_MSG_SIZE] __attribute__ ((packed));// 信息数据 +} ORTUMSG; + +typedef struct tagHOSTMSGHEAD +{ + WORD MsgType __attribute__ ((packed));// 信息类型 + WORD PortNumber __attribute__ ((packed));// 信息端口号 + WORD MsgLen __attribute__ ((packed));// 信息长度 + WORD EMsgLen __attribute__ ((packed));// 扩展信息长度 +} HOSTMSGHEAD; + +typedef struct tagHOSTMSG +{ + WORD MsgType __attribute__ ((packed));// 信息类型 + WORD PortNumber __attribute__ ((packed));// 信息端口号 + WORD MsgLen __attribute__ ((packed));// 信息长度 + WORD EMsgLen __attribute__ ((packed));// 扩展信息长度 + u_char MsgData[MAX_RTU_MSG_SIZE] __attribute__ ((packed));// 信息数据 +} HOSTMSG; +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +BOOL GetConfigName(char *szFileName, int iFileNameLen, int IsPortConfig); +BOOL IsWouldBlock(); +BOOL IsWouldBlockEx(int neterrno); +int GetNetErrorNo(); +void CloseNetSocket(SOCKET sock); +void ULongToIPString(char *ipstr, u_long ipulong); + +void InitSetTcpIpAddr(void); + +void SendNetNameplateMsgToHost(int flag); +BOOL InitFendMsg(void); +BOOL InitHostWSAStartup(void); +void FindCurrentFend(void); +void LinkOneHost(int hostid); +void HostConnect(SOCKET socket, WORD error); +void LinkToHost(void); +void CloseHostSocket(SOCKET socket, int flag); +void CloseHost(void); +BOOL ReadHost(int hostid); +int GetHostMsgFormHostRevBuf(HOSTMSG *hostmsg, int hostid); +BOOL ReadDataFormHost(SOCKET socket); +int SendDataToHostSendBuf(int hostid, u_char *buf, int len, BOOL bInsert); +void SendDataToAllHostSendBuf(u_char *buf, int len); +void SendHostSendBufToHost(void); +void ClearSendBuffer(int hostid); +void ClearRecvBuffer(int hostid); + +// 服务器数据处理及发送 +void HostDataProceWithSignalYkYt(HOSTMSG *hmsg); +void HostDataProce(HOSTMSG *hostmsg); +void SendRtuChangeDataToHost(void); +void SendPortStatisticsToHost(void); +void SendPortStatusToHost(int flag); +void SendPortAllDataToHost(void); +void SetSoeData(int commidex, SOE_DEF *pSoeData); +void SetYkYtAckData(int portno, char *buf); + +void SelectHostSocketEvent(void); +void SelectHostSocketEventEx(void); +void TcpHostTimer(void); + +// 服务器模拟盘数据处理 +void MapAnPointToHost(int iMapOutPort, int iMapSavePort); +void MapDiPointToHost(int iMapOutPort, int iMapSavePort); +void FormHostMapDataProce(int iMapOutPort, int iMapSavePort, HOSTMSG *msg); + +// 获取前置机的下发标识 +int GetFendTxdFlag(void); + +// 判断网络地址是否是前置机地址 +int CheckIsFendIpAddr(u_long addr); + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 前置机功能函数 +void WriteChangeData(int commidex, int point, void *pntmsg, BYTE type); +BOOL IsSendDatatoPort(int port); +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// 获取全局变量 +TCP_LINK_DEF *GetHostLinkPtr(); +FEND_DEF *GetFendMsgPtr(); +HOSTMSG *GetRtuChangeMsgPtr(); + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 增加字节顺序转换函数 +BOOL AllDataHostToRtuByteSequence(HOSTMSG *hmsg, ORTUMSG *pSendMsg); +BOOL AllDataRtuToHostByteSequence(HOSTMSG *hmsg); +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void SendSystemTimeToHost(void); +#endif diff --git a/typedef.h b/typedef.h new file mode 100644 index 0000000..3ecc03c --- /dev/null +++ b/typedef.h @@ -0,0 +1,372 @@ +/************************************************************************************* +* +* Copyright (C) 1999-2000 SCADA Technology Control Co., Ltd. All rights reserved. +* +* 作者: 杨小波 +* +* 日期: 2001/08/07 +* +* 说明: +* 最基本的类型定义. +* 1: 基本类型的长度(字节单位) +* 2: 定义可移植类型 +* +*************************************************************************************/ + +#ifndef __TYPEDEF_H__DFJGLWREPUEPISXVCMAFGLJHQEWPYRPEOAJLKGZNCNALDHFPQEWUPOQRJSJHGAQ +#define __TYPEDEF_H__DFJGLWREPUEPISXVCMAFGLJHQEWPYRPEOAJLKGZNCNALDHFPQEWUPOQRJSJHGAQ +/*! + * \if developer_doc + * \file + * + * \brief 最基本的类型定义 + * + * id: $Id: typedef.h,v 1.2 2006/08/04 03:37:33 zhuzhenhua Exp $ + * + * \author 杨小波 prcharold@sina.com.cn develop1@szscada.com + * \endif + */ + +#include + +/*! + * 定义最基本的类型, 这些类型可以在不同的操作系统中保持字节长度不变, + * 便于在不同的操作系统环境中, PGC系列软件之间交换数据和文件 + * + * 单字节数据类型 //(SIZE_OF_CHAR = sizeof(char)) + */ + +#define SIZE_OF_CHAR 1 +#if SIZE_OF_CHAR == 1 +typedef char pgcchar; +typedef char pgc8; +typedef signed char int8; +typedef signed char i_8; +typedef unsigned char u_char; +typedef unsigned char pgcu_char; +typedef unsigned char pgcbyte; +typedef unsigned char PGCBYTE; +typedef unsigned char pgcu8; +typedef unsigned char u_8; +typedef unsigned char BYTE; +#else +#error "Please choose a 1 byte data type to redefine pgcchar." +#endif /* SIZE_OF_CHAR == 1 */ + + +#define SIZE_OF_SHORT 2 +/*! + * 双字节 //(SIZE_OF_SHORT = sizeof(short)) + */ +#if SIZE_OF_SHORT == 2 +typedef short pgc16; +typedef short int16; +typedef short i_16; +typedef unsigned short pgcu16; +typedef unsigned short pgcword; +typedef unsigned short PGCWORD; +typedef unsigned short u_16; +typedef unsigned short u_short; +typedef unsigned short WORD; +#else +#error "Please choose a 2 byte data type to redefine pgc16." +#endif //SIZE_OF_SHORT == 2 + +#define SIZE_OF_LONG 4 +#define SIZE_OF_INT 4 +/*! + * 双字节 (SIZE_OF_LONG = sizeof(long)) + */ +#if SIZE_OF_LONG == 4 && SIZE_OF_INT == 4 +typedef int pgc32; +typedef int int32; +typedef unsigned int pgcu32; +typedef unsigned int pgcdword; +typedef unsigned int PGCDWORD; +typedef unsigned int u32; +/*#if OS_WINDOWS +typedef unsigned int DWORD; +#endif //OS_WINDOWS*/ +#elif SIZE_OF_LONG == 4 +typedef long pgc32; +typedef long int32; +typedef long i_32; +typedef unsigned long pgcu32; +typedef unsigned long pgcdword; +typedef unsigned long PGCDWORD; +typedef unsigned long u_32; +typedef unsigned long DWORD; +#elif SIZE_OF_INT == 4 //(SIZE_OF_INT = sizeof(ing)) +#ifndef _INTEGER_32BIT +#define _INTEGER_32BIT +typedef int pgc32; +typedef int int32; +typedef int i_32; +typedef unsigned int pgcu32; +typedef unsigned int pgcdword; +typedef unsigned int PGCDWORD; +typedef unsigned int u_32; +typedef unsigned int DWORD; +# endif +#else +#error "Please choose a 4 byte data type to redefine pgc32." +#endif //SIZE_OF_LONG == 4 and SIZE_OF_INT == 4 + +#define SIZE_OF_LONG 8 +/*! + * 8字节 (SIZE_OF_LONG == sizeof(long)) + */ +#if SIZE_OF_LONG == 8 +typedef long pgc64; +typedef long int64; +typedef long i_64; +typedef unsigned long pgcu64; +typedef unsigned long pgcddword; +typedef unsigned long PGCDDWORD; +typedef unsigned long u_64; +typedef unsigned long DDWORD; +#elif OS_WINDOWS +typedef __int64 pgc64; +typedef __int64 int64; +typedef __int64 i_64; +typedef unsigned __int64 pgcu64; +typedef unsigned __int64 pgcddword; +typedef unsigned __int64 PGCDDWORD; +typedef unsigned __int64 u_64; +typedef unsigned __int64 DDWORD; +#else +typedef int64_t pgc64; +typedef int64_t int64; +typedef int64_t i_64; +typedef u_int64_t pgcu64; +typedef u_int64_t pgcddword; +typedef u_int64_t PGCDDWORD; +typedef u_int64_t u_64; +typedef u_int64_t DDWORD; +#endif //SIZE_OF_LONG == 8 + +#define SIZE_OF_PTR 4 +/*! + * 指针 (SIZE_OF_PTR == sizeof(void *)) + */ +#if SIZE_OF_PTR == 4 +typedef pgc32 PGCPTR; +typedef pgc32 PTR; +typedef pgcu32 PGCUPTR; +typedef pgcu32 UPTR; +#elif SIZE_OF_PTR == 8 +typedef pgc64 PGCPTR; +typedef pgc64 PTR; +typedef pgcu64 PGCUPTR; +typedef pgcu64 UPTR; +#else +#error "Please choose a data type, which size is acturally the size of pointer, to present PGCPTR" +#endif + + +/*! + * PGCBOOL自定义类型 -- 表达SCADA布尔量 + */ +//#ifndef __PGCBOOL_DEF__ +//#define __PGCBOOL_DEF__ +typedef pgcu8 PGCBOOL; +#define PGCTRUE ((PGCBOOL)1) +#define PGCFALSE ((PGCBOOL)0) +//#endif //__PGCBOOL_DEF__ + +//#if OS_WINDOWS +//# ifndef key_t + typedef int key_t; +//# endif +//#endif // OS_WINDOWS + +/*! + * ipc别名定义. + * + * 共享内存键值, 共享内存id, 信号量键值, 信号量id, 消息队列键值, 消息队列id + * + */ +typedef key_t shmkey_t, SHMKEY_t; // 共享内存键值 +typedef int shmid_t, SHMID_t; // 共享内存id + +typedef key_t semkey_t, SEMKEY_t; // 信号量键值 +typedef int semid_t, SEMID_t; // 信号量id + +typedef key_t msgkey_t, MSGKEY_t; // 消息队列键值 +typedef int msgid_t, MSGID_t; // 消息队列id + + + +/*! + * 无效的共享内存映射地址(-1) + */ +#define SHM_ADDR_INVALID ((void *)(-1)) + + +/*! + * 和windows兼容的布尔类型定义BOOL + */ +typedef int BOOL; + + +/*! CAUTIOUS +* 如果, 以后站号, 点号类型的数据类型定义发生变化, 则需要修改该行 +* +* 站号, 点号类型定义 +*/ +typedef int32 stn_no_t; +typedef int32 pnt_no_t; + +/*! + * 历史数据采样类型定义 + */ +typedef i_8 sampling_type_t; + +/*! + * 在TRU64上, pthread_t的长度等于8, 而在linux(intel)上, pthread_t的长度 + * 等于4, 所以为了兼容, 定义thd_id_t的长度为8个字节, 因此, 在非64位平台 + * 上, 使用一个结构来代替 + * + * 线程标识符(id)类型定义 + */ +#if defined(OS_LINUX) // unix平台(肯定使用posix线程库) + #if SIZE_OF_PTHREAD_T == 8 + typedef pthread_t thd_id_t; + #elif SIZE_OF_PTHREAD_T == 4 + typedef struct + { + //! 低32位上定义thd_id + pthread_t thd_id; + + //! 高32位保留 + i_32 reserved; + + } thd_id_t; + #endif +#else + #if SIZE_OF_PTHREAD_T == 8 + typedef long thd_id_t; + #elif SIZE_OF_PTHREAD_T == 4 + typedef struct + { + //! 低32位上定义thd_id + u_32 thd_id; + + //! 高32位保留 + i_32 reserved; + + } thd_id_t; + #endif +#endif + +/*! + * 便于移植和修改的数据类型定义. + * + * 网络套接字类型 + */ +typedef int socket_t, SOCKET_t; + +#define SOCKET_INVALID ((socket_t)-1) + +#if defined(OS_LINUX) +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (SOCKET_INVALID) +#endif //end of INVALID_SOCKET +#endif //end of defined(__unix) + +/*! + * ip地址定义 + */ +//typedef u_32 ip_addr_t; + +#endif //__TYPEDEF_H__DFJGLWREPUEPISXVCMAFGLJHQEWPYRPEOAJLKGZNCNALDHFPQEWUPOQRJSJHGAQ + +/************************************************************************************* +* +* $Revision: 1.2 $ +* +* $Date: 2006/08/04 03:37:33 $ +* +* $State: Exp $ +* +* $Log: typedef.h,v $ +* Revision 1.2 2006/08/04 03:37:33 zhuzhenhua +* no message +* +* Revision 1.11 2003/09/19 07:55:15 scada +* no message +* +* Revision 1.10 2003/08/01 06:36:19 scada +* 在Win32平台上借用__int64定义64bit的整数 +* +* Revision 1.9 2003/07/01 01:31:01 scada +* no message +* +* Revision 1.8 2003/06/05 03:56:15 jehu +* 将注释修改为符合doxgen工具提取开发文档 +* +* Revision 1.7 2003/01/10 10:38:40 scada +* no message +* +* Revision 1.6 2003/01/02 03:14:32 scada +* trim substitution line +* +* Revision 1.5 2002/12/04 07:47:36 scada +* for NT +* +* Revision 1.4 2002/10/07 05:37:59 harold +* cvs up -d +* +* Revision 1.3 2002/09/18 09:13:38 harold +* revised errors and warning under solaris/CC environment +* +* Revision 1.2 2002/08/26 02:07:32 harold +* 重新定义stn_no_t, pnt_no_t, sampling_type_t, 由无符号整数-->有符号整数 +* +* Revision 1.1.1.1 2002/08/21 07:16:36 harold +* temporarily import +* +* Revision 1.9 2002/03/20 03:39:57 harold +* no message +* +* Revision 1.2 2002/03/17 15:33:52 harold +* changed for iccp v0.9 +* +* Revision 1.1.1.1 2002/03/15 13:43:17 harold +* no message +* +* Revision 1.1.1.1 2002/03/15 08:17:07 harold +* no message +* +* Revision 1.8 2002/03/05 03:01:34 harold +* *** empty log message *** +* +* Revision 1.7 2002/03/04 14:04:39 harold +* *** empty log message *** +* +* Revision 1.6 2002/01/15 10:37:07 harold +* no message +* +* Revision 1.5 2002/01/15 10:25:42 harold +* no message +* +* Revision 1.4 2002/01/15 10:20:11 harold +* no message +* +* Revision 1.3 2002/01/15 09:55:29 harold +* no message +* +* Revision 1.2 2002/01/15 08:44:34 harold +* 添加线程id类型定义thd_id_t +* +* Revision 1.1.1.1 2001/12/24 09:33:23 harold +* no message +* +* Revision 1.2 2001/12/24 06:39:57 harold +* 为了适应不同的操作系统, 不同的CPU类型, 及不同的编译器, +* 对头文件做了相应的修改, 同时添加了一些宏定义, 如: +* HAVE__FUNCTION__, __OS__, __PLATFORM__,__TIMEZONE__等等. +* +* +* +************************************************************************************/ diff --git a/udpcomm.cpp b/udpcomm.cpp new file mode 100644 index 0000000..16f4da8 --- /dev/null +++ b/udpcomm.cpp @@ -0,0 +1,962 @@ + + +//#include "stdafx.h" +#include "udpcomm.h" +#include "commport.h" +#include "udpping.h" +#include "tcphost.h" +//#include "qt_public.h" +//#include +//#include "WidgetMainWnd.h" + +extern FUNCTION_CALL *FunCallPtr; +extern SIO_PARAM_DEF SioParam[]; + +extern int CurPort; +extern int RealDataDispFlag; +extern char IniFilePath[256]; + +int giRealDataToFile = 1; + +UDP_SET_DEF UdpParam; +HOST_IP_ADDR HostIpAddr; + +int UdpParamInitFlag = 0; + +int iDevNum = 0; +int iCurDevIdx = 0; +DEV_DEF DevParam[MAX_DEV_NUM]; + +int SendCnt = 0; +int RecvCnt = 0; + +char gCurConfigFileName[512]; + +void InitGlobalMember() +{ + memset(gCurConfigFileName, 0, sizeof(gCurConfigFileName)); +} + +void GetHostIpAddr(void) +{ + int i; + WSADATA WSAData; + struct hostent *test; + struct in_addr *addr, inaddr; + char name[256]; + + memset((char*)&HostIpAddr, 0, sizeof(HOST_IP_ADDR)); + + if(WSAStartup(MAKEWORD(2, 1), (LPWSADATA)&WSAData) != 0) + return; + + gethostname(name, 100); + test = gethostbyname(name); + + test->h_addrtype = test->h_addrtype; + + for (i = 0; i < MAX_NET_NUM; i++) + { + addr = (struct in_addr *)test->h_addr_list[i]; + if(addr == NULL) + break; + + inaddr = *((in_addr *)test->h_addr_list[i]); + + HostIpAddr.AllIpAddr[i] = ntohl(inaddr.S_un.S_addr); + + if(IN_CLASSA(HostIpAddr.AllIpAddr[i])) /*A类地址*/ + { + HostIpAddr.NetMaskIpAddr[i] = IN_CLASSA_NET; + HostIpAddr.MainIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSA_NET); + HostIpAddr.BroadCastIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSA_NET) | IN_CLASSA_HOST; + } + else if(IN_CLASSB(HostIpAddr.AllIpAddr[i])) /*B类地址*/ + { + HostIpAddr.NetMaskIpAddr[i] = IN_CLASSB_NET; + HostIpAddr.MainIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSB_NET); + HostIpAddr.BroadCastIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSB_NET) | IN_CLASSB_HOST; + } + else if(IN_CLASSC(HostIpAddr.AllIpAddr[i])) /*C类地址*/ + { + HostIpAddr.NetMaskIpAddr[i] = IN_CLASSC_NET; + HostIpAddr.MainIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSC_NET); + HostIpAddr.BroadCastIpAddr[i] = (HostIpAddr.AllIpAddr[i] & IN_CLASSC_NET) | IN_CLASSC_HOST; + } + } +} + +//创建用于系统配置的UDP socket +void CreatUdpSetSock(void) +{ + int tmp; + char szConfig[256]; + + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szConfig, "%s/config.ini", IniFilePath); + + if(UdpParamInitFlag == 0) + { + memset((char*)&UdpParam, 0, sizeof(UDP_SET_DEF)); + + UdpParam.PortNumber = GetPrivateProInt("NetCommPort", "UdpCommPort", 0, szConfig); + if(UdpParam.PortNumber == 0) + { + UdpParam.PortNumber = DEFAULT_UDP_COMM_PORT; + } + + GetHostIpAddr(); + UdpParamInitFlag = 1; + } + + if(UdpParam.Socket) + return; + + UdpParam.Socket = socket(AF_INET, SOCK_DGRAM, 0); + if(UdpParam.Socket <= 0) + { + UdpParam.Socket = 0; + return; + } + + // wen 2005.12.01 在这里初始化数据 + InitGlobalMember(); + + //设置socket输入输出绶冲 + tmp = MAX_NET_BUF_SIZE; + setsockopt(UdpParam.Socket, SOL_SOCKET, SO_RCVBUF, (char*)&tmp, sizeof(tmp)); + tmp = MAX_NET_BUF_SIZE; + setsockopt(UdpParam.Socket, SOL_SOCKET, SO_SNDBUF, (char*)&tmp, sizeof(tmp)); + + tmp = 1; + setsockopt(UdpParam.Socket, SOL_SOCKET, SO_BROADCAST, (char*)&tmp, sizeof(tmp)); // 广播 + + //让配置socket 能收不同网段的配置命令 + memset(&UdpParam.Addr, 0, sizeof(UdpParam.Addr)); + UdpParam.Addr.sin_family = AF_INET; + UdpParam.Addr.sin_port = htons(UdpParam.PortNumber); + + // wen 2005.03.08 修改ip为指定的地址 + UdpParam.Addr.sin_addr.s_addr = htonl(INADDR_ANY); + //UdpParam.Addr.sin_addr.s_addr = inet_addr("192.168.1.200"); + + if(bind(UdpParam.Socket, (struct sockaddr *)&UdpParam.Addr, sizeof(UdpParam.Addr)) < 0) + { + // windows + //DWORD dwerror = GetLastError(); + + closesocket(UdpParam.Socket); + UdpParam.Socket = 0; + } +} + +void CloseUdpSetSock(void) +{ + if(UdpParam.Socket) + { + closesocket(UdpParam.Socket); + } + + UdpParam.Socket = 0; +} + +int CheckIsMySelftIpAddr(u_long addr) +{ + int i; + + for(i = 0; i < MAX_NET_NUM; i++) + { + if(addr == HostIpAddr.AllIpAddr[i]) + { + return true; + } + } + +// 定义前置机功能 +#ifdef FUNCTION_FEND +#if (FEND_OTHERDEV_DS3116 == 0) + // 非ds-3116设备时,需要用他来确定是否为另一个前置机 + return CheckIsFendIpAddr(addr); +#endif +#endif + + return false; +} + +int CheckIsCurDevIpAddr(u_long addr) +{ + //int i; + + //for(i = 0; i < MAX_NET_NUM; i++) + { + if(addr == DevParam[iCurDevIdx].CurCommIp) + { + return true; + } + } + + return false; +} + +//接收网络配置网络命令 +void SetUdpRecv(void) +{ + struct timeval outtime; + int len; + int addr_len = sizeof(struct sockaddr_in); + fd_set set; + u_char recvbuf[MAX_NET_BUF_SIZE]; + //char szDbg[128]; + + CreatUdpSetSock(); + + if(UdpParam.Socket == 0) + return; + + memset((char*)&outtime, 0, sizeof(struct timeval)); + memset((char*)&UdpParam.Addr, 0, sizeof(UdpParam.Addr)); + FD_ZERO(&set); + FD_SET(UdpParam.Socket, &set); + + for(; ;) + { + //异步收 + if(select(FD_SETSIZE, &set, NULL, NULL, &outtime) < 1) + break; + + len = recvfrom(UdpParam.Socket, (char*)recvbuf, MAX_NET_BUF_SIZE,0, (struct sockaddr *)&UdpParam.Addr, &addr_len) ; + + if(len < 1) + break; + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.09.28 增加对udp通讯端口的显示 + if(RealDataDispFlag) + { + if((CurPort == GetMaxPort()) && (CheckIsCurDevIpAddr(ntohl(UdpParam.Addr.sin_addr.s_addr)))) + { + RTUMSG *msg; + WORD wLen, wType; + BYTE *ptr; + + msg = (RTUMSG *)recvbuf; + if(IsNetSequence() == TRUE) + { + wType = msg->MsgType; + wLen = msg->MsgLen; + } + else + { + ptr = (BYTE *)&msg->MsgType; + wType = ptr[0] * 256 + ptr[1]; + ptr = (BYTE *)&msg->MsgLen; + wLen = ptr[0] * 256 + ptr[1]; + } + WatchDataPutDispBuf(msg->PortIdx, SDS_SIO_RECV_DATA, msg->MsgData, wLen); + } + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if(CheckIsMySelftIpAddr(ntohl(UdpParam.Addr.sin_addr.s_addr)) == false) + { + /* + if(UdpParam.Addr.sin_addr.S_un.S_addr != 0xd802a8c0) + { + sprintf(szDbg, "IP(recv): %d.%d.%d.%d:%d", + UdpParam.Addr.sin_addr.S_un.S_un_b.s_b1, + UdpParam.Addr.sin_addr.S_un.S_un_b.s_b2, + UdpParam.Addr.sin_addr.S_un.S_un_b.s_b3, + UdpParam.Addr.sin_addr.S_un.S_un_b.s_b4, + UdpParam.Addr.sin_port); + DebugPrint(szDbg); + } + */ + + void SetUdpRecvDataProcess(u_long ipaddr, u_char *buf, int len); + SetUdpRecvDataProcess(ntohl(UdpParam.Addr.sin_addr.s_addr), recvbuf, len); + } + //else + //{ + // DebugPrint("Recv self."); + //} + } +} + +//发送配置命令,引入IP地址,可以自由采用点对点,全网广播发送方式 +int SetUdpSend(u_long ipaddr, char *buf, int len) +{ + struct sockaddr_in addr; + int slen; + + if(UdpParam.Socket == 0) + { + return false; + } + +// 定义前置机功能 +#ifdef FUNCTION_FEND + // wen 2005.10.12 增加是否下发前置机的判断 +#if (FEND_OTHERDEV_DS3116 == 0) + if(GetFendTxdFlag() == 0) + { + return false; + } +#endif +#endif + + if(len == 0) + { + return false; + } + + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(UdpParam.PortNumber); + addr.sin_addr.s_addr = ntohl(ipaddr); + + slen = sendto(UdpParam.Socket, buf, len, 0, + (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); + + if(slen != len) + { + closesocket(UdpParam.Socket); + UdpParam.Socket = 0; + + return false; + } + else + { + RTUMSG *msg; + WORD wLen, wType; + BYTE *ptr; + + wLen = 0x55AA; + ptr = (BYTE *)&wLen; + + msg = (RTUMSG *)buf; + if(ptr[0] == 0x55) + { + wType = msg->MsgType; + wLen = msg->MsgLen; + } + else + { + ptr = (BYTE *)&msg->MsgType; + wType = ptr[0] * 256 + ptr[1]; + ptr = (BYTE *)&msg->MsgLen; + wLen = ptr[0] * 256 + ptr[1]; + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2005.09.28 增加对udp通讯端口的显示 + /*if((CurPort == msg->PortIdx) && RealDataDispFlag) + { + if(SDS_SIO_SEND_DATA == wType) + { + WatchDataPutDispBuf(msg->PortIdx, SDS_SIO_SEND_DATA, msg->MsgData, wLen); + } + }*/ + if(RealDataDispFlag) + { + if(CurPort == msg->PortIdx) + { + if(SDS_SIO_SEND_DATA == wType) + { + WatchDataPutDispBuf(msg->PortIdx, SDS_SIO_SEND_DATA, msg->MsgData, wLen); + } + } + else if(CurPort == GetMaxPort()) + { + WatchDataPutDispBuf(msg->PortIdx, SDS_SIO_SEND_DATA, msg->MsgData, wLen); + } + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + + return true; +} + +//填充配置结果,返包到上行绶冲 +int FillAndSendCmd(u_long ipaddr, u_char port, WORD cmd, u_char *retbuf, int len) +{ + RTUMSG rtumsg; + u_char *ptr; + int tmp = 0; + + rtumsg.PortIdx = port; + ptr = (u_char*)&rtumsg.MsgType; + ptr[0] = HIBYTE(cmd); + ptr[1] = LOBYTE(cmd); + ptr[2] = HIBYTE(len); + ptr[3] = LOBYTE(len); + + if(len) + memmove((char *)rtumsg.MsgData, retbuf, len); + + if(ipaddr) + tmp = SetUdpSend(ipaddr, (char*)&rtumsg, sizeof(RTUMSGHEAD) + len); + else + { + if(DevParam[iCurDevIdx].CurCommIp) + tmp = SetUdpSend(DevParam[iCurDevIdx].CurCommIp, (char*)&rtumsg, sizeof(RTUMSGHEAD) + len); + } + + return tmp; +} + +int GetSdsIpAddr(void) +{ + /*SYSTEMTIME sm; + char szInfo[128]; + + GetLocalTime(&sm); + sprintf(szInfo, "%02d_%02d:%02d:%02d.%03d GetSdsIpAddr\n", + sm.wDay, sm.wHour, sm.wMinute, sm.wSecond, sm.wMilliseconds); + OutputDebugString(szInfo);*/ + + return FillAndSendCmd(INADDR_BROADCAST, 0, SDS_N_GET_IP_ADDR, NULL, 0); +} + +void ValueToBuf(u_char *buf, u_long val, int len) +{ + switch(len) + { + case 2: + buf[0] = HIBYTE(LOWORD(val)); + buf[1] = LOBYTE(LOWORD(val)); + break; + case 4: + buf[0] = HIBYTE(HIWORD(val)); + buf[1] = LOBYTE(HIWORD(val)); + buf[2] = HIBYTE(LOWORD(val)); + buf[3] = LOBYTE(LOWORD(val)); + break; + } +} + +u_long BufToValue(u_char *buf, int len) +{ + u_long retv; + + switch(len) + { + case 2: + retv = BYTE1(buf[0]) + BYTE0(buf[1]); + break; + + case 4: + retv = BYTE3(buf[0]) + BYTE2(buf[1]) + BYTE1(buf[2]) + BYTE0(buf[3]); + break; + } + return retv; +} + +void AddDispLine(DISP_LINE_BUF *dispbuf, char *msg) +{ + char szbuf[128], tmp[128]; + int k; + + k = strlen(msg); + if(k == 0) + return; + + if(k > 120) + msg[120] = 0; + + k = 120 - strlen(msg); + + strcpy(szbuf, msg); + if(k > 0) + { + memset(tmp, ' ', 120); + tmp[k] = 0; + + strcat(szbuf, tmp); + } + + strcpy(dispbuf->Line[dispbuf->Rear], szbuf); + dispbuf->Rear = (dispbuf->Rear + 1) % MAX_DISP_LINE; + + // 当缓冲区满后, 丢掉前半个缓冲区内数据,否则, + // 我们无法停下来观看已有数据,它可能一直滚动, + // 因为每添加一行我们的指针不得不退让一行 + dispbuf->LineCnt = dispbuf->LineCnt + 1; + if(dispbuf->LineCnt == MAX_DISP_LINE) + { + dispbuf->LineCnt -= MAX_DISP_LINE / 2; + } +} + +void WatchDataPutDispBuf(int port, WORD type, u_char *buf, int len) +{ + int i, j, k, linechar; + char szbuf[256], tmp[256], tchar; + SYSTEMTIME st; + + if(giRealDataToFile == 1) + { + WatchDataPutDispBufToFile(port, type, buf, len); + return; + } + + linechar = 18; + + tchar = type == SDS_SIO_SEND_DATA ? 'S' : 'R'; + + GetLocalTime(&st); + + szbuf[0] = tchar; + sprintf((char*)&szbuf[1], "%04d-%02d-%02d %02d:%02d:%02d.%03d 端口%d %s 数据, 长度 = %d", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, + port + 1, type == SDS_SIO_SEND_DATA ? "发送" : "接收", len); + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); + + for (i = 0; i < len; i += linechar) + { + szbuf[0] = tchar; + sprintf((char*)&szbuf[1], "%04d: ", i); + + k = min(linechar, len - i); + + for (j = 0; j < k; j++) + { + sprintf(tmp, "%02X ", buf[i+j]); + strcat(szbuf, tmp); + if(((j + 1) % 6) == 0) + strcat(szbuf, " "); + } + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); + } + + sprintf(szbuf, "%c", tchar); + strcat(szbuf, " "); + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); +} + +void WatchDataPutDispBufToFile(int port, WORD type, u_char *buf, int len) +{ + int i, j, k, linechar; + char szbuf[256], tmp[256], tchar; + char szFileName[256]; + FILE *fp; + SYSTEMTIME st; + + linechar = 18; + + tchar = type == SDS_SIO_SEND_DATA ? 'S' : 'R'; + + GetLocalTime(&st); + + //getcwd(szFileName, sizeof(szFileName)); + sprintf(szFileName, "%s\\log\\realdata%02d.txt", IniFilePath, port+1); + fp = fopen(szFileName, "a"); + + szbuf[0] = tchar; + sprintf((char*)&szbuf[1], "%04d-%02d-%02d %02d:%02d:%02d.%03d 端口%d %s 数据, 长度 = %d", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, + port + 1, type == SDS_SIO_SEND_DATA ? "发送" : "接收", len); + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); + + if(fp) + { + strcat(szbuf, "\n"); + fwrite(szbuf, sizeof(char), strlen(szbuf), fp); + } + + for (i = 0; i < len; i += linechar) + { + szbuf[0] = tchar; + sprintf((char*)&szbuf[1], "%04d: ", i); + + k = min(linechar, len - i); + + for (j = 0; j < k; j++) + { + sprintf(tmp, "%02X ", buf[i+j]); + strcat(szbuf, tmp); + if(((j + 1) % 6) == 0) + strcat(szbuf, " "); + } + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); + + if(fp) + { + strcat(szbuf, "\n"); + fwrite(szbuf, sizeof(char), strlen(szbuf), fp); + } + } + + sprintf(szbuf, "%c", tchar); + strcat(szbuf, " "); + + AddDispLine(&DevParam[iCurDevIdx].WatchDispLine, szbuf); + + if(fp) + { + strcpy(szbuf, " \n"); + fwrite(szbuf, sizeof(char), strlen(szbuf), fp); + fclose(fp); + } +} + +int FindDev( u_long ipaddr ) +{ + int i, j; + + for ( i = 0; i < iDevNum; i++ ) + { + for( j = 0; j < MAX_NET_NUM; j++ ) + { + if ( DevParam[i].IpAddr[j] == 0 ) + continue; + + if ( DevParam[i].IpAddr[j] == ipaddr ) + return i; + } + } + + return -1; +} + +int AddDev( u_long *addr, int num ) +{ + int i, dev; + + for ( i = 0; i < num; i++ ) + { + if ( addr[i] ) + { + dev = FindDev( addr[i] ); + if ( dev >= 0 ) + return dev; + } + } + + // 新设备 + iDevNum++; + + return iDevNum - 1; +} + +void SetUdpRecvDataProcess(u_long ipaddr, u_char *buf, int len) +{ + RTUMSG *msg; + int plen, i, k, dev, net; + u_long addr[MAX_NET_NUM]; + WORD tmp; + char *ptr; + //char szInfo[256]; + + for(plen = 0; plen < len;) + { + msg = (RTUMSG*)&buf[plen]; + //让数值为高字节前,低字节后(但此处无特别的作用,仅为了与机器无关而设) + tmp = BYTE1(buf[plen+1]) + BYTE0(buf[plen+2]); + msg->MsgType = tmp; + tmp = BYTE1(buf[plen+3]) + BYTE0(buf[plen+4]); + msg->MsgLen = tmp; + + plen += (msg->MsgLen + sizeof(RTUMSGHEAD)); + + //if(!(msg->MsgType & 0x8000)) + //{ + // continue; + //} + + switch(msg->MsgType & 0x3fff) + { + // 获取系统IP到上行 + // 0x00 - 0x03字节: 第一网卡地址IP地址 + // 0x044 - 0x07字节: 第二网卡地址IP地址 + // 0x08字节: 端口数目总数,包括网络通讯端口 + // 0x09 - 0xd字节: 保留 + // 0x0e字节: 串行通讯端口数目 + // 0x0f字节: 网络通讯端口数目 + // 0x10 - 4个带0x00结尾的字符串,它们是设备名称、软件版本、 + // 软件版本日期和制造厂商名称 + // 接下来,如果网卡数量多于2个,接着填写从第三网卡 + // 开始的网络IP地址 + case SDS_GET_IP_ADDR: + case SDS_N_GET_IP_ADDR: + if(!(msg->MsgType & 0x8000)) + { + break; + } + for (i = 0; i < 2; i++) + { + addr[i] = BYTE3(msg->MsgData[i*4+0]) + + BYTE2(msg->MsgData[i*4+1]) + + BYTE1(msg->MsgData[i*4+2]) + + BYTE0(msg->MsgData[i*4+3]); + + /*sprintf(szInfo, "NET%d: %d.%d.%d.%d\n", + i+1, msg->MsgData[i*4+0], + msg->MsgData[i*4+1], + msg->MsgData[i*4+2], + msg->MsgData[i*4+3]); + OutputDebugString(szInfo);*/ + } + + // 跳过4个字符串 + k = 0x10; + ptr = (char*)&msg->MsgData[k]; + k += (strlen(ptr) + 1); + ptr = (char*)&msg->MsgData[k]; + k += (strlen(ptr) + 1); + ptr = (char*)&msg->MsgData[k]; + k += (strlen(ptr) + 1); + ptr = (char*)&msg->MsgData[k]; + k += (strlen(ptr) + 1); + + net = (msg->MsgLen - k) / 4; + + if((net + 2) > MAX_NET_NUM) + { + break; + } + + for (i = 0; i < net; i++) + { + addr[2+i] = BYTE3(msg->MsgData[k+0]) + + BYTE2(msg->MsgData[k+1]) + + BYTE1(msg->MsgData[k+2]) + + BYTE0(msg->MsgData[k+3]); + + /*sprintf(szInfo, "NET%d: %d.%d.%d.%d\n", + i+3, msg->MsgData[k+0], + msg->MsgData[k+1], + msg->MsgData[k+2], + msg->MsgData[k+3]); + OutputDebugString(szInfo);*/ + + k += 4; + } + net += 2; + + dev = AddDev(&addr[0], net); + DevParam[dev].CurCommIp = ipaddr; + for (i = 0; i < MAX_NET_NUM; i++) + { + if(i < net) + { + if(DevParam[dev].IpAddr[i]) + { + if(DevParam[dev].IpAddr[i] != addr[i]) + DevParam[dev].IpAddrChangeFlag = 1; + } + DevParam[dev].IpAddr[i] = addr[i]; + } + else + DevParam[dev].IpAddr[i] = 0; + } + DevParam[dev].NetNum = net; + DevParam[dev].PortNum = msg->MsgData[8]; + DevParam[dev].SerialPortNum = msg->MsgData[0x0e]; + DevParam[dev].NetPortNum = msg->MsgData[0x0f]; + break; + + case SDS_SIO_SET_CONFIG_FILE: + if(!(msg->MsgType & 0x8000)) + { + break; + } + //dev = FindDev(ipaddr); + //if (dev < 0) + // break; + + //ClrWaitFlag(dev); + + tmp = BYTE1(msg->MsgData[0]) + BYTE0(msg->MsgData[1]); + + // 传输错误, 重来 + if((msg->MsgType & 0xc000) == 0x4000) + { + tmp = 0; + } + SetDevConfigFile(tmp + 1); + break; + + case SDS_SIO_RECV_DATA: + if(!CheckIsCurDevIpAddr(ipaddr)) + { + break; + } + if(FunCallPtr[SioParam[msg->PortIdx].ProtocolIdx].RecvData) + { + FunCallPtr[SioParam[msg->PortIdx].ProtocolIdx].RecvData(msg->PortIdx, + msg->MsgData, msg->MsgLen); + + //SioParam[msg->PortIdx].RecvCharNum += msg->MsgLen; + } + // wen 2004.11.25 删除数据缓冲区数据长度(保持和5249中的程序一致) + SioParam[msg->PortIdx].RecvBuf.MsgCnt = 0; + + SioParam[msg->PortIdx].RecvCharNum += msg->MsgLen; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.24 如果仅仅是接收到数据,不认为端口状态为正常, + // 必须是修改了数据库点才认为是端口正常。子站除外。 + //SioParam[msg->PortIdx].LineCommCnt = 0; + //SioParam[msg->PortIdx].Status = TRUE; + //============================================================= + SioParam[msg->PortIdx].LineCommCnt = 0; + if(SioParam[msg->PortIdx].m_psBaoHu) + { + // 如果为子站 + if(SioParam[msg->PortIdx].m_psBaoHu->PortType) + { + SioParam[msg->PortIdx].Status = TRUE; + } + } + else + { + SioParam[msg->PortIdx].Status = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + //if((CurPort == msg->PortIdx) && RealDataDispFlag) + //{ + // WatchDataPutDispBuf(msg->PortIdx, SDS_SIO_RECV_DATA, msg->MsgData, msg->MsgLen); + //} + break; + case SDS_SIO_SEND_DATA: + // 数据已经接收 + //sprintf(szInfo, "TIP_(%08d): port=%d Send Data is received.\n", + // getpid(), msg->PortIdx+1); + //DebugPrint(szInfo); + break; + default: + //sprintf(szInfo, "ERR_(%08d): port=%d Recv Error(Func=%d).", + // getpid(), msg->PortIdx+1, msg->MsgType); + //DebugPrint(szInfo); + break; + } + } +} + +void SetDevConfigFile(int blk) +{ + if(SetDevConfigFileEx(gCurConfigFileName, blk) != 0) + { + //((CWidgetMainWnd *)qApp->mainWidget())->RestoreCursor(); + } +} + +int SetDevConfigFileEx(char *szPortConfigName, int blk) +{ + char szbuf[1024]; + int idx, blklen, iSendLen; + FILE *fp; + + if(!DevParam[iCurDevIdx].CurCommIp) + { + ////QTMessageBox("设备配置文件...", "无有效设备!!!"); + return -1; + } + + if(szPortConfigName == NULL) + { + //QTMessageBox("设备配置文件...", "下装设备配置文件名称错误!!!"); + return -1; + } + + if(strlen(szPortConfigName) == 0) + { + //QTMessageBox("设备配置文件...", "下装设备配置文件名称错误!!!"); + return -1; + } + + // wen 2005.12.01 在这里设置全局的配置文件名称 + if(blk == 0) + { + strcpy(gCurConfigFileName, szPortConfigName); + } + + fp = fopen(szPortConfigName, "rb"); + if(fp == NULL) + { + return -1; + } + + for(idx = 0; ; idx++) + { + blklen = fread((char*)&szbuf[2], 1, BLK_SIZE, fp); + if(blklen < 1) + { + break; + } + + if(idx == blk) + { + szbuf[0] = HIBYTE(blk); + szbuf[1] = LOBYTE(blk); + iSendLen = FillAndSendCmd(0, 0, SDS_SIO_SET_CONFIG_FILE, (u_char*)szbuf, blklen + 2); + fclose(fp); + if(iSendLen == 0) + { + //QTMessageBox("设备配置文件...", "下装设备配置文件失败!!!"); + return -1; + } + return 0; + } + } + + fclose(fp); + //MessageBox(NULL, "设备配置文件设置完成!!!", "设备配置文件...", MB_OK | MB_ICONINFORMATION); + //QTMessageBox("设备配置文件...", "设备配置文件设置完成!!!"); + + return 1; +} + +void SetDevTime() +{ + BYTE buf[16]; + DAY_TIME sm; + + GetLocalTimeEx(&sm); + + buf[0] = HIBYTE(sm.Year); + buf[1] = LOBYTE(sm.Year); + buf[2] = 0; + buf[3] = sm.Month; + buf[4] = 0; + buf[5] = sm.Day; + buf[6] = 0; + buf[7] = sm.Hour; + buf[8] = 0; + buf[9] = sm.Min; + buf[10] = 0; + buf[11] = sm.Sec; + + FillAndSendCmd(INADDR_BROADCAST, 0, SDS_SIO_SET_SYSTEM_TIME, buf, 12); +} + +void ResetDev(int iDevNo) +{ + if(iDevNo >= 0) + { + FillAndSendCmd(DevParam[iDevNo].CurCommIp, 0, SDS_SIO_RESET, NULL, 0); + } + else + { + FillAndSendCmd(0, 0, SDS_SIO_RESET, NULL, 0); + } +} + +BOOL isUdpSocketExist() +{ + if(UdpParam.Socket) + { + return TRUE; + } + else + { + return FALSE; + } +} diff --git a/udpcomm.h b/udpcomm.h new file mode 100644 index 0000000..10311eb --- /dev/null +++ b/udpcomm.h @@ -0,0 +1,38 @@ + + +#ifndef __UDP_COMM_H_ICL__ +#define __UDP_COMM_H_ICL__ + +#include "common.h" +//#include "resource.h" + +void InitGlobalMember(); + +void GetHostIpAddr( void ); +int GetSdsIpAddr( void ); +void CreatUdpSetSock( void ); +void CloseUdpSetSock( void ); +int CheckIsMySelftIpAddr( u_long addr ); + +void SetUdpRecv( void ); +int SetUdpSend( u_long ipaddr, char *buf, int len ); +int FillAndSendCmd( u_long ipaddr, u_char port, WORD cmd, u_char *retbuf, int len ); + +void ValueToBuf( u_char *buf, u_long val, int len ); +u_long BufToValue( u_char *buf, int len ); + +void WatchDataPutDispBuf( int port, WORD type, u_char *buf, int len ); +void WatchDataPutDispBufToFile(int port, WORD type, u_char *buf, int len); + +void SetUdpRecvDataProcess( u_long ipaddr, u_char *buf, int len ); + +void SetDevConfigFile(int blk); +int SetDevConfigFileEx(char *szPortConfigName, int blk); + +void SetDevTime(); + +void ResetDev(int iDevNo); + +BOOL isUdpSocketExist(); + +#endif \ No newline at end of file diff --git a/udpping.cpp b/udpping.cpp new file mode 100644 index 0000000..50da571 --- /dev/null +++ b/udpping.cpp @@ -0,0 +1,1027 @@ +/************************************************************************************ + * + * Copyright (C) 2002-2003 SCADA Control Technology Co., Ltd. All rights reserved. + * + * $Source: /opt/CVS_ROOT_PGC_EX2000/commserver/windows/widgets/udpping.cpp,v $ + * + * $Author: zhuzhenhua $ + * + * $Date: 2006/08/07 03:16:49 $ + * + * $Revision: 1.2 $ + * + * $State: Exp $ + * + * $Name: $ + * + * $Locker: $ + * + **************************************************************************************/ +//*************************************************************** +//* udpping.cpp * +//* Liangchu Lee 1999.12.20 * +//*************************************************************** +//************************修 改 提 示**************************** +//1. wen 2002.11.11 前置机为备用机B时,主机退出,无法进行切换: +// 问题:当前置机A为主机下发,退出系统后备用前置机无法把自身切换 +// 为主机。 +// 描述:修改读取函数部分 UdpPingReaddata(void)。 +// 结果:增加判断,长时间收不到对方PING包,置其下发标志为FALSE。 +//2. wen 2003.04.21 服务器和前置机共处一台机器中,会出现绑定失败。 +// 问题:前置机后启动,ping接收端口不能正常工作。 +// 描述:服务器、前置机共处一台机器,当前置机后启动,绑定失败, +// 地址被服务器使用。错误信息=10048(套接字地址被使用)。 +// 结果:设置socket属性为SO_REUSEADDR,地址可重用。 +//*************************************************************** +#include "commport.h" +#include "udpping.h" +#include "tcphost.h" + +UDP_PING_INFO UdpPing; + +int gUdpPingReadPort; +int gUdpPingWritePort; + +int gUdpPingInitOk = FALSE; + +int gPingWaitCnt = 0; +int gSendTxdDataFendIdx = 0; + +//int gtestread = 1; +extern char IniFilePath[256]; + +void UdpPingTimer(void) +{ + if(gUdpPingInitOk == TRUE) + { + UdpPingReaddata(); +#ifdef MACRO_NETPING_P2P + UdpPingSendDataP2P(); +#else + UdpPingSendData(); +#endif + } + else + { + gUdpPingInitOk = UdpPingInit(); + } +} + +BOOL UdpPingInit(void) +{ + static BOOL bFirst = TRUE; + int i, tmp_len; + struct sockaddr_in *cliaddr; + //struct hostent *test; +#ifndef MACRO_NETPING_P2P + BOOL bBroadcast = TRUE; // 是否广播方式发送数据报 +#endif + int timeout = 1000; // 超时 + + char szConfig[256]; + +#ifdef OS_LINUX + strcpy(szConfig, "config.ini"); +#else + //GetCurrentDirectory(sizeof(szDir), szDir); + sprintf(szConfig, "%s/config.ini", IniFilePath); +#endif + + gUdpPingReadPort = GetPrivateProInt("网络设置", "PING接收端口", 8124, szConfig); + gUdpPingWritePort = GetPrivateProInt("网络设置", "PING发送端口", 8123, szConfig); + + //test = gethostbyname(pFendMsg->Name); + for(i = 0; i < MAX_ADDR; i++) + { + if(bFirst == TRUE) + { + UdpPing.sSocket[i] = INVALID_SOCKET; + } + else + { + if(INVALID_SOCKET != UdpPing.sSocket[i]) + { + continue; + } + } + + cliaddr = &UdpPing.CliAddr; + + UdpPing.sSocket[i] = socket(AF_INET, SOCK_DGRAM, 0); + if(UdpPing.sSocket[i] < 0) + { + UdpPing.sSocket[i] = INVALID_SOCKET; + continue; + } + +#ifdef OS_LINUX + // wen 2005.07.08 将socket设置为非阻塞模式 + tmp = fcntl(UdpPing.sSocket[i], F_GETFL, 0); + fcntl(UdpPing.sSocket[i], F_SETFL, tmp|O_NONBLOCK); +#endif + +#ifndef MACRO_NETPING_P2P + // wen 2006.04.28 不使用广播发送ping包 + bBroadcast = TRUE; + setsockopt(UdpPing.sSocket[i], SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(bBroadcast)); +#endif + tmp_len = 1; + setsockopt(UdpPing.sSocket[i], SOL_SOCKET, SO_REUSEADDR, (char*)&tmp_len, sizeof(int)); + setsockopt(UdpPing.sSocket[i], SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); + setsockopt(UdpPing.sSocket[i], SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); + + memset((char *)cliaddr, 0, sizeof(*cliaddr)); + cliaddr->sin_family = AF_INET; + cliaddr->sin_addr.s_addr = htonl(INADDR_ANY); + cliaddr->sin_port = htons(INADDR_ANY); + if(bind(UdpPing.sSocket[i], (struct sockaddr *)cliaddr, sizeof(*cliaddr)) != 0) + //if((tmp = bind(UdpPing.sSocket[i], (struct sockaddr *)cliaddr, sizeof(*cliaddr))) == SOCKET_ERROR) + { + CloseNetSocket(UdpPing.sSocket[i]); + UdpPing.sSocket[i] = INVALID_SOCKET; + continue; + } + } + + cliaddr = &UdpPing.CliAddr; + + if(bFirst != TRUE) + { + if(INVALID_SOCKET != UdpPing.rSocket) + { + return TRUE; + } + } + else + { + bFirst = FALSE; + } + + UdpPing.rSocket = socket(AF_INET, SOCK_DGRAM, 0); + if(UdpPing.rSocket < 0) + { + UdpPing.rSocket = INVALID_SOCKET; + return FALSE; + } + + // wen 2003.04.21 服务器和前置机共处一台机器中,会出现绑定失败。套接字地址被使用 + tmp_len = 1; + setsockopt(UdpPing.rSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp_len, sizeof(int)); + + memset((char *)cliaddr, 0, sizeof(*cliaddr)); + cliaddr->sin_family = AF_INET; + cliaddr->sin_addr.s_addr = htonl(INADDR_ANY); + cliaddr->sin_port = htons(gUdpPingReadPort); + if(bind(UdpPing.rSocket, (struct sockaddr *)cliaddr, sizeof(*cliaddr)) != 0) + //if((tmp = bind(UdpPing.rSocket, (struct sockaddr *)cliaddr, sizeof(*cliaddr))) == SOCKET_ERROR) + { + CloseNetSocket(UdpPing.rSocket); + UdpPing.rSocket = INVALID_SOCKET; + + return FALSE; + } + + return TRUE; +} + +void UdpPingSendData(void) +{ + //char szDbg[256]; + static int cnt = 0; + int i, sendlen; + struct sockaddr_in *servaddr; + PINGINFORMATION PingData; + // wen 2002.07.11 + BOOL bSendFlag = FALSE; + TCP_LINK_DEF *pHostLink; + FEND_DEF *pFendMsg; + SIO_PARAM_DEF *pSioParam; + + cnt++; + if((cnt * TIMER_CNT) < 1000) + { + return; + } + cnt = 0; + + // 获取全局变量,通过函数调用 + pHostLink = GetHostLinkPtr(); + pFendMsg = GetFendMsgPtr(); + + //if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == TRUE) + //{ + // sprintf(szDbg, "FendIdx=%d is Txd Fend.", pFendMsg->FendIdx); + // DebugPrint(szDbg); + //} + + memmove((char*)PingData.barrRandom, PINGRANDOM, MAX_RANDOM); + if(pFendMsg->FendIdx == 0) + { + strcpy((char*)PingData.szNodeName, "FENDA"); + } + else + { + strcpy((char*)PingData.szNodeName, "FENDB"); + } + + PingData.bNodeType = FEND_TYPE; + PingData.wNodeID = pFendMsg->FendIdx; + PingData.inetMask = pFendMsg->HostIpAddr[0]; + PingData.inetAddr = pFendMsg->AllIpAddr[0]; + PingData.dwStatus = 0; + + if(gPingWaitCnt < MAX_DELAYTIME) + { + gPingWaitCnt++; + } + + //sprintf(szDbg, "WaitCnt=%d, Txd[0]=%d, Txd[1]=%d, Exist[0]=%d, Exist[1]=%d", + // gPingWaitCnt, pFendMsg->SendTxdDataFlag[0], pFendMsg->SendTxdDataFlag[1], + // pFendMsg->FendExistFlag[0], pFendMsg->FendExistFlag[1]); + //DebugPrint(szDbg); + + if(gPingWaitCnt == 5) + { + if((pFendMsg->SendTxdDataFlag[0] == 0) + && (pFendMsg->SendTxdDataFlag[1] == 0)) + { + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + //pFendMsg->SendTxdDataFlag[0] = FALSE; + //pFendMsg->SendTxdDataFlag[1] = FALSE; + //pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + //======================================================================= + if(pFendMsg->iPortMask) + { + pSioParam = GetSioParamPtr(); + for(i=0; iiPortMask & (0x00000001 << i)) + { + if(pSioParam[i].Status) + { + break; + } + } + } + } + else + { + i = DEFAULT_MAX_PORT_NUM; + } + if(i >= DEFAULT_MAX_PORT_NUM) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + } + + if((gSendTxdDataFendIdx == 0) && (gPingWaitCnt > 10)) + { + if((pFendMsg->SendTxdDataFlag[0] == 0) + && (pFendMsg->SendTxdDataFlag[1] == 0)) + { + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + //pFendMsg->SendTxdDataFlag[0] = FALSE; + //pFendMsg->SendTxdDataFlag[1] = FALSE; + //pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + //======================================================================= + if(pFendMsg->iPortMask) + { + pSioParam = GetSioParamPtr(); + for(i=0; iiPortMask & (0x00000001 << i)) + { + if(pSioParam[i].Status) + { + break; + } + } + } + } + else + { + i = DEFAULT_MAX_PORT_NUM; + } + if(i >= DEFAULT_MAX_PORT_NUM) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + + if(pFendMsg->FendExistFlag[0] == FALSE) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + } + + if(pFendMsg->FendExistFlag[1] == FALSE) + { + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + + // wen 2002.11.25 连接服务器慢的系统会出现切换不成功 + /* + switch(pFendMsg->LinkStatus[1]*2 + pFendMsg->LinkStatus[0]) + { + case 0x01: + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + break; + case 0x02: + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = TRUE; + break; + } + */ + } + + //DebugPrint("UdpPingSendData Begin..."); + // 字节顺序转换 + PingData.wNodeID = SequenceHostToRtuWord(PingData.wNodeID); + for(i = 0; i < MAX_ADDR; i++) + { + if(INVALID_SOCKET == UdpPing.sSocket[i]) + { + continue; + } + + PingData.inetMask = pFendMsg->HostIpAddr[i]; + PingData.inetAddr = pFendMsg->AllIpAddr[i]; + PingData.dwStatus = (pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] ? 4 : 0) + + (pHostLink[1].InitOk ? 2 : 0) + (pHostLink[0].InitOk ? 1 : 0) + 0x30000; + + switch(gSendTxdDataFendIdx) + { + case 1: // 前置机 A 下发数据 + if(pFendMsg->SendTxdDataFlag[0] == 0) + { + pFendMsg->SendTxdDataFlag[1] = FALSE; + PingData.dwStatus += 0x10; + } + else + { + if(pFendMsg->SendTxdDataFlag[0] + && pFendMsg->SendTxdDataFlag[1]) + { + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + gSendTxdDataFendIdx = 0; + } + break; + case 2: // 前置机 B 下发数据 + if(pFendMsg->SendTxdDataFlag[1] == 0) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + PingData.dwStatus += 0x20; + } + else + { + if(pFendMsg->SendTxdDataFlag[0] + && pFendMsg->SendTxdDataFlag[1]) + { + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + gSendTxdDataFendIdx = 0; + } + break; + } + + servaddr = &UdpPing.SerAddr; + memset((char *)servaddr, 0, sizeof(struct sockaddr_in)); + servaddr->sin_family = AF_INET; + servaddr->sin_addr.s_addr = htonl(pFendMsg->BroadCastAddr[i]); + if(0 == servaddr->sin_addr.s_addr) + { + continue; + } + + //sprintf(szDbg, "Txd[%d]=%d, wNodeId=%d, inetAddr=%08x, inetMask=%08x, dwStatus=%08x\n", + // pFendMsg->FendIdx, pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx], + // PingData.wNodeID, PingData.inetAddr, PingData.inetMask, PingData.dwStatus); + //DebugPrint(szDbg); + + // 字节顺序转换 + //PingData.wNodeID = SequenceHostToRtuWord(PingData.wNodeID); + PingData.inetMask = SequenceHostToRtuDWord(PingData.inetMask); + PingData.inetAddr = SequenceHostToRtuDWord(PingData.inetAddr); + PingData.dwStatus = SequenceHostToRtuDWord(PingData.dwStatus); + + //sprintf(szDbg, "Send dwStatus(change)=%02x", PingData.dwStatus); + //DebugPrint(szDbg); + + servaddr->sin_port = htons(gUdpPingWritePort); + sendlen = sendto(UdpPing.sSocket[i], (char*)&PingData, sizeof(PINGINFORMATION), 0, + (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)); + + //sprintf(szDbg, "sendto([%d] %08x:%d) ", + //i, pFendMsg->BroadCastAddr[i], gUdpPingWritePort, pFendMsg->HostIpAddr[i]); + //DebugPrint(szDbg); + + servaddr->sin_port = htons(gUdpPingReadPort); + sendlen = sendto(UdpPing.sSocket[i], (char*)&PingData, sizeof(PINGINFORMATION), 0, + (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)); + + //sprintf(szDbg, "sendto([%d] %08x:%d) \n", + //i, pFendMsg->BroadCastAddr[i], gUdpPingReadPort, pFendMsg->HostIpAddr[i]); + //DebugPrint(szDbg); + } + + //DebugPrint("UdpPingSendData End."); +} + +void UdpPingSendDataP2P(void) +{ + //char szDbg[256]; + static int cnt = 0; + int i, j, sendlen; + struct sockaddr_in *servaddr; + PINGINFORMATION PingData; + // wen 2002.07.11 + BOOL bSendFlag = FALSE; + TCP_LINK_DEF *pHostLink; + FEND_DEF *pFendMsg; + SIO_PARAM_DEF *pSioParam; + + cnt++; + if((cnt * TIMER_CNT) < 1000) + { + return; + } + cnt = 0; + + // 获取全局变量,通过函数调用 + pHostLink = GetHostLinkPtr(); + pFendMsg = GetFendMsgPtr(); + + //if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == TRUE) + //{ + // sprintf(szDbg, "FendIdx=%d is Txd Fend.", pFendMsg->FendIdx); + // DebugPrint(szDbg); + //} + + memmove((char*)PingData.barrRandom, PINGRANDOM, MAX_RANDOM); + if(pFendMsg->FendIdx == 0) + { + strcpy((char*)PingData.szNodeName, "FENDA"); + } + else + { + strcpy((char*)PingData.szNodeName, "FENDB"); + } + + PingData.bNodeType = FEND_TYPE; + PingData.wNodeID = pFendMsg->FendIdx; + PingData.inetMask = pFendMsg->HostIpAddr[0]; + PingData.inetAddr = pFendMsg->AllIpAddr[0]; + PingData.dwStatus = 0; + + if(gPingWaitCnt < MAX_DELAYTIME) + { + gPingWaitCnt++; + } + + //sprintf(szDbg, "WaitCnt=%d, Txd[0]=%d, Txd[1]=%d, Exist[0]=%d, Exist[1]=%d", + // gPingWaitCnt, pFendMsg->SendTxdDataFlag[0], pFendMsg->SendTxdDataFlag[1], + // pFendMsg->FendExistFlag[0], pFendMsg->FendExistFlag[1]); + //DebugPrint(szDbg); + + if(gPingWaitCnt == 5) + { + if((pFendMsg->SendTxdDataFlag[0] == 0) + && (pFendMsg->SendTxdDataFlag[1] == 0)) + { + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + //pFendMsg->SendTxdDataFlag[0] = FALSE; + //pFendMsg->SendTxdDataFlag[1] = FALSE; + //pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + //======================================================================= + if(pFendMsg->iPortMask) + { + pSioParam = GetSioParamPtr(); + for(i=0; iiPortMask & (0x00000001 << i)) + { + if(pSioParam[i].Status) + { + break; + } + } + } + } + else + { + i = DEFAULT_MAX_PORT_NUM; + } + if(i >= DEFAULT_MAX_PORT_NUM) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + } + + if((gSendTxdDataFendIdx == 0) && (gPingWaitCnt > 10)) + { + if((pFendMsg->SendTxdDataFlag[0] == 0) + && (pFendMsg->SendTxdDataFlag[1] == 0)) + { + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + //pFendMsg->SendTxdDataFlag[0] = FALSE; + //pFendMsg->SendTxdDataFlag[1] = FALSE; + //pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + //======================================================================= + if(pFendMsg->iPortMask) + { + pSioParam = GetSioParamPtr(); + for(i=0; iiPortMask & (0x00000001 << i)) + { + if(pSioParam[i].Status) + { + break; + } + } + } + } + else + { + i = DEFAULT_MAX_PORT_NUM; + } + if(i >= DEFAULT_MAX_PORT_NUM) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + } + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + } + +// wen 2006.04.29 在uclinux下,发送数据给自己无法接收的到。始终认为自己是存在的。 +#ifdef OS_LINUX + pFendMsg->FendExistFlag[pFendMsg->FendIdx] = TRUE; + pFendMsg->FendExistCnt[pFendMsg->FendIdx] = 0; +#endif + + if(pFendMsg->FendExistFlag[0] == FALSE) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + } + + if(pFendMsg->FendExistFlag[1] == FALSE) + { + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + + // wen 2002.11.25 连接服务器慢的系统会出现切换不成功 + /* + switch(pFendMsg->LinkStatus[1]*2 + pFendMsg->LinkStatus[0]) + { + case 0x01: + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + break; + case 0x02: + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = TRUE; + break; + } + */ + } + + //DebugPrint("UdpPingSendDataP2P Begin..."); + // 字节顺序转换 + PingData.wNodeID = SequenceHostToRtuWord(PingData.wNodeID); + for(i = 0; i < MAX_ADDR; i++) + { + if(INVALID_SOCKET == UdpPing.sSocket[i]) + { + continue; + } + + PingData.inetMask = pFendMsg->HostIpAddr[i]; + PingData.inetAddr = pFendMsg->AllIpAddr[i]; + PingData.dwStatus = (pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] ? 4 : 0) + + (pHostLink[1].InitOk ? 2 : 0) + (pHostLink[0].InitOk ? 1 : 0) + 0x30000; + + switch(gSendTxdDataFendIdx) + { + case 1: // 前置机 A 下发数据 + if(pFendMsg->SendTxdDataFlag[0] == 0) + { + pFendMsg->SendTxdDataFlag[1] = FALSE; + PingData.dwStatus += 0x10; + } + else + { + if(pFendMsg->SendTxdDataFlag[0] + && pFendMsg->SendTxdDataFlag[1]) + { + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + gSendTxdDataFendIdx = 0; + } + break; + case 2: // 前置机 B 下发数据 + if(pFendMsg->SendTxdDataFlag[1] == 0) + { + pFendMsg->SendTxdDataFlag[0] = FALSE; + PingData.dwStatus += 0x20; + } + else + { + if(pFendMsg->SendTxdDataFlag[0] + && pFendMsg->SendTxdDataFlag[1]) + { + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + gSendTxdDataFendIdx = 0; + } + break; + } + + servaddr = &UdpPing.SerAddr; + memset((char *)servaddr, 0, sizeof(struct sockaddr_in)); + servaddr->sin_family = AF_INET; + //servaddr->sin_addr.s_addr = htonl(pFendMsg->SetTcpIpAddr[2*i]); + // 字节顺序转换 + //PingData.wNodeID = SequenceHostToRtuWord(PingData.wNodeID); + PingData.inetMask = SequenceHostToRtuDWord(PingData.inetMask); + PingData.inetAddr = SequenceHostToRtuDWord(PingData.inetAddr); + PingData.dwStatus = SequenceHostToRtuDWord(PingData.dwStatus); + // 点对点发送给前置机 + for(j=0; jFendIdx) + { + continue; + } +#endif + if(strlen(pFendMsg->SetTcpIpAddr[MAX_FEND*j+i]) > 0) + { + //sprintf(szDbg, "FEND_%d: Txd[%d]=%d, wNodeId=%d, inetAddr=%08x, inetMask=%08x, dwStatus=%08x\n", + // j+1, pFendMsg->FendIdx, pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx], + // PingData.wNodeID, PingData.inetAddr, PingData.inetMask, PingData.dwStatus); + //DebugPrint(szDbg); + + //sprintf(szDbg, "Send dwStatus(change)=%02x", PingData.dwStatus); + //DebugPrint(szDbg); + + servaddr->sin_addr.s_addr = inet_addr((char *)pFendMsg->SetTcpIpAddr[MAX_FEND*j+i]); + + //DebugPrint((char *)pFendMsg->SetTcpIpAddr[MAX_FEND*j+i]); + + servaddr->sin_port = htons(gUdpPingReadPort); + sendlen = sendto(UdpPing.sSocket[i], (char*)&PingData, sizeof(PINGINFORMATION), 0, + (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)); + + //sprintf(szDbg, "sendto([%d] %08x:%d) \n", + //i, pFendMsg->BroadCastAddr[i], gUdpPingReadPort, pFendMsg->HostIpAddr[i]); + //DebugPrint(szDbg); + } + } + + // 点对点发送给服务器 + for(j=0; j 0) + { + //sprintf(szDbg, "HOST_%d: Txd[%d]=%d, wNodeId=%d, inetAddr=%08x, inetMask=%08x, dwStatus=%08x\n", + // j+1, pFendMsg->FendIdx, pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx], + // PingData.wNodeID, PingData.inetAddr, PingData.inetMask, PingData.dwStatus); + //DebugPrint(szDbg); + + servaddr->sin_addr.s_addr = inet_addr((char *)pHostLink[j].TcpIpAddr[i]); + servaddr->sin_port = htons(gUdpPingWritePort); + sendlen = sendto(UdpPing.sSocket[i], (char*)&PingData, sizeof(PINGINFORMATION), 0, + (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)); + } + } + } + + //DebugPrint("UdpPingSendDataP2P End."); +} + +void UdpPingReaddata(void) +{ + fd_set set; + struct timeval outtime; + struct sockaddr_in src_servaddr; + int rlen, i, j, k; + short msglen; + u_char msgdata[MAX_RTU_MSG_SIZE]; + PINGINFORMATION *pingmsg; + char revip[32]; + char szbuf[128]; + static int dflag = 0; + // wen 2002.11.11 前置机为备用机B时,主机退出,无法进行切换 + static int recvtimeout = 0; + TCP_LINK_DEF *pHostLink; + FEND_DEF *pFendMsg; + SIO_PARAM_DEF *pSioParam; + + // 获取全局变量,通过函数调用 + pHostLink = GetHostLinkPtr(); + pFendMsg = GetFendMsgPtr(); + //for(i = 0; i < MAX_ADDR; i++) + { + memset((char*)&outtime, 0, sizeof(struct timeval)); + memset((char*)&src_servaddr, 0, sizeof(src_servaddr)); + FD_ZERO(&set); + + FD_SET(UdpPing.rSocket, &set); + + if(UdpPing.rSocket == INVALID_SOCKET) + { + return; + } + + for(; ;) + { + rlen = select(UdpPing.rSocket+1, &set, NULL, NULL, &outtime); + if(rlen < 1) + { + break; + } + + rlen = sizeof(struct sockaddr_in); + msglen = recvfrom(UdpPing.rSocket, (char*)msgdata, MAX_RTU_MSG_SIZE, + 0, (struct sockaddr*)&src_servaddr, &rlen); + + if(msglen == SOCKET_ERROR) + { + break; + } + + for(j = 0; j < msglen; j += sizeof(PINGINFORMATION)) + { + pingmsg = (PINGINFORMATION*)msgdata; + //if(!CmpnString((char*)pingmsg->barrRandom, PINGRANDOM, MAX_RANDOM-1)) + // continue; + + // 字节顺序转换 + pingmsg->wNodeID = SequenceRtuToHostWord(pingmsg->wNodeID); + pingmsg->inetAddr = SequenceRtuToHostDWord(pingmsg->inetAddr); + pingmsg->inetMask = SequenceRtuToHostDWord(pingmsg->inetMask); + pingmsg->dwStatus = SequenceRtuToHostDWord(pingmsg->dwStatus); + + //sprintf(szbuf, "recv: wNodeId=%d, inetAddr=%08x, inetMask=%08x, dwStatus=%08x", + // pingmsg->wNodeID, pingmsg->inetAddr, pingmsg->inetMask, pingmsg->dwStatus); + //DebugPrint(szbuf); + + switch(pingmsg->bNodeType) + { + case MMI_TYPE: + break; + + case FEND_TYPE: + /* test + if(gtestread == 0) + { + // 前置机a + if(pingmsg->wNodeID == 0) + { + DebugPrint("屏蔽前置机a的ping包"); + break; + } + }*/ + + // wen 2002.11.11 前置机为备用机B时,主机退出,无法进行切换 + // 每一个ping 包 一秒钟发送一次 + if(!pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx]) + { + if(recvtimeout < 6) + { + recvtimeout++; + } + else + { + recvtimeout = 0; + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // wen 2006.04.22 主备切换时,判断的端口通讯状态屏蔽字(按位屏蔽) + //pFendMsg->SendTxdDataFlag[(pFendMsg->FendIdx+1)%MAX_ADDR] = FALSE; + //pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + //======================================================================= + if(pFendMsg->iPortMask) + { + pSioParam = GetSioParamPtr(); + for(i=0; iiPortMask & (0x00000001 << i)) + { + if(pSioParam[i].Status) + { + break; + } + } + } + } + else + { + i = DEFAULT_MAX_PORT_NUM; + } + if(i >= DEFAULT_MAX_PORT_NUM) + { + pFendMsg->SendTxdDataFlag[(pFendMsg->FendIdx+1)%MAX_ADDR] = FALSE; + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = TRUE; + } + } + } + + for(k = 0; k < MAX_FEND*MAX_ADDR; k++) + { + if((k / MAX_ADDR) == pFendMsg->FendIdx) + { + if(inet_addr((char*)pFendMsg->TcpIpAddr[k % MAX_ADDR]) != src_servaddr.sin_addr.s_addr) + continue; + } + else + { + if(inet_addr((char*)pFendMsg->SetTcpIpAddr[k]) != src_servaddr.sin_addr.s_addr) + { + continue; + } + + // wen 2002.11.11 前置机为备用机B时,主机退出,无法进行切换 + recvtimeout = 0; + } + + if((k / MAX_ADDR) != pingmsg->wNodeID) + continue; + + pFendMsg->FendExistFlag[pingmsg->wNodeID] = TRUE; + pFendMsg->FendExistCnt[pingmsg->wNodeID] = 0; + + pFendMsg->LinkStatus[pingmsg->wNodeID] = (pingmsg->dwStatus & 0x03) ? 1 : 0; + if(pFendMsg->LinkStatus[pingmsg->wNodeID]) + pFendMsg->LinkCnt[pingmsg->wNodeID] = 0; + + pFendMsg->SendTxdDataFlag[pingmsg->wNodeID] = (pingmsg->dwStatus & 0x04) ? TRUE : FALSE; + switch(pingmsg->dwStatus & 0x30) + { + case 0x10: + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + break; + case 0x20: + pFendMsg->SendTxdDataFlag[0] = FALSE; + pFendMsg->SendTxdDataFlag[1] = TRUE; + break; + // wen 2002.04.05 + default: + if(pFendMsg->SendTxdDataFlag[0] & pFendMsg->SendTxdDataFlag[1]) + { + pFendMsg->SendTxdDataFlag[0] = TRUE; + pFendMsg->SendTxdDataFlag[1] = FALSE; + } + break; + } + // wen 2006.04.29 多余的指令,这种情况永远不会发生,上面已经消除了这种情况 + //if(pFendMsg->SendTxdDataFlag[0] && pFendMsg->SendTxdDataFlag[1]) + //{ + // pFendMsg->SendTxdDataFlag[1] = FALSE; + //} + break; + } + break; + + case HOST_TYPE: + for(k = 0; k < MAX_HOST * MAX_ADDR; k++) + { + strcpy((char*)revip, inet_ntoa(*(struct in_addr*)&src_servaddr.sin_addr.s_addr)); + if(inet_addr((char*)pHostLink[k / MAX_ADDR].TcpIpAddr[k % MAX_ADDR]) != src_servaddr.sin_addr.s_addr) + continue; + + if((k / MAX_ADDR) != pingmsg->wNodeID) + continue; + + pHostLink[pingmsg->wNodeID].RevHostStatusMsg = TRUE; + pHostLink[pingmsg->wNodeID].VersionFalgByte = (u_char)(HIWORD(pingmsg->dwStatus) >> 8); + + pHostLink[pingmsg->wNodeID].Status = (u_char)(LOWORD(pingmsg->dwStatus) - 1); + if(pHostLink[pingmsg->wNodeID].InitOk == TRUE) + pHostLink[pingmsg->wNodeID].StatusCnt = 0; + break; + } + + if((pHostLink[0].Status == 0) && (pHostLink[1].Status == 0)) + { + if(dflag == 0) + { + sprintf(szbuf, "接收服务器状态为双主机状态错误!!! 当前处理服务器 %c 状态包。", pingmsg->wNodeID + 'A'); + DebugPrint((char*)szbuf); + } + dflag = 1; + } + else + { + if(dflag) + { + if(pHostLink[0].Status == 0) + { + sprintf(szbuf, "接收服务器状态 A 服务器为主机!!!"); + DebugPrint((char*)szbuf); + } + + if(pHostLink[1].Status == 0) + { + sprintf(szbuf, "接收服务器状态 B 服务器为主机!!!"); + DebugPrint((char*)szbuf); + } + } + dflag = 0; + } + + //sprintf(szbuf, "pHostLink[0].Status=%d, pHostLink[1].Status=%d\n", + // pHostLink[0].Status, pHostLink[1].Status); + //DebugPrint(szbuf); + break; + } + } + } + } +} + +void UdpPingClose(void) +{ + int i; + + for(i = 0; i < MAX_ADDR; i++) + { + if(UdpPing.sSocket[i] == INVALID_SOCKET) + { + continue; + } + CloseNetSocket(UdpPing.sSocket[i]); + UdpPing.sSocket[i] = INVALID_SOCKET; + } + + if(UdpPing.rSocket != INVALID_SOCKET) + { + CloseNetSocket(UdpPing.rSocket); + } + + UdpPing.rSocket = INVALID_SOCKET; + gUdpPingInitOk = FALSE; +} + +void UdpPingSwitch(void) +{ + int i; + FEND_DEF *pFendMsg; + + // 获取全局变量,通过函数调用 + pFendMsg = GetFendMsgPtr(); + + for(i=0; iFendExistFlag[i] = FALSE; + pFendMsg->FendExistCnt[i] = 0; + pFendMsg->LinkStatus[i] = FALSE; + pFendMsg->LinkCnt[i] = 0; + } + + if(pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] == TRUE) + { + pFendMsg->SendTxdDataFlag[pFendMsg->FendIdx] = FALSE; + + if(pFendMsg->FendIdx == 0) + { + gSendTxdDataFendIdx = 2; + } + else + { + gSendTxdDataFendIdx = 1; + } + } + else + { + if(pFendMsg->FendIdx == 0) + { + gSendTxdDataFendIdx = 1; + } + else + { + gSendTxdDataFendIdx = 2; + } + } +} diff --git a/udpping.h b/udpping.h new file mode 100644 index 0000000..5caf2ad --- /dev/null +++ b/udpping.h @@ -0,0 +1,109 @@ +/************************************************************************************ + * + * Copyright (C) 2002-2003 SCADA Control Technology Co., Ltd. All rights reserved. + * + * $Source: /opt/CVS_ROOT_PGC_EX2000/commserver/windows/widgets/udpping.h,v $ + * + * $Author: jehu $ + * + * $Date: 2006/07/05 07:31:44 $ + * + * $Revision: 1.1.1.1 $ + * + * $State: Exp $ + * + * $Name: $ + * + * $Locker: $ + * + * $Log: udpping.h,v $ + * Revision 1.1.1.1 2006/07/05 07:31:44 jehu + * no message + * + * Revision 1.4 2006/04/28 06:29:18 administrator + * 修改ping数据包为点对点发送 + * + * Revision 1.3 2006/04/22 07:51:07 administrator + * 竞争时间用宏代替 + * + * Revision 1.2 2005/10/20 07:03:56 Administrator + * 前置机功能完善 + * + * Revision 1.1 2005/10/12 06:03:47 Administrator + * 增加前置机功能 + * + * + * 添加CVS关键字,每次提交自动更新; + * + **************************************************************************************/ +//*************************************************************** +//* udpcomm.h * +//* Liangchu Lee 2000.07.10 * +//*************************************************************** + +#ifndef __UDPPING_H_ICL__ +#define __UDPPING_H_ICL__ + +#include "common.h" + +#define MAX_DELAYTIME 20 +#define MAX_RANDOM 32 +#define MAX_NODENAME 64 +#define PINGRANDOM ("!L$Q_TO5U^8&J @T#H*F(J)+D%RG|<>T~?:{}AESRGA") + +typedef struct tagUDP_PING_INFO +{ + SOCKET rSocket __attribute__ ((packed)); + SOCKET sSocket[MAX_ADDR] __attribute__ ((packed)); + + struct sockaddr_in SerAddr __attribute__ ((packed)); + struct sockaddr_in CliAddr __attribute__ ((packed)); +} UDP_PING_INFO; + +typedef struct tagUDP_PING_REV_DATA +{ + int MsgLen __attribute__ ((packed)); + char MsgData[MAX_NET_BUF] __attribute__ ((packed)); +} UDP_PING_REV_DATA; + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// 是pc机系统还是嵌入式系统 +#ifdef PC_MACHINE +#ifdef OS_WINDOWS + #pragma pack (push,1) +#else// OS_UNIX + #pragma pack(1) +#endif //OS_UNIX +#endif + +typedef struct tagPINGINFORMATION +{ + BYTE barrRandom[MAX_RANDOM] __attribute__ ((packed)); + char szNodeName[MAX_NODENAME] __attribute__ ((packed)); + BYTE bNodeType __attribute__ ((packed)); /*节点类型*/ + WORD wNodeID __attribute__ ((packed)); /*接点号*/ + u_long inetMask __attribute__ ((packed)); /*网络掩码, 发送者, 主机字节顺序*/ + u_long inetAddr __attribute__ ((packed)); /*完整IP地址, 发送者, 主机字节顺序*/ + DWORD dwStatus __attribute__ ((packed)); /*该网络接口IP地址的状态*/ +} PINGINFORMATION; + +// 是pc机系统还是嵌入式系统 +#ifdef PC_MACHINE +#ifdef OS_WINDOWS + #pragma pack (pop) +#else// OS_UNIX + #pragma pack (0) +#endif //OS_UNIX +#endif +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void UdpPingTimer(void); +BOOL UdpPingInit(void); +void UdpPingSendData(void); +void UdpPingSendDataP2P(void); +void UdpPingReaddata(void); +void UdpPingClose(void); + +// +void UdpPingSwitch(void); +#endif diff --git a/widgets.cpp b/widgets.cpp new file mode 100644 index 0000000..2fe7b84 --- /dev/null +++ b/widgets.cpp @@ -0,0 +1,153 @@ +锘// widgets.cpp : 姝ゆ枃浠跺寘鍚 "main" 鍑芥暟銆傜▼搴忔墽琛屽皢鍦ㄦ澶勫紑濮嬪苟缁撴潫銆 +// +#define OS_WINDOWS 0 +#include +#include "baohua.h" +#include "buban103.h" +#include "buban104.h" +#include "scadaprotect.h" + +// 缃戠粶绔彛鏁版嵁锛岃寖鍥翠负 0 - 16 +#define NET_PORT_NUM 8 + +extern const char *gpStrBuban103ConfigInfo[]; +extern const char *gpStrBuban104ConfigInfo[]; +extern const char *gpStrScadaProtectConfigInfo[]; + +u_char Bit_8_Mask[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; +BYTE SyncWordEB[6] = { 0xeb, 0x90, 0xeb, 0x90, 0xeb, 0x90 }; +BYTE SyncWordD7[6] = { 0xd7, 0x09, 0xd7, 0x09, 0xd7, 0x09 }; +FUNCTION_CALL FunctionCall[] = +{ + // 閰嶇疆涓绌哄崗璁, 涓昏鐢ㄤ簬澶勭悊鍗忚搴忓垪涓洪浂鐨勬儏鍐, 濡傞浂鍒濆鍊肩瓑 + {(char*)"none", (char*)"none", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + // 鏃佽矾鍗忚锛岀敤浜庡湪涓婁綅鏈鸿皟璇曡绾︾▼搴 + {(char*)"bypass", (char*)"bypass", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + + // BUBAN103瑙勭害 + {(char*)"BUBAN103", (char*)"BUBAN103 protocol", NULL, Buban103ReadConfig,\ + Buban103RecvData, Buban103Timer, Buban103YkYtProcess, Buban103SendSystemTime,\ + Buban103Exit, Buban103BaoHuCmdProcess, Buban103GetBaohuDataBase}, + + // BUBAN104瑙勭害 + {(char*)"BUBAN104", (char*)"BUBAN104 protocol", NULL, Buban104ReadConfig,\ + Buban104RecvData, Buban104Timer, Buban104YkYtProcess, Buban104SendSystemTime,\ + Buban104Exit, Buban104BaoHuCmdProcess, Buban104GetBaohuDataBase}, + + // SCADAPROTECT瑙勭害 + {(char*)"SCADAPROTECT", (char*)"SCADA INSIDE", NULL, ScadaProtectReadConfig,\ + ScadaProtectRecvData, ScadaProtectTimer, ScadaProtectYkYtProcess, NULL,\ + ScadaProtectExit, ScadaProtectBaoHuCmdProcess, ScadaProtectGetBaohuDataBase}, + + // 娣诲姞鍗忚鍚嶇О鍙婂鐞嗙▼搴忓叆鍙g瓑 + {(char*)" ", (char*)" ", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} // 缁撴潫鏍囧織 +}; + +int InitBaohuMainFlag = 0; + +//int testcnt = 0; +//char testbuf[] = "1234567890"; + +void BaohuLibMain(int netportnum); + +int main(void) +{ + std::cout << "Hello World!\n"; + + int ret = SUCCESS; + char filename[256]; + WSADATA WSAData; + + //瀹氭椂鍣ㄦ寚閽堢疆绌 + //m_pMainTimer = NULL; + //璇ユ浠g爜杩涘叆鐜鍙橀噺KERNELFEND_ROOT鎵鎸囧畾鐨勭洰褰 + char* envBuf; + envBuf = getenv("CAC_ROOT"); + if (envBuf != NULL) //濡傛灉鍙栧緱鐜鍙橀噺锛屽垯浣跨敤鍏舵墍鎸囧畾鐨勭洰褰 + { + sprintf(IniFilePath, "%s/ini", envBuf); + } + else //濡傛灉鏈彇寰楃幆澧冨彉閲忥紝鍒欎娇鐢ㄥ綋鍓嶅伐浣滅洰褰 + { + _getcwd(IniFilePath, sizeof(IniFilePath)); + } + + //娓呯┖鏁版嵁鏂囦欢鍚 + memset((void*)pvDataFileName, 0, sizeof(pvDataFileName)); + + //閲囩敤鍝堝笇琛ㄨ閰嶇疆鏂囦欢config.ini modified by jessie in 20060729 + sprintf(filename, "%s/config.ini", IniFilePath); + ret = conf_open(filename, &pvconf_handle); + if (SUCCESS != ret) + { + printf("WARN(%04d): load config.ini is failed\n", _getpid()); + return -1; + } + + //閲囩敤鍝堝笇琛ㄨ閰嶇疆鏂囦欢portconfig.ini modified by jessie in 20060729 + sprintf(filename, "%s/portconfig.ini", IniFilePath); + ret = conf_open(filename, &pvportconf_handle); + if (SUCCESS != ret) + { + printf("WARN(%04d): load portconfig.ini is failed\n", _getpid()); + return -1; + } + + // 鍒濆鍖栨暟鎹睆璁剧疆鏁版嵁搴撴寚閽 + if (InitBaohuMainFlag == 0) + { + FunCallPtr = &FunctionCall[0]; + + strcpy(DeviceName, DEVIVE_NAME); + strcpy(Version, VERSION); + strcpy(VersionDate, VERSION_DATE); + strcpy(Manufacturer, MANUFACTURER); + + InitBaohuMainFlag = 1; + if (WSAStartup(MAKEWORD(2, 1), (LPWSADATA)&WSAData) != 0) + { + ret = WSAGetLastError(); + //HostWSAStartupErr = TRUE; + //return FALSE; + } + + } + + // 娴嬭瘯绋嬪簭锛屼骇鐢熶笅鍙戞暟鎹紝姝e父鏄绾︾▼搴忎骇鐢熸暟鎹 +// if ( testcnt != DayTime.Sec ) +// { +// testcnt = DayTime.Sec; +// PutPollCmdToBuf( 0, NORMAL_CMD_TYPE, 0, testbuf, strlen(testbuf)); +// } + + for(;;) + BaohuLibMain(NET_PORT_NUM); + + if (pvconf_handle != NULL) + { + conf_close(pvconf_handle); + pvconf_handle = NULL; + } + if (pvportconf_handle != NULL) + { + conf_close(pvportconf_handle); + pvportconf_handle = NULL; + } + if (pvdataconf_handle != NULL) + { + conf_close(pvdataconf_handle); + pvdataconf_handle = NULL; + } +} + +// 杩愯绋嬪簭: Ctrl + F5 鎴栬皟璇 >鈥滃紑濮嬫墽琛(涓嶈皟璇)鈥濊彍鍗 +// 璋冭瘯绋嬪簭: F5 鎴栬皟璇 >鈥滃紑濮嬭皟璇曗濊彍鍗 + +// 鍏ラ棬浣跨敤鎶宸: +// 1. 浣跨敤瑙e喅鏂规璧勬簮绠$悊鍣ㄧ獥鍙f坊鍔/绠$悊鏂囦欢 +// 2. 浣跨敤鍥㈤槦璧勬簮绠$悊鍣ㄧ獥鍙h繛鎺ュ埌婧愪唬鐮佺鐞 +// 3. 浣跨敤杈撳嚭绐楀彛鏌ョ湅鐢熸垚杈撳嚭鍜屽叾浠栨秷鎭 +// 4. 浣跨敤閿欒鍒楄〃绐楀彛鏌ョ湅閿欒 +// 5. 杞埌鈥滈」鐩>鈥滄坊鍔犳柊椤光濅互鍒涘缓鏂扮殑浠g爜鏂囦欢锛屾垨杞埌鈥滈」鐩>鈥滄坊鍔犵幇鏈夐」鈥濅互灏嗙幇鏈変唬鐮佹枃浠舵坊鍔犲埌椤圭洰 +// 6. 灏嗘潵锛岃嫢瑕佸啀娆℃墦寮姝ら」鐩紝璇疯浆鍒扳滄枃浠垛>鈥滄墦寮鈥>鈥滈」鐩濆苟閫夋嫨 .sln 鏂囦欢 diff --git a/widgets.vcxproj b/widgets.vcxproj new file mode 100644 index 0000000..422c90c --- /dev/null +++ b/widgets.vcxproj @@ -0,0 +1,211 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {EEA43B07-32A7-4DE8-9E7F-20AE51E2C1A9} + Win32Proj + widgets + 10.0.17763.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;DISABLE_OS_HEAP + true + /UTF-8 %(AdditionalOptions) + + + Console + true + Ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/widgets.vcxproj.filters b/widgets.vcxproj.filters new file mode 100644 index 0000000..84d8d21 --- /dev/null +++ b/widgets.vcxproj.filters @@ -0,0 +1,168 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + 婧愭枃浠 + + + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + + + \ No newline at end of file diff --git a/widgets.vcxproj.user b/widgets.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/widgets.vcxproj.user @@ -0,0 +1,4 @@ +锘 + + + \ No newline at end of file