/* Version	 :  1.73
   Modul         : S7DEMO.C
   Projekt       : Demoprogramm f�r PC-S7-LINK-Anwendung
   Programmierer : Dipl.-Ing. A. Tr�ger
*/


#include <stdio.h>
#include <stdlib.h>

#ifndef __linux__
  #include <WINDOWS.H>
  #include <conio.h>
#endif
#include  <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#ifdef __linux__
#include <unistd.h>
#include <termios.h>
#include <sgtty.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#define  TRUE 1
#define  FALSE 0
#endif


#include "ips7lnk.h"


int SRes;
WORD   WordBuffer[2048];
BYTE   ByteBuffer[2048];
DWORD  DWordBuffer[2048];
double DoubleBuffer[2048];
INT64  Int64Buffer[2048];
WORD EigeneMPIAdr;
char IPAdr[255];
char *DefaultIPAdr ="192.168.0.80";

#ifndef __linux__
int 
GetKey (void)
{ 
  char C;
  fflush (stdin);
  fread (&C, 1, 1, stdin);
  return (C);
  //return (getchar ());
}
#else
int
GetKey (void)
{
  char C;
  struct termios terminal, altterminal;
  int ConsolenFd = -1;
  
  tcgetattr (fileno (stdin), &altterminal);
  terminal = altterminal;
  terminal.c_lflag &= ~(ICANON | ECHO );
  terminal.c_iflag &= ~(ICRNL);
  ConsolenFd = fileno (stdin);
  tcsetattr (ConsolenFd, TCSAFLUSH, &terminal);

  do
  {
    SRes = fread (&C, 1, 1, stdin);
  }
  while (C == '\n');

  tcsetattr (ConsolenFd, TCSAFLUSH, &altterminal);
  return (C);
}
#endif
/* ------------------------------------------------------------------ */

/* ------------------------------------------------------------------ */

void
MsgGetKey (void)
{
  printf ("Weiter mit beliebiger Taste. / press any key..\r");
  GetKey ();
  printf ("                                                               \r");
}


void      
DoErr (long Ref, long Res)
{     
  char *Err = "";
  int SocketErr = 0;
 
  switch (Res)
  {
    case -1:
      Err = "Zeitueberlauf / Timeout";
      break;
    
    case 2:                 
      Err = "Baustein oder Datenbereich exisitiert nicht / DB or data area doesn't exist";
      break;
    
    case -5:
      Err = "allgemeiner Fehler / general error";
      break;

    case -7:
      Err = "Socket-Fehler / Socket Error";
      SocketErr = IPS7GetSockErr (Ref);
      break;

    case -6:
      Err = "Rack oder Slot Nummer falsch oder maximale Anzahl projektierter Verbindungen in der S7-CPU erreicht.\n"
            "Invalid rack or slot no. or max. count of available connections at S7-CPU reached.\n";
      break;
      
    case -10:
      Err = "Typ-Kennung falsch / invalid kind of type";
      break; 
    
    case -99: 
      Err = "Referenznummer ist ungueltig / invalid refernce number";
      break;
 
    case -88:
      Err = "Multiread-Auftrag wurde noch nicht bearbeitet / The MultiRead job is not yet processed";
      break;
      
    case 0x1234:
      Err = "Demozeit ist abgelaufen / demo time has expired";
      break;
    
    default:   
      Err = "Fehlernummer siehe Handbuch ips7lnk.pdf / For error code see the manual ips7lnk.pdf";
  }                               
  printf ("\n*************************\n"
          "\aFehler: / Error: %ld\n %s\n"
          "%s\n" , Res, Err, SocketErr ? strerror (SocketErr) :"");
  MsgGetKey ();
} 
/* ------------------------------------------------------------------ */





