// SportIdent.h: interface for the SportIdent class. // ////////////////////////////////////////////////////////////////////// #pragma once #include #include #include "oPunch.h" /************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2023 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ const BYTE STX=0x02; const BYTE ETX=0x03; const BYTE ACK=0x06; const BYTE DLE=0x10; const BYTE WAKEUP=0xFF; const BYTE NAK=0x15; // This is taken from r56 and checked in on r63 #include class gdioutput; struct SICard5Detect { BYTE code;//Code; BYTE len; SHORT station; DWORD number; WORD crc; }; struct SIPunch { DWORD Code; DWORD Time; void analyseHour12Time(DWORD zeroTime); }; enum class ConvertedTimeStatus { Unknown = 0, Hour12, Hour24, Done, }; struct SICard { SICard(ConvertedTimeStatus status) { clear(0); convertedTime = status; } // Clears the card if this == condition or condition is 0 void clear(const SICard *condition) { if (this==condition || condition==0) memset(this, 0, sizeof(SICard)); } void analyseHour12Time(DWORD zeroTime); bool empty() const {return CardNumber==0;} DWORD CardNumber; SIPunch StartPunch; SIPunch FinishPunch; SIPunch CheckPunch; DWORD nPunch; SIPunch Punch[192]; wchar_t firstName[21]; wchar_t lastName[21]; wchar_t club[41]; int miliVolt; // SIAC voltage char readOutTime[32]; bool punchOnly; ConvertedTimeStatus convertedTime; // Used for manual time input int runnerId; int relativeFinishTime; bool statusOK; bool statusDNF; vector codeLogData(gdioutput &converter, int row) const; static vector logHeader(); unsigned int calculateHash() const; bool isManualInput() const {return runnerId != 0;} string serializePunches() const; void deserializePunches(const string &arg); int getFirstTime() const; }; struct SI_StationData { SI_StationData(); int stationNumber; int stationMode; bool extended; bool handShake; bool autoSend; int radioChannel; }; struct SI_StationInfo { SI_StationInfo(); HANDLE ThreadHandle; wstring ComPort; HANDLE hComm; COMMTIMEOUTS TimeOuts; vector data; int stationMode() const { if (data.empty()) return 0; else return data[0].stationMode; } bool extended() const { if (data.empty()) return false; bool ext = true; for (size_t k = 0; k < data.size(); k++) { if (!data[k].extended) ext = false; } return ext; } //Used for TCP ports WORD tcpPort; int localZeroTime; }; class SportIdent { protected: bool useSubsecondMode = false; bool readSI6Block(HANDLE hComm, BYTE *data); bool readSystemData(SI_StationInfo *si, int retry=2); bool readSystemDataV2(SI_StationInfo &si); CRITICAL_SECTION SyncObj; int readByte_delay(BYTE &byte, HANDLE hComm); int readBytes_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDLE hComm); int readBytesDLE_delay(BYTE *byte, DWORD buffSize, DWORD len, HANDLE hComm); int readByte(BYTE &byte, HANDLE hComm); int readBytes(BYTE *byte, DWORD len, HANDLE hComm); int readBytesDLE(BYTE *byte, DWORD len, HANDLE hComm); // Returns zero on failure, number of bytes used on success. int analyzeStation(BYTE *db, SI_StationData &si); SI_StationInfo SI_Info[32]; int n_SI_Info; //Number of structures.. SI_StationInfo *Current_SI_Info; //Current SI_Info in use (for thread startup); WORD calcCRC(BYTE *data, DWORD length); bool checkCRC(BYTE *bf, DWORD maxLen); void setCRC(BYTE *bf); bool getCard5Data(BYTE *data, SICard &card); bool getCard6Data(BYTE *data, SICard &card); bool getCard9Data(BYTE *data, SICard &card); DWORD GetExtCardNumber(const BYTE *data) const; void getSI5Data(HANDLE hComm); void getSI5DataExt(HANDLE hComm); void getSI6Data(HANDLE hComm); void getSI6DataExt(HANDLE hComm); void getSI9DataExt(HANDLE hComm); void analyseSI5Time(BYTE *data, DWORD &time, DWORD &control); bool analysePunch(BYTE *data, DWORD &time, DWORD &control, bool subSecond); void analyseTPunch(BYTE *data, DWORD &time, DWORD &control); //Card read waiting to be processed. list ReadCards; HWND hWndNotify; DWORD ClassId; volatile int tcpPortOpen; volatile size_t serverSocket; bool MonitorTEST(SI_StationInfo &si); bool MonitorSI(SI_StationInfo &si); int MonitorTCPSI(WORD port, int localZeroTime); struct TestCard { int cardNo; vector punches; bool operator<(const TestCard &c) const { return cardNo < c.cardNo; } TestCard(int cardNo, const vector &punches) : cardNo(cardNo), punches(punches) { } }; set testCards; bool readVoltage; vector punchMap; SI_StationInfo* findStationInt(const wstring& com); void addTestStation(const wstring& com); public: map getSpecialMappings() const; void addSpecialMapping(int code, oPunch::SpecialPunch); void removeSpecialMapping(int code); const SI_StationInfo *findStation(const wstring &com) const; /** Log debug data. */ void debugLog(const wchar_t *ptr); void getInfoString(const wstring &com, vector> &info) const; bool isAnyOpenUnkownUnit() const; bool isPortOpen(const wstring &com); bool autoDetect(list &ComPorts); void stopMonitorThread(); void startMonitorThread(const wchar_t *com); bool getCard(SICard &sic); void addCard(const SICard &sic); void addPunch(DWORD Time, int Station, int Card, int Mode=0); void addTestCard(int cardNo, const vector &punches); void EnumrateSerialPorts(list &ports); void closeCom(const wchar_t *com); bool openCom(const wchar_t *com); bool tcpAddPort(int port, DWORD zeroTime); bool openComListen(const wchar_t *com, DWORD BaudRate); SportIdent(HWND hWnd, DWORD Id, bool readVoltage); void setSubSecondMode(bool subSec) { useSubsecondMode = subSec; } void resetPunchMap(); virtual ~SportIdent(); friend void start_si_thread(void *ptr); };