/***************************************************************************
                          knutnet.cpp  -  description
                             -------------------
    begin                : Ne led 12 2003
    copyright            : (C) 2003 by Daniel Prynych
    email                : Daniel.Prynych@alo.cz
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "knutnet.h"

#include <tqtextstream.h>
#include <tqstring.h>
#include <tqcstring.h>
#include <tqtimer.h>


#include <unistd.h>  // for function sleep

//#include <iostream>



/****** CONSTS ***********/

//const TQ_ULONG rBufferLen = 1024;



KNutNet::KNutNet (const TQString upsAddress, const TQString upsName, const unsigned short port, unsigned int countRepeat, const unsigned  int delay)
        : TQObject(), m_upsAddress(upsAddress), m_upsName(upsName), m_countRepeat(countRepeat), m_port(port), m_delay(delay)  {


//tqDebug ("KNutNet::KNutNet");

  m_state = Idle;  //idle is value
  m_numberVars = 0;
  m_numberRWVars = 0;
  m_numberIComms = 0;
  m_upsStatusVar = 0;
  m_nutProtocol = 0;
  m_nutVariables = 0;
  m_switchToTCP = false;

  m_description = false; // popis neni natazen  - description is not loaded

  m_unConnectTimer = new TQTimer( this );
  connect( m_unConnectTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotTimerReconnect()) );

  m_error = NoError;

  m_commandSocket = new TQSocket( this );
  connect( m_commandSocket, TQ_SIGNAL( hostFound()),this, TQ_SLOT( slotHostFound()));
  connect( m_commandSocket, TQ_SIGNAL( connected()),this,TQ_SLOT( slotConnected()));
  connect( m_commandSocket, TQ_SIGNAL( connectionClosed()),this, TQ_SLOT( slotConnectionClosed()));
  connect( m_commandSocket, TQ_SIGNAL( error(int)),this, TQ_SLOT( slotConnectionError(int)));
  }


KNutNet::~KNutNet(){
  TQCString  inBuffer;
  TQString  outBuffer;

  close(); // close connetion when is existed
    while (m_state == Closing ) {
      sleep (100);
      }
//  deleteVars() is made in close();
  }


void KNutNet::close (void) {
// std::cout << "--KNutNet::close"  << std::endl;
  TQCString  inBuffer;
  TQString  outBuffer;

  m_unConnectTimer->stop();
  deleteVars();
  if ((m_state == Connected) || (m_state == Connecting)) {
    m_state = Closing;
    if (m_state == Connected) {
      inBuffer="LOGOUT\n";
      getUpsData (inBuffer,outBuffer);
      // getUpsDate makes "commandSocket->flush()"
      }

    if (m_commandSocket->bytesToWrite () > 0) sleep (1000);
    m_commandSocket->clearPendingData (); //  data in  output buffer will be errased
    m_commandSocket->close(); // closes the socket

    if ( m_commandSocket->state() == TQSocket::Closing ) {
      connect( m_commandSocket, TQ_SIGNAL(delayedCloseFinished()),this,TQ_SLOT(slotClosed()) );
      }
    else {
      slotClosed();
      }
    }
  }

void KNutNet::slotClosed (void) {

  disconnect( m_commandSocket,TQ_SIGNAL(delayedCloseFinished()),this, TQ_SLOT(slotClosed()) );
  m_state = Idle;
  }


void KNutNet::open (void) {

  TQCString  inBuffer;
  TQString  outBuffer;

  if ((m_state == Connected) || (m_state == Connecting)) close(); // close connetion when is existed
  else {
    while (m_state == Closing ) {
      sleep (100);
      }
    }
  if (m_upsAddress != "") {
    if ( m_commandSocket->state() != TQSocket::Connecting ) {
      m_firstConnect=true;
      m_numberConnection=0;
      m_state = HostLookup;
      emit tryFirstConnection(m_countRepeat); // how many times we can try to connect with ups server /upsd/
//    std::cout << "--KNutNet :: Open emit - tryFirstConnection" << std::endl;
      m_commandSocket->connectToHost(m_upsAddress,m_port);
      }
    }
  }


void KNutNet::newUPS (const TQString upsAddress, const TQString upsName, const unsigned short port) {

  if ((m_state == Connected) || (m_state == Connecting)) { 
    close();
    while (m_state == Closing ) {
      sleep (100);
      }
    }

  m_upsAddress = upsAddress;
  m_upsName = upsName;
  m_port = port;

  m_state = Idle;
  m_numberVars = 0;
  m_numberRWVars = 0;
  m_numberIComms = 0;
  m_upsStatusVar = 0;
  m_nutProtocol = 0;
  m_nutVariables = 0;
  m_switchToTCP = false;

  m_error = NoError;
  //firstConnect=true;
  //numberConnection=0;
  }



int KNutNet::getError ( void ) { return m_error; }

int KNutNet::getState ( void ){ return m_state; }

bool KNutNet::isDescription ( void ){ return m_description; }

int KNutNet::getNutProtocol ( void ) { return m_nutProtocol; }

int KNutNet::getNutVariables ( void ) { return m_nutVariables; }

bool KNutNet::switchedToTCP ( void ) { return m_switchToTCP; }


int KNutNet::getUpsVars ( void) {
  int returnValue;

  m_error=0;
  if (m_state == Connected) {

    // init vars and lists
    m_numberVars = 0;
    m_numberRWVars = 0;
    m_numberIComms = 0;
    deleteVars();
    int countWaitRevision = 5;
    do {
      switch (m_nutProtocol) {
        case 1:
          returnValue = getUpsVars1();
        break;
        case 2:
          returnValue = getUpsVars2();
        break;
        default:
        return 0;
        }
      if ( readStatus() != KNutNet::WAIT) return returnValue;
      countWaitRevision--;
      if (countWaitRevision) sleep (2);
      }
    while (countWaitRevision);
    return NoListVars; //getUpsVars can't read list variables
    }
  else {
    return NotConnection;
    }
  }


int KNutNet::getUpsValues (const bool allVars ) {// allVars = true vse; allVars = false jen activate

  m_error=0; // vynulujeme chyby
  if (m_state == Connected) {
    // init vars and lists
    switch (m_nutProtocol) {
      case 1:
        return getUpsValues1(allVars);
      break;
      case 2:
        return getUpsValues2(allVars);
      break;
      default:
      return 0;
      }
    }
  else {
    return NotConnection;
    }
  }  



int KNutNet::getDescription (bool always) {

  m_error=0; // vynulujeme chyby
  if (m_state == Connected) {
    switch (m_nutProtocol) {
      case 1:
        return getDescription1 (always);
      break;
      case 2:
        return getDescription2 (always);
      break;
      default:
        return 0;
      }
    }  
  else return NotConnection;
  }


int KNutNet::instantCommand (const TQString command, const TQString userName, const TQString password, const bool onlyCommand) {
  m_error=0; // vynulujeme chyby

  if (m_state == Connected) {
    TQString outBuffer;

    // funkce sendComm sama mastavi promenou error
    if (onlyCommand) {
      if (!(m_error = sendComm("INSTCMD", command, "",true))) {
//        netMutex=false;
        return 0;
        }
      else { 
//        netMutex=false;
        return m_error;
        }
      }
    else {




      if (!(m_error = sendComm ("USERNAME", userName, ""))) {
        if (!(m_error = sendComm("PASSWORD", password, ""))) {
          if (!(m_error = sendComm("INSTCMD", command, "",true))) {
//            netMutex=false;
            return 0;
            }
          else { 
            return m_error; // spatny prikaz
            }
          } //username
        else { 
          return m_error;  //spatne helso
	  }
        }
      else {
	return m_error; // spatne jmeno
	}
      }
    }
  else return NotConnection;
  }