void 
WrDB (long Ref)
{
  
  unsigned DBNr,
           i,      
           Len, Wert;
  long Res;

         
  printf ("Schreibe DW ab DW 0 / write DW starting at DW 0\n");
  printf ("\nSchreibe DB-Nummer: / write DB-no.:");
  SRes = scanf ("%u", &DBNr);

  printf ("\nAnzahl der Worte: / count of words");
  SRes = scanf ("%u",&Len);                    
  
  printf ("\nSchreibwert: / value to write:");
  SRes = scanf ("%u",&Wert);                    
  
  for (i = 0; i < Len; i++)         
    WordBuffer[i] = Wert;
                           
  Res = IPS7WrW (Ref, 'D', DBNr, 0, Len, WordBuffer);
  if (Res == 0) // alles OK
  {       
    for (i=0; i < Len;i++)
    {
      printf ("DW %03u = 0x%04x               \n",i*2,WordBuffer[i]);
      MsgGetKey ();
    }
  }
  else   
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/


void 
RdDB (long Ref)
{
  
  unsigned DBNr, 
           i,      
          Len, AbWort;
  
  long Res;      
           
  
  printf ("Lese DB  / read DB\n");
  printf ("Lese DB-Nummer: / DB no.:");
  SRes = scanf ("%u",&DBNr);

  printf ("\nStart ab Wort: / start at word");
  SRes = scanf ("%u",&AbWort);                    
  
  printf ("\nAnzahl der Worte: / count of words:");
  SRes = scanf ("%u",&Len);                    
  
  
  Res = IPS7RdW (Ref, 'D', DBNr, AbWort, Len, WordBuffer);
  if (Res == 0)
  {
    for (i=0; i < Len;i++)
    {
      printf ("DW %03u = 0x%04x               \n",AbWort + i*2,WordBuffer[i]);
      GetKey ();
    }           
  }
  else
  {
    DoErr (Ref, Res);
  }
}

void 
GetPlcTime (long Ref)
{
  long Year, Month, Day, Hour,  Minute, Second, Millisecond;
  long Res;
  printf ("Lese S7-CPU-Zeit / read S7-PLC-Time\n");

  Res = IPS7GetPLCTime(Ref, &Year, &Month, &Day, &Hour, &Minute, &Second, &Millisecond);
  if (Res == 0)
  {
     printf ("SPS-Zeit/PLC-Time: %ld.%ld.%04ld %02ld:%02ld:%02ld + %ld(ms)\n", Day, Month, Year, Hour, Minute, Second, Millisecond);
     GetKey ();
   }
  else
  {
    DoErr (Ref, Res);
  }
}


/*------------------------------------------------------------*/
void
RdEB (long Ref)
{
  
  unsigned  EBNr,
            i,      
            Len;
  long Res;
  
  printf ("Lese Eingangsbyte / read input byte\n ");
  printf ("StartNr: / start at:");
  SRes = scanf ("%u",&EBNr);

  printf ("Anzahl der Bytes / count of bytes\n");
  SRes = scanf ("%u",&Len);                    

  Res =  IPS7RdB (Ref, 'E', 0, EBNr, Len, ByteBuffer);
                                                       
  if (Res == 0)
  {
    
    for (i=0; i < Len;i++)
    {
      printf ("EB %03u = 0x%04x \n",i, (WORD) ByteBuffer[i]);
      GetKey ();
    }
  }   
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/
    
void 
RdMB (long Ref)
{
  unsigned MBNr,
          i,      
          Len;
  long Res;
  
  printf ("Lese MerkerByte / read flag bytes\n ");
  printf ("StartNr: ");

  SRes = scanf ("%u",&MBNr);

  printf ("Anzahl der Bytes / count of bytes\n");  
  SRes = scanf ("%u",&Len);                    
  
  Res = IPS7RdB (Ref, 'M', 0,  MBNr, Len, ByteBuffer);
  if (Res == 0)
  {
    for (i=0; i < Len;i++)
    {
      printf ("MB %03u = 0x%04x \n",i, (WORD) ByteBuffer[i]);
      GetKey ();
    }
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void 
RdTimer (long Ref)
{
  
  unsigned TimerNr,
           i,      
           Cnt;
  long  Res;
  
  printf ("Lese Timer / read timer\n ");
  printf ("StartNr: / start at:");
  SRes = scanf ("%u",&TimerNr);

  printf ("Anzahl der Timer / count of timers\n");  
  SRes = scanf ("%u",&Cnt);                    
   
  
  Res = IPS7RdDW (Ref, 'T', 0,  TimerNr, Cnt, DWordBuffer);
  
  if (Res == 0)
  {
    for (i=0; i < Cnt;i++)
    {
      printf ("T %3u = %uld \n",i+TimerNr, DWordBuffer[i]);
      GetKey ();
    }
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void 
WrTimer (long Ref)
{
  
  unsigned i,TimerNr, Len;
  unsigned long  Wert;
  long Res;
         
  printf ("Schreibe Timer ab / write timer\n");
  
  printf ("StartNr: / start at:");
  SRes = scanf ("%u",&TimerNr);

  printf ("\nAnzahl der Timer: / count of timers");
  SRes = scanf ("%u",&Len);                    
  
  printf ("\nSchreibwert: / value to write");
  SRes = scanf ("%lu",&Wert);                    
  
  for (i = 0; i < Len; i++)         
    DWordBuffer[i] = (Wert += i);
                           
  Res = IPS7WrDW (Ref, 'T', 0, TimerNr, Len, DWordBuffer);
  if (Res == 0) // alles OK
  {       
    for (i=0; i < Len;i++)
    {
      printf ("T %03u = %ld               \n",i + TimerNr,(unsigned long)DWordBuffer[i]);
      MsgGetKey ();
    }
  }
  else   
  {  
    DoErr (Ref, Res);
  }
}

void 
RdCounter (long Ref)
{
  
  unsigned  Nr,
            i,      
            Cnt;
  long  Res;
  
  printf ("Lese Zaehler\n / read counter");
  printf ("StartNr: ");
  SRes = scanf ("%u",&Nr);

  printf ("Anzahl der Zaehler / count fo counters\n");  
  SRes = scanf ("%u",&Cnt);                    
   
  
  Res = IPS7RdW (Ref, 'Z', 0,  Nr, Cnt, WordBuffer);
  
  if (Res == 0)
  {
    for (i=0; i < Cnt;i++)
    {
      printf ("Z %3u = %d \n",i+Nr, WordBuffer[i]);
      MsgGetKey ();
    }
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void 
WrCounter (long Ref)
{
  unsigned i,Nr, Len;
  unsigned long  Wert;
  long Res;
         
  printf ("Schreibe Zaehler ab / write counter\n");
  
  printf ("StartNr:  / start at:");


  SRes = scanf ("%u",&Nr);

  printf ("\nAnzahl der Zaehler: / count of counters ");
  SRes = scanf ("%u",&Len);                    
  
  printf ("\nSchreibwert: / value to write");
  SRes = scanf ("%lu",&Wert);                    
  
  for (i = 0; i < Len; i++)         
    WordBuffer[i] = (WORD) (Wert += 10);
                           
  Res = IPS7WrW (Ref, 'Z', 0, Nr, Len, WordBuffer);
  if (Res == 0) // alles OK
  {       
    for (i=0; i < Len;i++)
    {
      printf ("Z %03u = %d\n",i + Nr,WordBuffer[i]);
      MsgGetKey ();
    }
  }
  else   
  {  
    DoErr (Ref, Res);
  }
}


void 
RdMBit (long Ref)
{
  
  unsigned  MBNr, BitNr;      
  long  Res;
  
  printf ("Lese Merker Bit / read flag bit\n ");
  printf ("ByteNr: / no. of bit:");
  SRes = scanf ("%u",&MBNr);
  for (;;)
  {
    printf ("Bit-Nr: / no. of bit:");
    SRes = scanf ("%u",&BitNr);
    if (BitNr > 7 || BitNr < 0)
      printf ("BitNr muss zwischen 0 und 7 liegen. / Enter a value in the range for 0 to 7.\n");
    else
      break;
  }
     
  Res = IPS7RdBit (Ref, 'M', 0,  MBNr, BitNr, ByteBuffer);
  
  if (Res == 0)
  {
    printf ("MB %d.%d = %d \n", MBNr, BitNr, (WORD) ByteBuffer[0]);
    MsgGetKey ();
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void 
SetMBit (long Ref, BOOL Mode)
{
  
  unsigned  MBNr, BitNr;      
  long  Res;
  
  if (Mode)
  {
    printf ("Setze Merker Bit / set flag bit\n ");
  }
  else
    printf ("Ruecksetze Merker Bit / reset flag bit\n ");

  printf ("ByteNr:  /  no. of byte:");
  SRes = scanf ("%u",&MBNr);
  for (;;)
  {
    printf ("BitNr:  /  no. of bit:");
    SRes = scanf ("%u",&BitNr);
    if (BitNr > 7 || BitNr < 0)
      printf ("BitNr muss zwischen 0 und 7 liegen. / Enter a value in the range for 0 to 7.\n");
    else
      break;
  }
     
  if (Mode)
    //Res = IPS7SetBit (Ref, 'M', 0, MBNr, BitNr);
    Res = IPS7SetBit (Ref, 'D', 10, MBNr, BitNr);
  else
    Res = IPS7ResetBit (Ref, 'M', 0, MBNr, BitNr);
  
  if (Res == 0)
  {
    if (Mode)
      printf ("Bit gesetzt. / bit is set to '1'");
    else
      printf ("Bit zurueckgesetzt. / bit is set to '0'");
    MsgGetKey ();
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/
void 
WrAB (long Ref)
{
  
  unsigned Nr,
        i,      
        Len,
        Wert;
  long Res;
  
  printf ("\nSchreibe Ausgangsbyte: / write output byte \n");
  
  printf ("StartNr: / start at:");
  SRes = scanf ("%u",&Nr);
               
  printf ("Schreibwert: / value to write");
  SRes = scanf ("%u",&Wert);                    
  
  printf ("Anzahl: / count of bytes:");
  SRes = scanf ("%u",&Len);                    
  
  for (i = 0; i < Len; i++)
    ByteBuffer[i] = (BYTE) Wert;        
  
  Res = IPS7WrB (Ref, 'A', 0, Nr, Len, ByteBuffer);
  if (Res == 0)
  {
    printf ("ab/starting at AB %d , %d Bytes geschrieben / bytes written\n", Nr, Len);
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void 
WrMB (long Ref)
{
  
  unsigned  Nr,
        i,      
        Len,
        Wert;
  long Res;
  
  printf ("\nSchreibe Merkerbytes: / write flag bytes\n");
  
  printf ("StartNr: / start at:");
  SRes = scanf ("%u",&Nr);
               
  printf ("Schreibwert: / value to write:");
  SRes = scanf ("%u",&Wert);                    
  
  printf ("Anzahl: / count of bytes:");
  SRes = scanf ("%u",&Len);                    
  
  for (i = 0; i < Len; i++)
    ByteBuffer[i] = (BYTE) Wert;        
  
  Res = IPS7WrB (Ref, 'M', 0, Nr, Len, ByteBuffer);
  if (Res == 0)
  {
    printf ("ab/starting at  MB %d , %d Bytes geschrieben/ written\n", Nr, Len);
  }
  else
  {
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void
RdFloat (long Ref)
{
  
  unsigned DBNr,
       Ab,
       i,      
       Len;
  long Res;
         
  printf ("Lese Fliesskomma von DB/ read floating point values from DB\n");
  printf ("\nDB Nummer: / no. of DB:");
  SRes = scanf ("%u",&DBNr);

  printf ("\nStartbyte: / start at byte:");
  SRes = scanf ("%u",&Ab);                    
  
  printf ("\nAnzahl der Werte: / count of values");
  SRes = scanf ("%u",&Len);                    
                        
  
  Res = IPS7RdReal (Ref, 'D', DBNr, Ab, Len, DoubleBuffer);
  if (Res == 0)
  {
    for (i=0; i < Len;i++)
    {
      printf ("Float an/at Byte %d = %f\n",i*4 + Ab,DoubleBuffer[i]);
      MsgGetKey ();
    }
  }    
  if (Res != 0)  
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/
void
WrFloat (long Ref)
{
  
  unsigned DBNr,
       Ab,
       i,      
       Len;
  double Wert;
  long Res;
         
  printf ("Schreibe Flie�komma in DB / write floating point values tio DB\n");
  printf ("\nDB  Nummer: / number of DB:");
  SRes = scanf ("%u",&DBNr);

  printf ("\nStartbyte: / start at byte:");
  SRes = scanf ("%u",&Ab);                    
  
  printf ("\nAnzahl der Werte: / count of values");
  SRes = scanf ("%u",&Len);                    

  printf ("\nSchreibwert: / value to write:");
  SRes = scanf ("%lf",&Wert);                    
  
  for (i = 0; i < Len; i++)         
    DoubleBuffer[i] = Wert;
                           
  Res = IPS7WrReal (Ref, 'D', DBNr, Ab, Len, DoubleBuffer);
  if (Res == 0) // alles OK
  {       
    Res = IPS7RdReal (Ref, 'D', DBNr, Ab, Len, DoubleBuffer);
    if (Res == 0)
    {
      for (i=0; i < Len;i++)
      {
        printf ("Float an/at Byte %d = %lf\n",i*4 + Ab,DoubleBuffer[i]);
        MsgGetKey ();
      }
    }    
  }
  if (Res != 0)  
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void ShowDWord (DWORD *pW, int Start, int Cnt)
{
  int i;
  
  for (i=0; i < Cnt; i++)
  {
    printf ("DWord an Byte %d = %08lx (hex) = %ld (dec)\n", 
	     i * 4 + Start, (unsigned long) pW[i], (unsigned long) pW[i]);
    MsgGetKey ();
  }
}

void
WrDWord (long Ref)
{
  
  unsigned DBNr,
       Ab,
       i,      
       Len;
  unsigned long Wert;
  long Res;
         
  printf ("Schreibe Doppelwort in DB / write doublewords (32-Bit) to DB\n");
  printf ("\nDB Nummer: / no. of DB:");
  SRes = scanf ("%u",&DBNr);

  printf ("\nStartbyte: / start at byte:");
  SRes = scanf ("%u",&Ab);                    
  
  printf ("\nAnzahl der Werte: / count of values");
  SRes = scanf ("%u",&Len);                    

  printf ("\nSchreibwert: / value to write:");

  SRes = scanf ("%ld",&Wert);                    
  
  for (i = 0; i < Len; i++)         
    DWordBuffer[i] = Wert;
                           
  Res = IPS7WrDW (Ref, 'D', DBNr, Ab, Len, DWordBuffer);
  if (Res == 0) // alles OK
  {       
    Res = IPS7RdDW (Ref, 'D', DBNr, Ab, Len, DWordBuffer);
    if (Res == 0)
    {
      ShowDWord (DWordBuffer, Ab, Len);
    }    
  }
  if (Res != 0)  
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void
RdDWord (long Ref)
{
  
  unsigned DBNr,
       Ab,
       i,      
       Len;
  long Res;
         
  printf ("Lese Doppelwort von DB / read double words (32-Bit) from DB\n");
  printf ("\nDB Nummer: / no. of DB");
  SRes = scanf ("%u",&DBNr);


  printf ("\nStartbyte: / start at byte:");
  SRes = scanf ("%u",&Ab);                    
  
  printf ("\nAnzahl der Werte: / count of values:");
  SRes = scanf ("%u",&Len);                    
  
  Res = IPS7RdDW (Ref, 'D', DBNr, Ab, Len, DWordBuffer);
  if (Res == 0)
  {
    for (i=0; i < Len; i++)
    {
      printf ("DWord an/at Byte %d = %08lx (hex) = %ld (dec)\n", 
	       i*4 + Ab, (unsigned long)DWordBuffer[i], (unsigned long) DWordBuffer[i]);
      MsgGetKey ();
    }
  }    
  if (Res != 0)  
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/

void
RdLInt (long Ref)
{
  unsigned DBNr,
    Ab,
    i,      
    Len;
  long Res;

  printf ("Lese LInt von DB / read LInt (64-Bit) from DB\n");
  printf ("\nDB Nummer: / no. of DB");
  SRes = scanf ("%u",&DBNr);


  printf ("\nStartbyte: / start at byte:");
  SRes = scanf ("%u",&Ab);                    

  printf ("\nAnzahl der Werte: / count of values:");
  SRes = scanf ("%u",&Len);                    

  Res = IPS7RdLInt (Ref, 'D', DBNr, Ab, Len, Int64Buffer);
  if (Res == 0)
  {
    for (i=0; i < Len; i++)
    {
      printf ("LInt an/at Byte %d = %08llx (hex) = %lld (dec)\n", 
        i*4 + Ab, Int64Buffer[i], Int64Buffer[i]);
      MsgGetKey ();
    }
  }    
  if (Res != 0)  
  {  
    DoErr (Ref, Res);
  }
}
/*------------------------------------------------------------*/



  // AccessMode 1.23
char *AccessModes =  
  "0    = OP-Verbindung ohne SubNet    / OP-connection without SubNet\n"
  "1    = PG-Verbindung ohne SubNet    / PG-connection with SubNet\n"
  "2    = S7200-Verbindung ohne SubNet / S7200-connection without SubNet\n"
  "3    = Logo\n"
  "10   = OP-Verbindung mit Subnet     / OP-connection with SubNet\n"
  "11   = PG-Verbindung mit SubNet     / PG-Connection with SubNet\n"
  "1215 = S7 1200/1500\n";


int
GetAccessMode (void)
{
  int Mode = 0;
  
  for (;;)
  {
    printf ("%s",AccessModes);
    SRes = scanf ("%u",&Mode);
    
    if (Mode == 0   ||
        Mode == 1   ||
        Mode == 2   ||
        Mode == 3   ||
        Mode == 10  ||
        Mode == 11  ||
        Mode == 1215)
    {
      return (Mode);
    }
    else
    {
      printf ("Mode %d ist nicht m�glich. Bitte neu eingeben...\n"
              "Invalid mode. Please enter again..\n",  Mode);
    }
    MsgGetKey ();
  }
}

int
GetInt (char *Txt, int Ist , int Min, int Max)
{
  for (;;)
  {
    printf ("%s:",Txt);
    SRes = scanf ("%i",&Ist);

    if (Ist >= Min && Ist <= Max)
    {
      return (Ist);
    }
    else
    {
      printf ("Wert:%d for %s ist nicht m�glich.\nBitte neu eingeben...\n", Ist, Txt);
      printf ("Value:%d for %s not valid.\nPlease enter again...\n", Ist, Txt);
      
    }
    MsgGetKey ();
  }
}


unsigned long
GetULongHex (char *Txt, unsigned long Ist)
{
  printf ("%s:(im Hex)",Txt);

  SRes = scanf ("%08lx", &Ist);

  printf ("Wert/value:%08lx \n", Ist);
  return (Ist);
}

                        
void InitRq (IPS7_RQ_MULTI *pRq, long DataArea, long DataType, long PcDataArea, long DBNr,  long Start, long StartBit, long Cnt, void *pData)
{
  pRq->DataArea = DataArea;
  pRq->DataType = DataType;
  pRq->DBNr = DBNr;
  pRq->Cnt = Cnt;
  pRq->Start = Start;
  pRq->StartBit = StartBit;
  pRq->PcDataType = PcDataArea;
  pRq->Data = pData;
}

char *MakeAdrName (int DataArea, int DBNr, int PLCDataType)
{
  static char m_strAdrName[64];
  const char *TypeChar = "";
  
  switch (PLCDataType)
  {
    case IPS7_BIT: 
      if (DataArea == 'D')
        TypeChar = "X";
      break;

    case IPS7_BYTE:
      TypeChar = "B";      
      break;
    
    case IPS7_WORD:
    case IPS7_INT:
      TypeChar = "W";
      break;
    
    case IPS7_DWORD:
    case IPS7_DINT:
    case IPS7_REAL:
      TypeChar = "D";
      break;

  }
  if (DataArea == 'D')
  {
    sprintf (m_strAdrName, "DB%03d.DB%s", DBNr, TypeChar);
  }
  else if (DataArea == 'T')
    strcpy (m_strAdrName,"T ");
  else if (DataArea == 'Z')
    strcpy (m_strAdrName, "Z ");
  else
  {
    sprintf (m_strAdrName, "%c%s", (BYTE) DataArea, TypeChar);
  }
  return (m_strAdrName);
}



void ShowMultiRdItems (int Ref, int Idx, int DataArea, int DBNr, int StartAt, int StartBit, int Cnt, int PCDataType, int PLCDataType,  void *pData, BOOL bShowHex, int Result)
{
  int i;
  int Step;
  BOOL bBit = FALSE;
  int BitNr = StartBit;
  int S7ItemNr;
  char *AdrName;
  
  BYTE *pByte = (BYTE *)pData;
  double *pDouble = (double *)pData;
  
  float *pFloat = (float *)pData;
  short int  *pInt16 = (short int *)pData;
  unsigned short int *pUInt16 = (unsigned short int *)pData;
  int32_t  *pInt32 = (int32_t  *)pData;
  DWORD *pUInt32= (DWORD *)pData;
  int UnitSize = 1;

  if (Result != 0)
  {
    printf ("Rq[%d].Result = %d\n\r", Idx, Result);
    DoErr (Ref, Result);
    return;
  }
  
  switch (PLCDataType)
  {
    case IPS7_BIT:
      bBit = TRUE;
      Step = 1;
      bShowHex = FALSE;
      break;

    default:

    case IPS7_TIMER:
    case IPS7_COUNTER:
      bShowHex = FALSE;
    case IPS7_BYTE:
      Step = 1;
      break;
   

    case IPS7_WORD:
    case IPS7_INT:
      Step = 2;
      break;
    
    case IPS7_DWORD:
    case IPS7_DINT:
    case IPS7_REAL:
      Step = 4;
      break;
  }
  if (DataArea == 'Z' || DataArea == 'T')
  {
    Step = 1;
    bShowHex = FALSE;
  }
  
  AdrName = MakeAdrName (DataArea, DBNr, PLCDataType);

  S7ItemNr = StartAt;
  for (i = 0; i < Cnt; i++)
  {
    char S[256];
    char StrValue[64];
    char StrHex[64];
    char StrAscii[64];
        
    StrHex[0] = '\0';
    StrAscii[0] = '\0';        
    if (bBit)
    {
      sprintf (S, "%s%03d.%d", AdrName,  S7ItemNr , BitNr);
      if (++BitNr > 7)
      {
        BitNr = 0;
        ++S7ItemNr;
      }
    }
    else
    {
      sprintf (S, "%s%03d", AdrName,  S7ItemNr);
      S7ItemNr += Step;
    }
    
    switch (PCDataType)
    {
      default:
      case PC_BYTE:
        sprintf (StrValue, "%d", (unsigned) pByte[i]);
        UnitSize = sizeof (BYTE);
        break;

      case PC_WORD16:
        sprintf (StrValue, "%5u", pUInt16[i]);
        UnitSize = sizeof (WORD);
        break;

      case PC_INT16:
        sprintf (StrValue, "%6d", pInt16[i]);
        UnitSize = sizeof (short int);
        break;

      case PC_WORD32:
        sprintf (StrValue, "%8lu", (unsigned long) pUInt32[i]);
        UnitSize = sizeof (DWORD);
        break;
        
      case PC_INT32:
        sprintf (StrValue, "%8ld", (long int) pInt32[i]);
        UnitSize = sizeof (int32_t );
        break;

      case PC_FLOAT:
        sprintf (StrValue, "%.2f", (double) pFloat[i]);
        bShowHex = FALSE;
        UnitSize = sizeof (float);
        break;

      case PC_DOUBLE: 
        sprintf (StrValue, "%.2f", pDouble[i]);
        UnitSize = sizeof (double);
        bShowHex = FALSE;
        break;
    }
    if (bShowHex)
    {
      int UnitSize = 1;
      int j;
      BYTE HexData[4];
      switch (PLCDataType)
      {
        default:
        case IPS7_BIT:
        case IPS7_BYTE:
          UnitSize = 1;
          HexData[0] = pByte[i * UnitSize];
          break;

        case IPS7_TIMER:
        case IPS7_COUNTER:
          bShowHex = FALSE;
        case IPS7_WORD:
        case IPS7_INT:
          UnitSize = 2;
          HexData[0] = pByte[i * UnitSize +1];
          HexData[1] = pByte[i * UnitSize + 0];
          break;

        case IPS7_DWORD:
        case IPS7_DINT:
        case IPS7_REAL:
          UnitSize = 4;
          HexData[0] = pByte[i * UnitSize + 3];
          HexData[1] = pByte[i * UnitSize + 2];
          HexData[2] = pByte[i * UnitSize + 1];
          HexData[3] = pByte[i * UnitSize + 0];
          break;
      }
      
      for (j = 0; j < UnitSize; j++)
      {
        sprintf (&StrHex[strlen(StrHex)], "%02X",HexData[j]);
        
        if (isprint (HexData[j]))
          sprintf (&StrAscii[strlen(StrAscii)], "%c",HexData[j]);
        else
          strcat (StrAscii, ".");
      }
    }

    printf ("%s %s %s %s\n", S, StrValue, StrHex, StrAscii);
    MsgGetKey ();
 }
}

void OnRdMulti (int Ref) 
{
  BYTE EBits[64];
  BYTE EBytes[1024];
  WORD MWords[32];
  WORD DB10Words [150];
  double DB10WordsAsDouble [150];
  float DB20RealAsFloat [60];
  int32_t TimerAsInt [10];
  int Res;
  int Cnt = 10;
  int i;
  
  IPS7_RQ_MULTI  Rq[10] ; // Max. 10 Auftr�ge;
  memset (Rq, 0, sizeof (Rq));
  
  Cnt = 0;
  
  // lese ab E 4.0 32 Bit
  InitRq (&Rq[Cnt++], 'E', IPS7_BIT, PC_BYTE, 0, 4, 0, 32, EBits); 

  BYTE DB10Bits[65];  

  // lese ab DB10.DBX1.1  32 Bit
  InitRq (&Rq[Cnt++], 'D', IPS7_BIT, PC_BYTE, 10, 1, 1, 32, DB10Bits); 

  // lese ab EB0 20 Byte und lege diese ab [20] ab
  InitRq (&Rq[Cnt++], 'E', IPS7_BYTE, PC_BYTE, 0, 0, 0, 20, &EBytes[20]); 
  
  //lese ab MB 20 10 Worte
  InitRq (&Rq[Cnt++], 'M', IPS7_WORD, PC_WORD16, 0, 20, 0, 1, MWords);
  
  //lese  DB10 ab Datenbyte 0 150 Worte
  InitRq (&Rq[Cnt++], 'D', IPS7_WORD, PC_WORD16, 10, 0, 0, 150, DB10Words);
  
  //lese DB20 ab Datenbyte 0 150 Worte lege diese aber als double im PC ab
  InitRq (&Rq[Cnt++], 'D', IPS7_WORD, PC_DOUBLE, 10, 0, 0, 150, DB10WordsAsDouble);
  
  //lese  DB20 ab Datenbyte 6 60 Realwerte und lege diese als Floatwerte im PC ab
  InitRq (&Rq[Cnt++], 'D', IPS7_REAL, PC_FLOAT, 100, 6, 0, 60, DB20RealAsFloat); 
  
  //lese ab Timer 5 10 Timer und lege diese als int ab
  InitRq (&Rq[Cnt++], 'T', IPS7_TIMER, PC_WORD32, 0, 0, 0, 5, TimerAsInt); // T5 10 Timer
 
  Res = IPS7RdMulti(Ref, Rq, Cnt);
  if (Res != 0)
    DoErr (Ref, Res);
  for (i = 0; i < Cnt; i++ )
  {
    ShowMultiRdItems (Ref, i, Rq[i].DataArea, Rq[i].DBNr, Rq[i].Start, Rq[i].StartBit, Rq[i].Cnt,  Rq[i].PcDataType,  Rq[i].DataType, Rq[i].Data,  TRUE, Rq[i].Result);
  }
}


void ReadDiagBuffer (int Ref)
{
  int Res;
  int EventCnt;
  S7_EVENTENTRY Entries[20];
  memset (&Entries, 0, sizeof (Entries));

  Res = IPS7ReadDiagBuffer (Ref, Entries, 20, &EventCnt);
  if (Res != 0)
    DoErr (Ref, Res);
  else
  {
    int i;

	for (i = 0; i < EventCnt; i++)
	  printf ("ID:%04X: %s\n", Entries[i].EventId, Entries[i].Text); 	
  }
}



                       
int main (int argc, char *Args[])
{
  int i;
  int RackNr = 0;
  int Slot = 2;
  long Ref;
  int AccessMode;
  int DstMPIProfiAdr = 2;
  unsigned long SubNetId = 0;

  strcpy (IPAdr, DefaultIPAdr);                                                                       
  printf ("IP-S7-LINK-DEMO Version 1.48\n");
  AccessMode = 0;

  AccessMode = GetAccessMode ();
  if (AccessMode < 10) // ohne Subnet d.h. Rack und SlotNr notwendig
  {
    if (AccessMode != 3) // nicht bei Logo
    {
      printf ("RackNr / rack no. %u: \n", RackNr);
      SRes = scanf ("%u",&RackNr);
      printf ("\naktuelle RackNr / actual rack no.  %u \n", RackNr);
      printf ("Steckplatz-Nr: / Slot: %u: \n", Slot);
      SRes = scanf ("%u",&Slot);
    }
  }
  else if (AccessMode == 1215)
  {
    RackNr = 0;
    Slot = 1;
    AccessMode = 0;
  }
  else
  {
    DstMPIProfiAdr = GetInt ("MPI,Profibus-Adresse der Ziel-CPU /  MPI, Profibus address of dest. CPU", DstMPIProfiAdr , 0, 126);
    SubNetId = GetULongHex ("Subnet-ID (Beispiel f�r 1230-4500 eingeben 12304500) / Subnet-ID (e.g for 1230-4500 enter 12304500)", SubNetId);
  }
  
  strcpy (IPAdr, DefaultIPAdr);
  printf ("\nIP-Adresse: / IP-Address: %s \n", IPAdr);
  SRes = scanf ("%s", IPAdr);  

  printf ("Mit IP-Adr %s wird gearbeitet: / working withg IP-Address: %s\n", IPAdr, IPAdr);

//  Ref = IPS7Open (IPAdr, RackNr, Slot, 500,500, 500);
  //Ref = IPS7Open (IPAdr, RackNr, Slot, 5000,5000, 5000);


  Ref = IPS7OpenEx (IPAdr, RackNr, Slot, SubNetId, DstMPIProfiAdr, AccessMode, 5000,5000, 5000); // 1.23
  if (Ref >= 0) 
  {       
    BOOL bDo = TRUE;
    for (;bDo;)
    { 
      printf ("\n****************\n"
              "1 = lese Merker / read flags\n"
              "2 = lese Eingang / read inputs\n"
              "3 = schreibe Ausgang / read outputs\n"
              "4 = Lese DB / read DB\n"
              "5 = Schreibe DB / write DB\n"
              "7 = schreibe Merker / write flag\n"
              "8 = lese Merker Bit / read flag bit\n"
              "9 = setze Merker Bit / set flaf bit\n"
              "a = ruecksetze Merker Bit / reset flag bit\n"
              "b = lese Timer / read timer\n"
              "c = schreibe Timer / write timer\n"
              "d = lese Zaehler / read counter\n"
              "e = schreibe Zaehler / write counter\n"
              "f = lese Fliesskommawerte / read floating point values\n"
              "g = schreibe Fliesskommawerte / write flouting point values\n"
              "h = lese Doppelworte  (32 Bit) / read double words (32 bit)\n"
              "i = schreibe Doppelworte (32 Bit) / write double words (32 bit)\n"
              "l = lese LInt  (64 Bit) / read LInt (64 bit)\n"
              "m = gemischtes Lesen (MultiRead)  / mixed read (MultiRead)\n"
  	    	    "t = SPS-Zeit lesen / read PLC-Time\n"
  	    	    "x = Diagnosepuffer lesen / read Diagnostic buffer\n"
              "0 = Ende / exit\n"
              "Bitte waehlen / please select\n\n"
              );
      
      switch (i = GetKey ())
      {
        case '1':
          RdMB (Ref);
          break;
        
        case '2':
          RdEB (Ref);
          break;
        
        case '3':
          WrAB (Ref);
          break;
             
        case '4':
          RdDB (Ref);
          break;
               
        case '5':
          WrDB (Ref);
          break;
     
        case '7':
          WrMB (Ref);
          break;

        case '8':
          RdMBit (Ref);
          break;
       
        case '9':
          SetMBit (Ref, 1);
          break;

        case 'a':
        case 'A':
          SetMBit (Ref, 0);
          break;

        case 'b':
        case 'B':
          RdTimer (Ref);
          break;

        case 'c':
        case 'C':
          WrTimer (Ref);
          break;

        case 'd':
        case 'D':
          RdCounter (Ref);
          break;

        case 'e':
        case 'E':
          WrCounter (Ref);
          break;

        case 'f':
        case 'F':
          RdFloat (Ref);
          break;
      
        case 'g':
        case 'G':
          WrFloat (Ref);
          break;

        case 'h':
        case 'H':
          RdDWord (Ref);
          break;
      
        case 'i':
        case 'I':
          WrDWord (Ref);
          break;

        case 'm':
        case 'M':
          OnRdMulti (Ref);
           break;

        case 't':
        case 'T':
          GetPlcTime (Ref);
          break;

        case 'l':
        case 'L':
          RdLInt (Ref);
          break;


		    case 'x':
		    case 'X':
		      ReadDiagBuffer (Ref);
		      break;

        case '0':
          bDo = FALSE;
          break;
      }
    }
    IPS7Close (Ref);        
  }   
  else
  {
    printf ("Fehler bei 'IPS7Open:' / Error at 'IPS7Open' %ld\n", Ref);
  }
  
  return EXIT_SUCCESS;
  
}
/*------------------------------------------------------------*/