int KNutNet::setVariable (const TQString variable, const TQString value, const TQString userName, const TQString password, const bool onlyVariable) {
  m_error=0; // vynulujeme chyby
  if (m_state == Connected) {
    TQString outBuffer;
    TQString setCommand;

    switch (m_nutProtocol) {
      case 1: setCommand = "SET";
         break;
      case 2: setCommand = "SET VAR";
      }
    if (onlyVariable) {
      if (!(m_error = sendComm(setCommand, variable, value, true))) {
        return 0;
        }
      else { 
        return m_error;
        }
      }
    else {
      if (!(m_error = sendComm ("USERNAME", userName, ""))) {
        if (!(m_error = sendComm("PASSWORD", password, ""))) {
          if (!(m_error = sendComm(setCommand, variable, value, true))) {
            //netMutex=false;
            return 0;
            }
          else {
	    return m_error;
	    }
          } //username
        else {
	  return m_error;
	  }
        }
      else {
	 return m_error;
	 }
      }
    }
  else return NotConnection;
  }


int KNutNet::readNumberVars (typeOfVar typVar) {
//  Vraci pocet promenych
  m_error=0;
  if (m_state == Connected) {
    switch (typVar) {
      case AllVars:
        return m_numberVars;
        break;
      case ROVars:
        return m_numberVars - m_numberRWVars;
        break;
      case RWVars:
        return m_numberRWVars;
        break;
      default:
        return -1;
      }
    }
  else return -1;
  }

int KNutNet::readNumberComms (void) {
//  Vraci pocet prikazu
  m_error=0;
  if (m_state == Connected) return m_numberIComms;
  else return -1;
  }


int KNutNet::readIComm (const int seqNumber, upsICommDef& upsIComm) {
  m_error =0;
  if (m_state == Connected) {
    if ((seqNumber < 1) || ((unsigned int)seqNumber > m_listIComms.size())) {
      m_error=CommNotFind;
      return m_error;
      }
    upsIComm = m_listIComms[seqNumber-1];
    return 0;
    }
  else return NotConnection;
  }


int KNutNet::readVars (const TQString name, struct upsVarDef& allVar) {
  m_error =0;
  if (m_state == Connected) {
      TQValueVector<upsVarDef>::const_iterator it;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
       if ((*it).upsVarName == name) {
         allVar = (*it);
         return 0;
         }
       }
     m_error=VarNotFind;
     return m_error;
    }
  else return NotConnection;
  }

  int KNutNet::readVars (const int seqNumber, struct upsVarDef& allVar, const typeOfVar typVar) {

  m_error =0;
  if (m_state == Connected) {
    int n = 1;
    TQValueVector<upsVarDef>::const_iterator it;

    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      if ((typVar== AllVars) || ((typVar==ROVars) && ((*it).upsVarType)) ||
        ((typVar==RWVars) && (!(*it).upsVarType))) {
        if (n == seqNumber) {
          allVar = (*it);
          return 0;
          }
        n++;
        }
      }
    m_error=VarNotFind;
    return m_error;
    }
  else return NotConnection;
  }


TQString KNutNet::readStringVar (const TQString name) {

  m_error =0;
  if (m_state == Connected) {
      TQValueVector<upsVarDef>::const_iterator it;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      if ((*it).upsVarName == name) return (*it).upsValue;
      }
    m_error = VarNotFind;
    return 0l;  
    }
  else return 0l;
}


TQString KNutNet::readEnumValueVar (const TQString name, const int valueNumber) {

  m_error =0;
  if (m_state == Connected) {
//    #if defined  (TDE_VERSION_MAJOR)
//      #if TDE_VERSION_MAJOR >= 3
        TQValueVector<upsVarDef>::const_iterator it;
//      #else
//        TQValueList<upsVar>::ConstIterator it;
//      #endif
//    #else
//      TQValueList<upsVar>::ConstIterator it;
//    #endif


    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      if ((*it).upsVarName == name) {
        if ((valueNumber < 1) || (valueNumber > (*it).upsVarMax)) {
          m_error=EnumValueNotFind;
          return 0l;
          }
        // vratime hodnotu
        return (*(*it).upsEnumValues)[valueNumber-1];
        }
      }
    m_error = VarNotFind;
    return 0;
    }
  else return 0;
  }


int KNutNet::readStatus(void) {

  m_error=0;
  return m_upsStatusVar;
  }


int KNutNet::setActivate ( const TQString name ) {
  return activate (name,true);
  }


int KNutNet::unSetActivate ( const TQString name ) {
  return activate (name,false);
  }


int KNutNet::unSetActivateAll ( void ) {
  return activateAll (false);
  }


int KNutNet::existName ( const TQString name ) {

  m_error =0;
  if (m_state == Connected) {
        TQValueVector<upsVarDef>::const_iterator it;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      if ((*it).upsVarName == name) return 0;
      }
    m_error = VarNotFind;
    return m_error;
    }
  else return NotConnection;
  }

/*************************************************************************/  
/*                                                                       */
/*                           PRIVATE FUNCTIONS                           */
/*                                                                       */
/*************************************************************************/


int KNutNet::version (int countRepeat, const int delay) {
  TQCString  inBuffer;
  TQString  outBuffer;

  m_error =0;
  do {
    inBuffer="VER\n";
    if (!(m_error=getUpsData (inBuffer,outBuffer))) {
      outBuffer=outBuffer.stripWhiteSpace ();

      if (outBuffer.length() > 0) {
        outBuffer = outBuffer.mid(outBuffer.find("upsd")+4);
        int n = outBuffer.find(".");
        if (n > 0) {
          TQString firstNumber= outBuffer.left(n);
          TQString secondNumber= outBuffer.mid(n+1);
          int n = secondNumber.find(".");
          if (n > 0) {
            bool ok;
            secondNumber = secondNumber.left(n);
            int secondInt = secondNumber.toInt(&ok);
            if (!ok) {m_error = UnknownFormatVer; return m_error;}
            int firstInt = firstNumber.toInt(&ok);
            if (!ok) {m_error = UnknownFormatVer; return m_error;}
            if ((firstInt == 0) || ((firstInt == 1)  && (secondInt < 3))) {
              m_nutProtocol =1;
              m_nutVariables =1;
              }
            else {
              m_nutProtocol =2;
              m_nutVariables =2;
              }
            return 0;
            }
          else m_error = UnknownFormatVer; // n is <= 0 the second dot
          }
        else m_error = UnknownFormatVer; // n is <= 0 the first dot
        }
      m_error = UnknownAnswer; // i cannot specify number of protocol and number of variables
      return m_error;
      }
    countRepeat--;
    if (countRepeat) sleep (delay);
    }
  while ((countRepeat));
  return m_error;
  }



int KNutNet::getFirstUpsName (TQString& firstUpsName) {
  TQCString  inBuffer;
  TQString  outBuffer;
  TQString  varOutBuffer;
  int lenString;

  m_error=0;
  inBuffer = "LIST UPS\n";
  if (!(m_error=getUpsData (inBuffer,outBuffer,"END LIST UPS"))) {

    TQString inLine, upsNameRet, varName, value;
    int key, typeValue;
    bool beginList = false;
    TQTextIStream varInputStream(&outBuffer);
    while (!(inLine = varInputStream.readLine()).isNull()) {
      key = parseLine (inLine, upsNameRet, varName, value, typeValue, lenString);
      switch (key) {
        case BEGIN_LIST_UPS: {
          beginList = true;;
          break;
          }
        case UPS:
         if (beginList ) {
           firstUpsName = upsNameRet;
           return 0;
           }
        case END_LIST_UPS:
          firstUpsName = "";
            m_error=NoUpsHere;
            return m_error;
        case ERR:
          m_error = upsTranslateError(value);
          return m_error;
        default:
          m_error=UnknownAnswer;
          return m_error;
        }
      }// end while
    }
  else {m_error=NoData; return m_error; }
  return 0;
  }



int KNutNet::setKey (const TQString line) {

  TQString myLine=line.stripWhiteSpace();
  if (myLine == "OK") return OK;
  if (myLine == "ERR") return ERR;
  if (myLine == "BEGIN") return BEGIN;
  if (myLine == "END") return END;
  if (myLine == "VAR") return VAR;
  if (myLine == "TYPE") return TYPE;
  if (myLine == "DESC") return DESC;
  if (myLine == "CMDDESC") return CMDDESC;
  if (myLine == "UPSDESC") return CMDDESC;
  if (myLine == "UPS") return UPS;
  if (myLine == "LIST") return LIST;
  if (myLine == "RW") return RW;
  if (myLine == "CMD") return CMD;
  if (myLine == "ENUM") return ENUM;
  if (myLine == "STARTTLS") return STARTTLS;
  return NONE;
  }

TQString KNutNet::parseValue (const TQString line) {

  if (line.isEmpty()) return "";
  if (line[0] != "\"") {
    if ((m_posChar=line.find(' ')) == -1) return line;
    else return line.left(m_posChar+1);
    }
  else {
    int len = line.length();
    TQString outString = "";
    for (int i=1; i < len; i++) {
      if ( line[i] == "\\") {
        if ((i+1) <len) {
          if ((line[i+1] == "\"") || (line[i+1] == "\"")) {
            outString +=line[i+1];
            i++;
            }
          else i +=2;  
          }
        outString +=line[i];
        continue;
        }
      if (line [i] == "\"") {
        return outString;
        }
      outString += line[i];    
      }
    return outString;
    }
  return "";
  }

int KNutNet::parseTypeValue (TQString line, int& lenString ) {
  int ret=0;
  TQString word;

  lenString = 0;
  if (line.isEmpty()) return 0;
  TQTextIStream inputStream(&line);
  while (!inputStream.atEnd()) {
    inputStream >> word;
    if (word == "RW") ret += RW_FLAG;
    if (word == "ENUM") ret += ENUM_FLAG;
    if (word.find("STRING:") != -1) {
      word = word.mid(7);
      ret += STRING_FLAG;
      lenString = word.toInt();
      }
    }
  return ret;
  }


int KNutNet::parseLine(TQString& line, TQString& upsName ,TQString& varName, TQString& value, int& typeValue, int& lenString) {
  int posChar;
  TQString word1, word2, word3;
  int key1, key2, key3;

  line = line.stripWhiteSpace();

  upsName = "";
  varName = "";
  value = "";
  typeValue =0;

  if (line.isEmpty()) return NONE;

  if ((posChar=line.find(' ')) == -1) {
    if (setKey(line) == OK) return OK;
    else return NONE;
    }
  else {
    key1 = setKey( line.left(posChar));
    line = line.mid(posChar+1);

    switch (key1) {

      case NONE:
        return key1;
      case OK:
        return key1;
      case ERR:
        value = parseValue(line);
        return key1;
      default:
        if ((posChar=line.find(' ')) == -1) return NONE;
        word2 = line.left(posChar);
        key2 = setKey( word2);
        line = line.mid(posChar+1);

        switch (key1) {
          case BEGIN:
            if ((key2 == LIST) && (setKey(line) == UPS)) return BEGIN_LIST_UPS;
          break;
          case END:
            if ((key2 == LIST) && (setKey(line) == UPS)) return END_LIST_UPS;
          break;
          case UPS:
            upsName = word2;
            value = parseValue(line);
            return key1;
          case CMD:
            upsName = word2;
            varName = parseValue(line);
            return key1;
          }

        if ((posChar=line.find(' ')) == -1) return NONE;

        word3 = line.left(posChar);
        key3 = setKey( word3);
        line = line.mid(posChar+1);

        switch (key1) {
          case VAR:
            upsName = word2;
            varName = word3;
            value = parseValue(line);
            return VAR;
          case TYPE:
            upsName = word2;
            varName = word3;
            typeValue = parseTypeValue(line,lenString);
            return TYPE;
          case ENUM:
            upsName = word2;
            varName = word3;
            value = parseValue(line);
            return ENUM;
          case DESC:
            upsName = word2;
            varName = word3;
            value = parseValue(line);
            return DESC;
          case CMDDESC:
            upsName = word2;
            varName = word3;
            value = parseValue(line);
            return CMDDESC;
          case BEGIN:
            if (key2 != LIST) return NONE;
            if (key3 == VAR) {
              upsName=line.stripWhiteSpace();
              return BEGIN_LIST_VAR;
              }
            if (key3 == RW) {
              upsName=line.stripWhiteSpace();
              return BEGIN_LIST_RW;
              }
            if (key3 == CMD) {
              upsName=line.stripWhiteSpace();
              return BEGIN_LIST_CMD;
              }
            if (key3 == ENUM) {
              if ((posChar=line.find(' ')) == -1) return NONE;
              upsName = line.left(posChar);
              line=line.mid(posChar+1);
              varName = line.stripWhiteSpace();
              return BEGIN_LIST_ENUM;
              }
            return NONE;  
          case END:
            if (key2 != LIST) return NONE;
            if (key3 == VAR) {
              upsName=line.stripWhiteSpace();
              return END_LIST_VAR;
              }
            if (key3 == RW) {
              upsName=line.stripWhiteSpace();
              return END_LIST_RW;
              }
            if (key3 == CMD) {
              upsName=line.stripWhiteSpace();
              return END_LIST_CMD;
              }
            if (key3 == ENUM) {
              if ((posChar=line.find(' ')) == -1) return NONE;
              upsName = line.left(posChar);
              line=line.mid(posChar+1);
              varName = line.stripWhiteSpace();
              return END_LIST_ENUM;
              }
            return NONE;
          default:
            return NONE;
          }
      }
    }
  }


int KNutNet::newDescription (const TQCString  inBuffer, TQString& upsDescription) {
  TQString  outBuffer;

  if (!(m_error=getUpsData (inBuffer,outBuffer))) {
    outBuffer=outBuffer.stripWhiteSpace ();
    TQString word1, word2, word3;

    if ((m_posChar = outBuffer.find(' ')) == -1)
      word1 = outBuffer;
    else {
      word1 = outBuffer.left(m_posChar);
      word2 = outBuffer.mid(m_posChar+1);
      }
    if (word1 == "DESC") {
      if ((m_posChar = word2.find('\"')) == -1) word3="";
      else
        {
        word3 = word2.mid(m_posChar+1);
        if ((m_posChar = word3.find('\"')) != -1) word3=word3.left(m_posChar);
        }
      if (!word3.isEmpty()) upsDescription=word3;
      }
    else {
      if (word1 == "ERR" ) return upsTranslateError(word2);
      else return UnknownAnswer;
      }
    }
  else return m_error;
  return 0;
  }


void KNutNet::cleanConnecting (void) {
  TQ_ULONG rMaxLen; 
  TQCString  recvBuffer(rBufferLen);
  TQ_LONG lengthInputData;

  int n = 0;
  while (m_commandSocket->bytesAvailable() > 0) {

    if ( (m_commandSocket->bytesAvailable()+1) > rBufferLen) rMaxLen = rBufferLen;
    else rMaxLen=m_commandSocket->bytesAvailable()+1;

    recvBuffer.resize(rMaxLen);
    if ((lengthInputData = m_commandSocket->readBlock(recvBuffer.data(),rMaxLen)) == -1) {
      }
     if (lengthInputData == 0) break;
     if (n > 20) break; else n++;
    }
  }


int KNutNet::getUpsData (const TQCString sBuffer, TQString& rBuffer, const TQCString endString) {

  //rbufferLen a sbufferLen are maximal value of buffers
  TQCString  recvBuffer(rBufferLen);
  TQ_LONG lengthInputData;
  TQ_ULONG dataAvailable;


  TQMutexLocker getUpsDataLocker( &m_getUpsDataMutex );

  cleanConnecting();
  // first we clean input TCP buffer

  //cleans buffer 
  rBuffer=""; // clean main input buffer;


  // after write block, runs command flush for sending data to server inmediately
  if (m_commandSocket->writeBlock(sBuffer.data(),sBuffer.length()) < 0 ) return SendErr;
  m_commandSocket->flush();

  if (m_commandSocket->waitForMore(1000) == 0) {
    m_commandSocket->waitForMore(500); // workaround 
    }
  bool endRecv = false;
  do {
    dataAvailable=m_commandSocket->bytesAvailable();
    if (recvBuffer.size() < (dataAvailable+1) ) recvBuffer.resize(dataAvailable+1);
    if ((lengthInputData = m_commandSocket->readBlock(recvBuffer.data(),dataAvailable)) == -1) return RecvErr;

//correct for X86_64  by Alexey Sidorov    
    recvBuffer[(int)lengthInputData]='\0';
    //    recvBuffer[lengthInputData]='\0';  

    //Problem is that
    //for 64bit environment is TQ_LONG defined like _int64 and
    //for other environments is TQ_LONG defined like long      




    rBuffer.append(recvBuffer.data()); // adds reading data to main input buffer
    if (endString.isEmpty()) endRecv = false;
    else {
      if (recvBuffer.findRev(endString.data()) == -1)  {
//doesn't find right end of input data
        if (m_commandSocket->bytesAvailable() == 0) m_commandSocket->waitForMore(1000); 
        if (m_commandSocket->bytesAvailable() > 0)  endRecv=true; // makes other cyckle og while
          else endRecv=false;
        }
//finds right end of input data
      else endRecv = false; // we have found what we want to find
      }    
    } while (endRecv);
  return 0;   // all is OK
  }



    void KNutNet::setRWVars (const TQString varName, const bool valueType, const int varMax, TQValueVector<TQString>* enumValues) {
      TQValueVector<upsVarDef>::iterator it;

   for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
     if ((*it).upsVarName == varName) {
       (*it).upsVarMax = varMax;
       (*it).upsValueType=valueType;
       (*it).upsEnumValues=enumValues;
       (*it).upsVarType=false;
       break;
       }
    }
  }

void KNutNet::upsSetType (struct upsVarDef& upsVar, const TQString name, const TQString value) {

  if (((m_nutVariables = 2) && (name == "STATUS")) || ((m_nutVariables = 2) && (name == "ups.status")))
    upsVar.upsVarActivate=true;
  else upsVar.upsVarActivate=false;

  upsVar.upsVarName = name;
  upsVar.upsVarType=true;
  upsVar.upsValueType=true;
  upsVar.upsVarMax=0;
  upsVar.upsValue=value;
  upsVar.upsDescription="";
  upsVar.upsEnumValues=0L;
}


void KNutNet::deleteVars (void) {
//  #if defined  (TDE_VERSION_MAJOR)
//    #if TDE_VERSION_MAJOR >= 3
      TQValueVector<upsVarDef>::iterator it;
//    #else
//      TQValueList<upsVar>::Iterator it;
//    #endif
//  #else
//    TQValueList<upsVar>::Iterator it;
//  #endif
  for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
    if ((*it).upsEnumValues != 0) {
      (*it).upsEnumValues->clear();
      delete (*it).upsEnumValues;
      }
    }
  m_listVars.clear();
  m_listIComms.clear();
  }

void KNutNet::genStatusFlags (TQString value) {
  m_upsStatusVar = 0;
  TQTextIStream inputStream(&value);
  TQString word;
  while (!inputStream.atEnd()) {
    inputStream >> word;
    if (word == "OFF") m_upsStatusVar +=OFF;
    if (word == "OL") m_upsStatusVar +=OL;
    if (word == "OB") m_upsStatusVar +=OB;
    if (word == "LB") m_upsStatusVar +=LB;
    if (word == "CAL") m_upsStatusVar +=CAL;
    if (word == "TRIM") m_upsStatusVar +=TRIM;
    if (word == "BOOST") m_upsStatusVar +=BOOST;
    if (word == "OVER") m_upsStatusVar +=OVER;
    if (word == "RB") m_upsStatusVar +=RB;
    if (word == "WAIT") m_upsStatusVar = WAIT;
    //OFF     -  1 ups je vypnuta
    //OL      -  2 ups je bezi na sit
    //OB      -  4 ups bezi na baterie
    //LB      -  8 baterie je vybyta (pokud je zaroven OB dojde k shutdownu)
    //CAL     - 16 je spustena kalibrace
    //OVER    - 128 ups je pretizena
    //RB      - 256 ups pozaduje vymenu baterie
    //WAIT    - 512 ups zada o strpeni // UPS asks for waiting 
    }
  }


int KNutNet::getDescription1 (bool always) {

  if (always || (! m_description)) {
    TQCString  inBuffer;
    TQString  outBuffer;

     TQValueVector<upsVarDef>::iterator itv;
     TQValueVector<upsICommDef>::iterator itc;
     for (itv = m_listVars.begin(); itv != m_listVars.end(); itv++) {
      //nacteme promenou
      inBuffer = "VARDESC " + (*itv).upsVarName.local8Bit() + "\n";
      if ((m_error = newDescription (inBuffer, (*itv).upsDescription))) {
        //netMutex.unlock();
//        netMutex=false;
        return m_error;
        }
      }
    for (itc = m_listIComms.begin(); itc != m_listIComms.end(); itc++) {
      //nacteme promenou
      inBuffer = "INSTCMDDESC "+(*itc).upsCommName.local8Bit()+"\n";
      if ((m_error = newDescription (inBuffer, (*itc).upsDescription))) {
        //netMutex.unlock();
        //netMutex=false;
        return m_error;
        }
      }
    //netMutex=false;
    m_description = true;
    }
  return 0;
  }



int KNutNet::getDescription2 (bool always) {

  if (always || (! m_description)) {
    TQCString  inBuffer;
    TQString  outBuffer;
    TQString upsNameRet;
    TQString varName;
    TQString value;
    int typeValue;
    int lenString;

     TQValueVector<upsVarDef>::iterator itv;
     TQValueVector<upsICommDef>::iterator itc;
     for (itv = m_listVars.begin(); itv != m_listVars.end(); itv++) {
      //nacteme promenou
      inBuffer = "GET DESC " + m_upsName.local8Bit() + " " + (*itv).upsVarName.local8Bit()+"\n";

      if (!(m_error=getUpsData (inBuffer,outBuffer))) {
        outBuffer=outBuffer.stripWhiteSpace ();
        if ( !outBuffer.isEmpty() ) {
          int key = parseLine(outBuffer, upsNameRet, varName, value, typeValue, lenString);
          switch (key) {
            case DESC:
              (*itv).upsDescription = value;
               break;
            case ERR:
              m_error=upsTranslateError(value);
              return m_error;
            default:
              m_error=UnknownAnswer;
              return m_error;
            }
          }
        else {
          m_error = NoData;
          return m_error;
          }
        }
      else {
        return m_error;
        }
      }
    for (itc = m_listIComms.begin(); itc != m_listIComms.end(); itc++) {
      //nacteme promenou
      inBuffer = "GET CMDDESC " + m_upsName.local8Bit() + " " + (*itc).upsCommName.local8Bit()+"\n";
      if (!(m_error=getUpsData (inBuffer,outBuffer))) {
        outBuffer=outBuffer.stripWhiteSpace ();
        if ( !outBuffer.isEmpty() ) {
          int key = parseLine(outBuffer, upsNameRet, varName, value, typeValue, lenString);
          switch (key) {
            case CMDDESC:
              (*itc).upsDescription = value;
               break;
            case ERR:
              m_error=upsTranslateError(value);
              return m_error;
            default:
              m_error=UnknownAnswer;
              return m_error;
            }
          }
        else {
          m_error = NoData;
          return m_error;
          }
        }
      else {
        return m_error;
        }
      }
    m_description = true;
    }
  return 0;
  }



int KNutNet::getUpsVars1 ( void) {
// getUpsVars nacte promene a jejich typ
// vraci kod chyby nebo 0 pokud je vse v poradku
  TQCString  inBuffer;
  TQString  outBuffer;
  TQString  varOutBuffer;
  upsVarDef upsVar;
  upsICommDef upsIComm;

  // init vars and lists
  if (!m_upsName.isEmpty()) { // pokud upsName neni je vzdy nastaveno na null
    inBuffer="LISTVARS ";
    inBuffer.append(m_upsName.local8Bit());
    inBuffer.append("\n");
    }
  else inBuffer ="LISTVARS\n";

  if (!(m_error=getUpsData (inBuffer,outBuffer))) {
    outBuffer=outBuffer.stripWhiteSpace ();
    if (outBuffer.length() > 0) {
    // precteme data
      TQTextIStream inputStream(&outBuffer);
      TQString word;
      int count =1 ;
      while (!inputStream.atEnd()) {
        inputStream >> word;
        switch (count) {
          case 1:
          // vyndame prvni polozku
          if (word == "VARS") count++;
          else {
            if (word == "ERR") {
              inputStream >> word;
              m_error = upsTranslateError(word);
              }
            else m_error=UnknownAnswer;
            return m_error;
            }
          break;
        case 2:
          count++;
          if ((word.length() > 0) && word.startsWith("@")) break;
          default:
          // pridame polozku do tabulky
          upsSetType(upsVar, word);
          m_listVars.push_back(upsVar);
          m_numberVars++;
          break;
          }
        }
      }
    else { m_error=NoData; return m_error; }
    }
  else return m_error;

  if ((m_error = getUpsValues1(true))) return m_error;

  // *********** RW VARIABLES
  if (!m_upsName.isEmpty()) { // pokud upsName neni je vzdy nastaveno na null
    inBuffer="LISTRW ";
    inBuffer.append(m_upsName.local8Bit());
    inBuffer.append("\n");
    }
  else inBuffer ="LISTRW\n";

  if (!(m_error=getUpsData (inBuffer,outBuffer))) {
    outBuffer=outBuffer.stripWhiteSpace();
    if (!outBuffer.isEmpty()) {
    // precteme data
      TQTextIStream inputStream(&outBuffer);
      TQString word;
      int count =1 ;
      bool valueType;
      int varMax;
      while (!inputStream.atEnd()) {
        inputStream >> word;
        switch (count) {
          case 1:
          // vyndame prvni polozku
           if (word == "RW") count++;
           else {
             if (word == "ERR") {
               inputStream >> word;
               m_error = upsTranslateError(word);
               }
             else m_error=UnknownAnswer;
             return m_error;
             }
          break;
          case 2:
          count++;
          if ((word.length() > 0) && word.startsWith("@")) break;
          default:
          // Zpracujeme polozku v tabulce
          // zjistime informaci o promene
          inBuffer="VARTYPE ";
          inBuffer.append(word.local8Bit());
          if (!m_upsName.isEmpty()) {
            inBuffer.append("@"); // pokud upsName neni je vzdy nastaveno na null
            inBuffer.append(m_upsName.local8Bit());
            }
          inBuffer.append("\n");
          if (!(m_error=getUpsData (inBuffer,varOutBuffer))) {
            varOutBuffer=varOutBuffer.stripWhiteSpace();
            if ( !outBuffer.isEmpty() ) {
              TQTextIStream varInputStream(&varOutBuffer);
              TQString word1, word2, word3;
              varInputStream >> word1;
              varInputStream >> word2;
              varInputStream >> word3;
              if (word1 == "TYPE") {
                if ((word2.isEmpty()) || (word3.isEmpty())) {
                  m_error=UnknownFormat;
                  return m_error;
                  }
                if (word2 == "ENUM") valueType=false;
                else {
                  if (word2 =="STRING") valueType=true;
                  else {
                    m_error=UnknownFormat;
                    return m_error;
                    }
                  }
                bool ok = true;
                varMax=word3.toInt(&ok);
                if (!ok) {m_error=UnknownFormat; return m_error;};
                } // word1 = Type
              else {
                if (word1=="ERR") {
                  m_error = upsTranslateError(word2);
                  return m_error;
                  }
                else {
                  m_error = UnknownAnswer;
                  return m_error;
                  }
                }
              }
            else { m_error=NoData; return m_error; }
            }
          else return m_error;
          // ********** ENUM / STRING ******************

          TQValueVector<TQString>* enumString=0;
          if (!valueType) {
          // nacteme enum hodnoty
            inBuffer="ENUM ";
            inBuffer.append(word.local8Bit());
            // pokud existuje pridame jmeno UPS-ky
            if (!m_upsName.isEmpty()) {
              inBuffer.append("@");
              inBuffer.append(m_upsName.local8Bit());
              }
            inBuffer.append("\n");
            if (!(m_error=getUpsData (inBuffer,varOutBuffer,"END\n"))) {
//               varOutBuffer.stripWhiteSpace();  nemuze provest protoze bychom si odstranili konce radek
              if (!varOutBuffer.isEmpty()) {
                TQString inLine, word1, word2;
                TQTextIStream varInputStream(&varOutBuffer);
                int inCountLine=1;
                while (!(inLine = varInputStream.readLine()).isNull()) {
                  inLine=inLine.stripWhiteSpace();

                  if ((m_posChar=inLine.find(' ')) == -1) word1=inLine;
                  else {
                    word1=inLine.left(m_posChar);
                    inLine = inLine.mid(m_posChar+1);
                    }
                  if (word1.isEmpty()) { m_error = UnknownFormat; return m_error; }
                  if (inCountLine == 1) {
                  if ((m_posChar=inLine.find(' ')) == -1) word2=inLine;
                  else word2=inLine.left(m_posChar);
                    if (word1 =="ENUM") {
                      if (word2 != word) { m_error = UnknownFormat; return m_error; }
                      varMax=0;
                      inCountLine++;
                      enumString = new TQValueVector<TQString>;
                      enumString->clear();
                      }
                    else {
                      if (word1=="ERR")
                        m_error=upsTranslateError(word2); // prevede chybu na jeji kod
                      else m_error=UnknownAnswer;
                      return m_error;
                      }
                    }
                  else {
                    if (word1 == "END") break;
                    if (word1 != "OPTION") { m_error = UnknownFormat; return m_error; }
                    if ((m_posChar = inLine.find('\"')) == -1) word2 = "";
                    else {
                      word2 = inLine.mid(m_posChar+1);
                      if ((m_posChar=word2.find('\"')) != -1) word2 = word2.left(m_posChar);
                      }
                    enumString->push_back(word2);
                    varMax++;
                    }
                  } // end while
                } // buffer is not empty
              else { m_error = NoData ; return m_error; }
              } // getUpsData
            else return m_error;
            } // type of var
          else  enumString = 0l;
          // nacteme stringovou promenou
          // ulozime promene
          setRWVars (word,valueType,varMax,enumString);
          m_numberRWVars++;
          break;
          }
        } // end  while (!inputStream.atEnd())
      }
    else { m_error = NoData ; return m_error; }
    }
  else return m_error;

  // *************** INSTANT COMMAND
  if (!m_upsName.isEmpty()) { // pokud upsName neni je vzdy nastaveno na null
    inBuffer="LISTINSTCMD ";
    inBuffer.append(m_upsName.local8Bit());
    inBuffer.append("\n");
    }
  else inBuffer ="LISTINSTCMD\n";

  if (!(m_error=getUpsData (inBuffer,outBuffer))) {
    outBuffer=outBuffer.stripWhiteSpace ();
    if ( !outBuffer.isEmpty() ) {
      // precteme data
      TQTextIStream inputStream(&outBuffer);
      TQString word;
      int count =1 ;
      while (!inputStream.atEnd()) {
        inputStream >> word;
        switch (count) {
          case 1:
          // vyndame prvni polozku
           if (word == "INSTCMDS") count++;
           else {
             if (word == "ERR") {
               inputStream >> word;
               m_error = upsTranslateError(word);
               }
             else m_error=UnknownAnswer;
             return m_error;
             }
          break;
          case 2:
          count++;
          if ((word.length() > 0) && word.startsWith("@")) break;
          default:
          // Zpracujeme polozku v tabulky
          upsIComm.upsCommName=word;
          upsIComm.upsDescription="";
          m_listIComms.push_back(upsIComm);
          m_numberIComms++;
          break;
          }
        }
      }
    else { m_error=NoData; return m_error; }
    }
  else return m_error;
  return 0;
  }



int KNutNet::getUpsVars2 ( void) {
  TQCString  inBuffer;
  TQString  outBuffer;
  TQString  varOutBuffer;
  upsVarDef upsVar;
  upsICommDef upsIComm;
  int key;
  int typeValue;
  int lenString;
  int varMax=0;

  TQValueVector<TQString>* enumString=0;
  inBuffer = "LIST VAR " + m_upsName.local8Bit() + "\n";
  if (!(m_error=getUpsData (inBuffer,outBuffer,"END LIST VAR"))) {
    TQString inLine, upsNameRet, varName, varNameRet, value;
    bool beginList = false;
    TQTextIStream varInputStream(&outBuffer);
    while (!(inLine = varInputStream.readLine()).isNull()) {

      key = parseLine (inLine, upsNameRet, varName, value, typeValue, lenString);
      switch (key) {
        case BEGIN_LIST_VAR:
          if (upsNameRet == m_upsName) beginList = true;
        break;
        case VAR:
         if (beginList ) {
           upsSetType(upsVar, varName, value);

           if (varName == "ups.status") genStatusFlags(value);
           inBuffer = "GET TYPE " + m_upsName.local8Bit() + " " + varName.local8Bit() +"\n";
           if (!(m_error=getUpsData (inBuffer,varOutBuffer))) {
             key = parseLine (varOutBuffer, upsNameRet, varNameRet, value, typeValue, lenString);
             switch (key) {
               case TYPE:
                if (typeValue & RW_FLAG) {
                  upsVar.upsVarMax = 0;
                  upsVar.upsEnumValues=0L;
                  if (typeValue & ENUM_FLAG) {
                    upsVar.upsValueType=false;
                    // nacteme enumValues
                    inBuffer = "LIST ENUM " + m_upsName.local8Bit() + " " + varName.local8Bit() +"\n";
                    if (!(m_error=getUpsData (inBuffer,varOutBuffer,"END LIST ENUM"))) {
                      bool beginEnumList = false;
                      TQTextIStream varInputStream(&varOutBuffer);
                      while (!(inLine = varInputStream.readLine()).isNull()) {
                        key = parseLine (inLine, upsNameRet, varName, value, typeValue, lenString);
                        switch (key) {
                          case BEGIN_LIST_ENUM:
                            beginEnumList = true;
                            varMax=0;
                                 enumString = new TQValueVector<TQString>;
                            enumString->clear();
                            upsVar.upsEnumValues=enumString;
                          break;
                          case ENUM:
                            if (beginList ) {
                                  enumString->push_back(value);
                              varMax++;
                              }
                          break;
                          case ERR:
                            m_error = upsTranslateError(value);
                          return m_error;
                          default:
                            m_error=UnknownAnswer;
                          return m_error;
                          case END_LIST_ENUM:
                          upsVar.upsVarMax=varMax;
                          break;
                          }
                        }
                      }
                    }
                  else {
                    // Vse co nenini ENUM je STRING
                    upsVar.upsValueType=true;
                    upsVar.upsVarMax=lenString;
                    }
                  upsVar.upsVarType=false;
                  m_numberRWVars++;
                  }
                 break;
               case ERR:
                 m_error = upsTranslateError(value);
                 return m_error;
               default:
                 m_error=UnknownAnswer;
                 return m_error;
               }
             }
           else { return m_error; }
           m_listVars.push_back(upsVar);
           m_numberVars++;
           }
          break;
        case END_LIST_VAR:
          break;
        case ERR:
          m_error = upsTranslateError(value);
          return m_error;
        default:
          m_error=UnknownAnswer;
          return m_error;
        } // end switch
      } // end while
    }
  else { return m_error; }
  // INSTANT COMMANDS

  inBuffer = "LIST CMD " + m_upsName.local8Bit() + "\n";
  if (!(m_error=getUpsData (inBuffer,outBuffer,"END LIST CMD"))) {

    TQString inLine, upsNameRet, varName, value;
    int key, typeValue;
    bool beginList = false;
//std::cout << "CMD Buffer " << outBuffer  << std::endl;

    TQTextIStream varInputStream(&outBuffer);
    while (!(inLine = varInputStream.readLine()).isNull()) {
      key = parseLine (inLine, upsNameRet, varName, value, typeValue, lenString);
//std::cout << "CMD Line " << inLine  << std::endl;

      switch (key) {
        case BEGIN_LIST_CMD: {
          if (upsNameRet == m_upsName) beginList = true;
          break;
          }
        case CMD:
         if (beginList ) {
           // Zpracujeme polozku v tabulky
           upsIComm.upsCommName=varName;
           upsIComm.upsDescription="";
           m_listIComms.push_back(upsIComm);
           m_numberIComms++;
           }
         break;
        case END_LIST_CMD:
          break;
        case ERR:
          m_error = upsTranslateError(value);
          return m_error;
        default:
          m_error=UnknownAnswer;
          return m_error;
        } // end switch
      } // end while
    }
  else { return m_error; }
  return 0;
  }



int KNutNet::getUpsValues1 (const bool allVars ) {// allVars = true vse; allVars = false jen activate
    TQString endChar;
    TQCString  inBuffer;
    TQString  outBuffer;
    TQValueVector<upsVarDef>::iterator it;

  // Nacte hodnotu promenych
  // reads value of variables


    emit getVarDesc (m_numberVars, 0);

    int numberVar  = 0;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      numberVar++;
      if ((allVars) || ((*it).upsVarActivate)) {
        //nacteme promenou
        inBuffer = "REQ ";
        inBuffer.append((*it).upsVarName.local8Bit());
        if (!m_upsName.isEmpty()) { // pokud upsName neni je vzdy nastaveno na null
          inBuffer.append("@");
          inBuffer.append(m_upsName.local8Bit());
          }
        inBuffer.append("\n");
//        if (!(error=getUpsData (inBuffer,outBuffer))) {
        m_error=getUpsData (inBuffer,outBuffer);
        // when outBuffer is empty sends and reads date again, but only the only time
        if ((!(m_error)) && (outBuffer.isEmpty())) m_error=getUpsData (inBuffer,outBuffer);
        if (!(m_error)) {

          endChar = "";
          if ((outBuffer.length()>0) && (outBuffer.at(outBuffer.length()-2)==' ')) endChar=' ';

          outBuffer=outBuffer.stripWhiteSpace ();
          outBuffer += endChar;
          emit getVarDesc (m_numberVars, numberVar);

          if ( !outBuffer.isEmpty() ) {
            TQTextIStream inputStream(&outBuffer);
            TQString word1, word2, word3 ;
            inputStream >> word1;
            inputStream >> word2;
            if (inputStream.atEnd()) { // neexistuje treti cast VALUE
              if (word1 == "ERR") {
                // vracena chyba
                m_error=upsTranslateError(word2);
                return m_error;
                }
              else {
//                if ((word2 != "MODEL") && (word2 != "MFR")) {   
                if (endChar != " ") { // if values of variable is empty, string is ended on char space
                  m_error=UnknownFormat;
                  return m_error;
                  }
                }
              }
            inputStream >> word3;
            if (word1 == "ANS") {
              // answer - odpoved
              // odstranime pripadne jmeno upsky
              if ((m_posChar = word2.find('@')) != -1) word2 = word2.left(m_posChar);
              if ( word2 != (*it).upsVarName ) {
                m_error=UnknownAnswer;
                return m_error;// neni to odpoved na spravnou promennou
                }
              // test pro starsi format modulu, vraceli chybu v hodnote promene
              if ((m_error=upsOldTranslateError(word3))) {
                return m_error;
                }
              // zalozime hodnotu do vectoru;
              (*it).upsValue=word3;
              if ((*it).upsVarName == "STATUS") {
                // dogenerujeme dalsi slova pro status
                word3 += inputStream.readLine();
                genStatusFlags(word3);
                }
              }
            else {
              // neznama odpoved - neni ANS ani ERR
              m_error=UnknownAnswer;
              return m_error;
              }
            }
          else {
            m_error=NoData;
            return m_error;
            }
          }
        else {
          return m_error;
          }
        }
      }
    return 0;
  }



int KNutNet::getUpsValues2 (const bool allVars ) {// allVars = true vse; allVars = false jen activate
  TQString varName;
  TQString upsNameRet;
  TQString value;
  int typeValue;
  int lenString;

  // reads value of variables
  TQCString  inBuffer;
  TQString  outBuffer;
  TQValueVector<upsVarDef>::iterator it;

  emit getVarDesc (m_numberVars, 0);
   int numberVar  = 0;
  for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
    numberVar++;
    if ((allVars) || ((*it).upsVarActivate)) {
      //reads variable
      inBuffer = "GET VAR "+m_upsName.local8Bit()+" "+(*it).upsVarName.local8Bit()+"\n";
//      if (!(error=getUpsData (inBuffer,outBuffer))) {
      m_error=getUpsData (inBuffer,outBuffer);
      // when outBuffer is empty sends and reads date again, but only the only time
      if ((!(m_error))  &&  (outBuffer.isEmpty())) m_error=getUpsData (inBuffer,outBuffer);
      if (!(m_error)) {
        outBuffer=outBuffer.stripWhiteSpace ();
        emit getVarDesc (m_numberVars, numberVar);
        if ( !outBuffer.isEmpty() ) {
          int key = parseLine(outBuffer, upsNameRet, varName, value, typeValue, lenString);
          switch (key) {
            case VAR:
              if ( varName != (*it).upsVarName ) {
                m_error=UnknownAnswer;
                return m_error;// it isn't answer for right variable - neni to odpoved na spravnou promennou
                }
              (*it).upsValue=value;
              if ((((*it).upsVarName == "STATUS") && (m_nutVariables == 1)) || (((*it).upsVarName == "ups.status") && (m_nutVariables == 2))) {
                // dogenerujeme dalsi slova pro status
                genStatusFlags(value);
                }
              break;  
            case ERR:
              m_error=upsTranslateError(value);
              return m_error;
            default:
              m_error=UnknownAnswer;
              return m_error;
            }
          }
        else {
          m_error= NoData;
          return m_error;
          }
        }
      else {
        return m_error;
        }
      }
    }
  return 0;
  }


int KNutNet::sendComm (const TQString command, const TQString arg1, const TQString arg2, const bool useUpsName) {
  int localError;
// nenastavi promenou error ale nenuluje ji
  TQCString inBuffer;
  TQString outBuffer;

  switch (m_nutProtocol) {
    case 1:
      inBuffer=command.local8Bit() + " " + arg1.local8Bit();
      if (useUpsName && (!m_upsName.isEmpty())) { // pokud upsName neni je vzdy prazdne
        inBuffer += "@"+m_upsName.local8Bit();
      }
      if (!arg2.isEmpty()) {
        inBuffer += " " + arg2.local8Bit();
      }
      break;
    case 2:
      inBuffer = command.local8Bit() + " ";
      if (useUpsName) {
        inBuffer += m_upsName.local8Bit() + " ";
      }
      inBuffer.append(arg1.local8Bit());
      if (!arg2.isEmpty()) {
        inBuffer += " \"" + arg2.local8Bit() +"\"";
      }
      break;
    }
  inBuffer.append("\n");

  if (!(localError=getUpsData (inBuffer,outBuffer))) {
    outBuffer=outBuffer.stripWhiteSpace();
    TQTextIStream inputStream(&outBuffer);
    TQString word1, word2;
    inputStream >> word1;
    inputStream >> word2;
    if (word1.isEmpty()) return UnknownAnswer; // zadna odpoved
    if (word1 != "OK") {
      // neni rovno OK
      if (word1 == "ERR") return upsTranslateError (word2);
      else return UnknownAnswer;
      }
    else return 0;
    }
  else return localError;
  }


int KNutNet::activate ( const TQString name, const bool setActivate  ) {
  m_error =0;
  if (m_state == Connected) {
    TQValueVector<upsVarDef>::iterator it;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      if ((*it).upsVarName == name) {
        (*it).upsVarActivate = setActivate;
        return 0;
        }
      }
    m_error = VarNotFind;
    return m_error;
    }
  else return NotConnection;
  }

int KNutNet::activateAll ( const bool setActivate  ) {
  m_error =0;
  if (m_state == Connected) {
    TQValueVector<upsVarDef>::iterator it;
    for (it = m_listVars.begin(); it != m_listVars.end(); it++) {
      (*it).upsVarActivate = setActivate;
      }
    return 0;
    }
  else return NotConnection;
  }


int KNutNet::upsTranslateError (const TQString string) {
  if (string == "VAR-NOT-SUPPORTED") return VarNotSupported;
  if (string == "VAR-UNKNOWN") return VarUnknown;

  if (string == "ACCESS-DENIED") return AccessDenied;
  if (string == "PASSWORD-REQUIRED") return PasswordRequired;
  if (string == "PASSWORD-INCORRECT") return PasswordIncorrect;
  if (string == "UNKNOWN-UPS") return UnknownUps;
  if (string == "ALREADY-LOGGED_IN") return AlreadyLoggedIn;
  if (string == "ALREADY-SET-PASSWORD") return AlreadySetPassword;
  if (string == "ALREADY-SET-USERNAME") return AlreadySetUsername;
  if (string == "UNKNOWN-COMMAND") return UnknownCommand;

  if (string == "UNKNOWN-INSTCMD") return UnknownInstCmd;
  if (string == "CMD-NOT-SUPPORTED") return CmdNotSupported;

  if (string == "INVALID-VALUE") return InvalidValue;

  if (string == "NO-RESPONSE") return NoResponse;
  if (string == "UNKNOWN-REPLY") return UnknownReply;
  if (string == "NOT-IMPLEMENTED") return NotImplemented;
  if (string == "COMMAND-FAILED") return CommandFailed;

  if (string == "MISSING-ARGUMENT") return MissingArgument;
  if (string == "DATA-STALE") return DataStale;
  if (string == "UNKNOWN-TYPE") return UnknownType;

  if (string == "DRIVER-NOT-CONNECTED") return DriverNotConnected;

  if (string == "") return UnknownFormat;

  return UnknownErr;
  }

int KNutNet::upsOldTranslateError (const TQString string) {
  if (string == "NOT-SUPPORTED") return VarNotSupported;
  if (string == "UNKNOWN") return VarUnknown;
  if (string == "DATA-STALE") return DataStale;
  return 0; // nebylo nalezeno
  }

//--------------------Socket----------------


void KNutNet::slotConnectionError(int error) {
//std::cout << "--KNutNet::slotConnectionError"  << std::endl;
//tqDebug ("--KNutNet::slotConnectionError");

  m_state = ConnectError;
  m_unConnectTimer->stop();
  if (error == TQSocket::ErrHostNotFound) {
    error = NoSuchHost;
    emit connectionError(error);
    return;
    }
                        //connection was refused                                  //  no connection
  if ((error == TQSocket::ErrConnectionRefused) && (m_commandSocket->state()==TQSocket::Idle)) {
    if (m_firstConnect) {
      if (m_numberConnection < m_countRepeat) {
        m_numberConnection++;
//    tqDebug ("--KNutNet:: connect error - try connect on next time");
        m_unConnectTimer->start( m_delay, TRUE );
        }
      else  {
        // i don't connect server
        error=CantConnect;
//        tqDebug("--KNutNet::emit - connection error ");
        emit connectionError(error);
        return;
        }
      } // end of if (firstConnection)
    else {
      // connecting is down, try repeated connection

//    tqDebug ("--KNutNet::no first connect connection error ");
      m_unConnectTimer->start( m_delay, TRUE );
      }
    return;
    }
  if (error == TQSocket::ErrConnectionRefused) {
    error = ConnectionRefused;
//    std::cout << "--KNutNet::connection error ErrConnectionRefused " << TQSocket::Idle << " - " << error << std::endl;
    emit connectionError(error);
    return;
    }
  if (error ==   TQSocket::ErrSocketRead) {
    error = SocketReadErr;
//    std::cout << "--KNutNet::connection error TQSocket::ErrSocketRead " << error << std::endl;
    emit connectionError(error);
    return;
    }
  }


void KNutNet::slotConnected(void) {
  int n;

    if ((n = version (m_countRepeat, m_delay)) == 0) { // 0 OK, 0> error
      if ((m_nutProtocol == 0) || (m_nutVariables == 0)) { // answer from upsd (VER) is unknown
        m_error=NutProtocolVarErr;
        m_state = Closing;
        m_commandSocket->close();
        while (m_commandSocket->state() == TQSocket::Closing) {
          sleep (100);
          }
        m_state = ConnectError;

        return;
        }
      if ((m_nutProtocol == 2) && m_upsName.isEmpty()) {
      // if upsName is empty reads first ups name from upsd server 
        if ((m_error =KNutNet::getFirstUpsName (m_upsName))) { // reading first upsName
          // upsd server doesn't support any ups
          m_state = Closing;
          m_commandSocket->close();
          while (m_commandSocket->state() == TQSocket::Closing) {
            sleep (100);
            }
          m_state = ConnectError;

          }
        }
        m_state=Connected;
      }
    else {
        m_commandSocket->close();
      }
    emit firstConnection();
//  std::cout << "KNutNet::emit - firstConnection" << std::endl;
  }

void KNutNet::slotHostFound(void) {

//  std::cout << "--KNutNet::slotHostFound"  << std::endl;
  m_state = Connecting;
  emit hostFound();
  }


void KNutNet::slotConnectionClosed(void) {

//  std::cout << "--KNutNet::slotConnectionClosed" << std::endl; 
  m_unConnectTimer->stop();
  deleteVars();
  m_state = Idle;
  emit connectionClosed();
  }



void KNutNet::slotTimerReconnect(void) {
//  std::cout << "--KNutNet::slotTimerReconnect"  << std::endl;

 m_unConnectTimer->stop();
  if (m_commandSocket->state()==TQSocket::Idle) {
  //std::cout << "--KNutNet::slotTimerReconnect TQSOcket::Idle" << std::endl;
     emit tryRepeatFirstConnection(m_numberConnection);
   //  std::cout << "KNutNet::emit-tryRepeatFirstConnection" << std::endl;
    m_state=Connecting;
    if ( m_commandSocket->state() != TQSocket::Connecting )
      m_commandSocket->connectToHost(m_upsAddress,m_port);
    }
  }


#include "knutnet.moc"