void parse_lib(std::string filename)
{
    int inpfile = open(filename.c_str(), O_RDONLY);
    if (inpfile == -1) {
        printf("[%s:%d] unable to open '%s'\n", __FUNCTION__, __LINE__, filename.c_str());
        exit(-1);
    }
    int len = read(inpfile, buffer, sizeof(buffer));
    if (len >= sizeof(buffer) - 1) {
        printf("[%s:%d] incomplete read of '%s'\n", __FUNCTION__, __LINE__, filename.c_str());
        exit(-1);
    }
    parsenext();
    if (tokval != "library") {
        printf("[%s:%d] 'library' keyword not found\n", __FUNCTION__, __LINE__);
        exit(-1);
    }
    validate_token(isId(tokval[0]), "name");
    parseparam();
    parse_item(false, "", nullptr);
}
void parse_item(bool capture, std::string pinName, AttributeList *attr)
{
    while (tokval != "}" && !eof) {
        std::string paramname = tokval;
        validate_token(isId(tokval[0]), "name");
        if (paramname == "default_intrinsic_fall" || paramname == "default_intrinsic_rise") {
            validate_token(tokval == ":", ":(paramname)");
            if (capture)
                addAttr(attr, pinName, paramname, tokval);
            validate_token(isdigit(tokval[0]), "number");
        }
        else if (paramname == "bus_type") {
            validate_token(tokval == ":", ":(bus_type)");
            if (capture)
                addAttr(attr, pinName, paramname, tokval);
            validate_token(isId(tokval[0]), "name");
        }
        else if (tokval == "(") {
            while (tokval == "(") {
                std::string paramstr = parseparam();
                bool cell = paramname == "cell" && paramstr == options.cell;
                int ind = paramstr.find("[");
                if (capture && (paramname == "pin" || paramname == "bus")) {
                    if (ind > 0 && paramstr[paramstr.length()-1] == ']') {
                        std::string sub = paramstr.substr(ind+1);
                        sub = sub.substr(0, sub.length()-1);
                        paramstr = paramstr.substr(0, ind);
                        capturePins[paramstr].pins[atol(sub.c_str())] = 1;
                    }
                    parse_item(true, paramstr, &capturePins[paramstr].attr);
                }
                else if (paramname == "type") {
                    parse_item(true, "", &busInfo[paramstr].attr);
                }
                else
                    parse_item(capture || cell, pinName, attr);
//if (paramname == "cell")
//printf("[%s:%d] paramname %s paramstr %s \n", __FUNCTION__, __LINE__, paramname.c_str(), paramstr.c_str());
                if (cell) {
                    processCell();
                    return;
                }
                paramname = tokval;
                if (!isId(tokval[0]))
                    break;
                parsenext();
            }
        }
        else {
            validate_token(tokval == ":", ":(other)");
            if (capture && paramname != "timing_type")
                addAttr(attr, pinName, paramname, tokval);
            if (isdigit(tokval[0]) || isId(tokval[0]) || tokval[0] == '"')
                parsenext();
            else
                validate_token(false, "number or name or string");
            if (tokval != "}")
                validate_token(tokval == ";", ";");
        }
    }
    validate_token(tokval == "}", "}");
}
int main(int argc, char *argv[]) {
    int      key    = 0;
    int      iCheck = 0;
    int      iX;
    int      iK;
    char     KeyInput[_MAX_PATH];
    char     Key[3];
    char     CommandlineDatPath[_MAX_PATH];
    double   csvValue;
    int      Meters = 0;
    unsigned long ReturnValue;
    FILE    *hDatFile;

    uint16_t InfoFlag = SILENTMODE;
    uint16_t Port = 0;
    uint16_t Mode = RADIOT2;
    uint16_t LogMode = LOGTOCSV;
    uint16_t wMBUSStick = iM871AIdentifier;

    char     comDeviceName[100];
    int      hStick;
//Variables added for CIVIS project
    FILE *fp;
    char row[100], word1[50], word2[50];
    char *res;
    int i=1;
    char filepath[50]="/home/pi/sw/civis_config.txt\0";
//----
    ecwMBUSMeter ecpiwwMeter[MAXMETER];
    memset(ecpiwwMeter, 0, MAXMETER*sizeof(ecwMBUSMeter));

    memset(CommandlineDatPath, 0, _MAX_PATH*sizeof(char));



    if(argc > 1)
      parseparam(argc, argv, CommandlineDatPath, &InfoFlag, &Port, &Mode, &LogMode);

    //read config back
    if ((hDatFile = fopen("meter.dat", "rb")) != NULL) {
        Meters = fread((void*)ecpiwwMeter, sizeof(ecwMBUSMeter), MAXMETER, hDatFile);
        fclose(hDatFile);
    }

    Intro();

//Gets ApartmentID for CIVIS project
    
    fp=fopen(filepath, "r");
    do {
	memset(row, 0, 100);
	memset(word1,0, 50);
	memset(word2,0, 50);
	strcpy(row,"");
	strcpy(word1,"");
	strcpy(word2,"");
	res=fgets(row, 99, fp);
	sscanf(row, "%s %s", word1, word2);
		if (strcmp(word1, "ID")==0){
			strcpy(ApartmentID,word2);
			break;
		}
	} while (res!=NULL);
    printf("ApartmentID=%s\n", ApartmentID);
    fclose(fp);

//------
    //open wM-Bus Stick #1
    wMBUSStick = iM871AIdentifier;
    sprintf(comDeviceName, "/dev/ttyUSB%d", Port);
    hStick = wMBus_OpenDevice(comDeviceName, wMBUSStick);

    if(hStick <= 0) { //try 2.Stick
        wMBUSStick = iAMB8465Identifier;
        usleep(500*1000);
        hStick = wMBus_OpenDevice(comDeviceName, wMBUSStick);
    }

    if(hStick <= 0) {
         ErrorAndExit("no wM-Bus Stick not found\n");
    }

    if((iM871AIdentifier == wMBUSStick) && (APIOK == wMBus_GetStickId(hStick, wMBUSStick, &ReturnValue, InfoFlag)) && (iM871AIdentifier == ReturnValue)) {
        if(InfoFlag > SILENTMODE) {
            printf("IMST iM871A Stick found\n");
        }
    }
    else {
        wMBus_CloseDevice(hStick, wMBUSStick);
        //try 2. Stick
        wMBUSStick = iAMB8465Identifier;
        hStick = wMBus_OpenDevice(comDeviceName,wMBUSStick);
        if((iAMB8465Identifier == wMBUSStick) && (APIOK == wMBus_GetStickId(hStick, wMBUSStick, &ReturnValue, InfoFlag)) && (iAMB8465Identifier == ReturnValue)) {
            if(InfoFlag > SILENTMODE) {
                printf("Amber Stick found\n");
            }
        }
        else {
            wMBus_CloseDevice(hStick, wMBUSStick);
            ErrorAndExit("no wM-Bus Stick not found\n");
        }
    }

    if(APIOK == wMBus_GetRadioMode(hStick, wMBUSStick, &ReturnValue, InfoFlag)) {
        if(InfoFlag > SILENTMODE) {
            printf("wM-BUS %s Mode\n", (ReturnValue == RADIOT2) ? "T2" : "S2");
        }
        if (ReturnValue != Mode)
           wMBus_SwitchMode(hStick, wMBUSStick, (uint8_t) Mode, InfoFlag);
    }
    else
        ErrorAndExit("wM-Bus Stick not found\n");

    wMBus_InitDevice(hStick, wMBUSStick, InfoFlag);

    UpdateMetersonStick(hStick, wMBUSStick, Meters, ecpiwwMeter, InfoFlag);

    IsNewMinute();

    while (!((key == 0x1B) || (key == 'q'))) {
        usleep(500*1000);   //sleep 500ms

        key = getkey();

        /*key =fgetc(stdin);
        while(key!='\n' && fgetc(stdin) != '\n');
        printf("Key=%d",key);*/


        //add a new Meter
        if (key == 'a') {
            iX=0;
            while(0 != ecpiwwMeter[iX].manufacturerID) {
                iX++;
                if(iX == MAXMETER-1)
                  continue;
              }
            //check entry in list of meters
            if(iX < MAXMETER) {
                printf("\nAdding Meter #%d \n",iX+1);
                printf("Enter Meter Ident (12345678): ");
                if(fgets(KeyInput, _MAX_PATH,stdin))
                    ecpiwwMeter[iX].ident=CalcUIntBCD(atoi(KeyInput));

                printf("Enter Meter Type (2 = Electricity ; 3 = Gas ; 7 = Water) : ");
                if(fgets(KeyInput, _MAX_PATH,stdin)) {
                    switch(atoi(KeyInput)) {
                        case METER_GAS  :        ecpiwwMeter[iX].type = METER_GAS;          break;
                        case METER_WATER:        ecpiwwMeter[iX].type = METER_WATER;        break;
                        default: printf(" - wrong Type ; default to Electricity");
                        case METER_ELECTRICITY : ecpiwwMeter[iX].type = METER_ELECTRICITY;  break;
                    }
                }
                ecpiwwMeter[iX].manufacturerID = FASTFORWARD;
                ecpiwwMeter[iX].version        = 0x01;

                printf("Enter Key (0 = Zero ; 1 = Default ; 2 = Enter the 16 Bytes) : ");
                if(fgets(KeyInput, _MAX_PATH, stdin)) {
                    switch(atoi(KeyInput)) {
                        case 0  : for(iK = 0; iK<AES_KEYLENGHT_IN_BYTES; iK++)
                                    ecpiwwMeter[iX].key[iK] = 0;
                        break;

                        default:
                        case 1  : for(iK = 0; iK<AES_KEYLENGHT_IN_BYTES; iK++)
                                    ecpiwwMeter[iX].key[iK] = (uint8_t)(0x1C + 3*iK);
                        break;

                        case 2  :
                                printf("Key:");
                                fgets(KeyInput, _MAX_PATH, stdin);
                                    for(iK = 0; iK<AES_KEYLENGHT_IN_BYTES; iK++)
                                        ecpiwwMeter[iX].key[iK] = 0;
                                if((strlen(KeyInput)-1) < AES_KEYLENGHT_IN_BYTES*2)
                                    printf("Key is too short - default to Zero\n");
                                else {
                                    memset(Key,0,sizeof(Key));
                                    for(iK = 0; iK<(int)(strlen(KeyInput)-1)/2; iK++) {
                                        Key[0] =  KeyInput[2*iK];
                                        Key[1] =  KeyInput[2*iK+1];
                                        ecpiwwMeter[iX].key[iK] = (uint8_t) strtoul(Key, NULL, 16);
                                    }
                                }
                        break;
                    }
                }

                Meters++;
                Meters = min(Meters, MAXMETER);
                DisplayListofMeters(Meters, ecpiwwMeter);
                UpdateMetersonStick(hStick, wMBUSStick, Meters, ecpiwwMeter, InfoFlag);
            } else
                printf("All %d Meters defined\n", MAXMETER);
        }

        // display list of meters
        if(key == 'l')
            DisplayListofMeters(Meters, ecpiwwMeter);

        //remove a meter from the list
        if(key == 'r') {
            printf("Enter Meterindex to remove: ");
            if(fgets(KeyInput, _MAX_PATH, stdin)) {
                iX = atoi(KeyInput);
                if(iX-1 <= Meters-1) {
                    printf("Remove Meter #%d\n",iX);
                    memset(&ecpiwwMeter[iX-1], 0, sizeof(ecwMBUSMeter));
                    DisplayListofMeters(Meters, ecpiwwMeter);
                    UpdateMetersonStick(hStick, wMBUSStick, Meters, ecpiwwMeter, InfoFlag);
                 }
                 else
                    printf("Index not defined\n");
            }
        }

        // switch to S2 mode
        if(key == 's')
            wMBus_SwitchMode( hStick,wMBUSStick, RADIOS2,InfoFlag);

        // switch to T2 mode
        if(key == 't')
            wMBus_SwitchMode( hStick,wMBUSStick, RADIOT2,InfoFlag);

        //check whether there are new data from the EnergyCams
        if (IsNewMinute() || (key == 'u')) {
            if(wMBus_GetMeterDataList() > 0) {
                iCheck = 0;
                for(iX=0; iX<Meters; iX++) {
                    if((0x01<<iX) & wMBus_GetMeterDataList()) {
                        ecMBUSData RFData;
                        int iMul=1;
                        int iDiv=1;
                        wMBus_GetData4Meter(iX, &RFData);

                        if(RFData.exp < 0) {  //GAS
                            for(iK=RFData.exp; iK<0; iK++)
                               iDiv=iDiv*10;
                            csvValue = ((double)RFData.value)/iDiv;
                        } else {
                            for(iK=0; iK<RFData.exp; iK++)
                                iMul=iMul*10;
                            csvValue = (double)RFData.value*iMul;
                        }
                        if(InfoFlag > SILENTMODE) {
                            Colour(PRINTF_GREEN, false);
                            printf("Meter #%d : %4.1f %s", iX+1, csvValue, (ecpiwwMeter[iX].type == METER_ELECTRICITY) ? "Wh" : "m'3");
                        }
                        if(ecpiwwMeter[iX].type == METER_ELECTRICITY)
                            csvValue = csvValue/1000.0;

                        if(InfoFlag > SILENTMODE) {
                            if((RFData.pktInfo & PACKET_WAS_ENCRYPTED)      ==  PACKET_WAS_ENCRYPTED)     printf(" Decryption OK");
                            if((RFData.pktInfo & PACKET_DECRYPTIONERROR)    ==  PACKET_DECRYPTIONERROR)   printf(" Decryption ERROR");
                            if((RFData.pktInfo & PACKET_WAS_NOT_ENCRYPTED)  ==  PACKET_WAS_NOT_ENCRYPTED) printf(" not encrypted");
                            if((RFData.pktInfo & PACKET_IS_ENCRYPTED)       ==  PACKET_IS_ENCRYPTED)      printf(" is encrypted");
                            printf(" RSSI=%i dbm, #%d \n", RFData.rssiDBm, RFData.accNo);
                            Colour(0,false);
                        }

                        Log2File(CommandlineDatPath, LogMode, iX, InfoFlag, csvValue, &RFData, ecpiwwMeter[iX].ident);

                    }
                }
            }
            else {
              if(InfoFlag > SILENTMODE) {
                  Colour(PRINTF_YELLOW, false);
                  printf("%02d ", iCheck);
                  Colour(0, false);
                  if((++iCheck % 20) == 0) printf("\n");
                }
            }
        }
    } // end while

    if(hStick >0) wMBus_CloseDevice(hStick, wMBUSStick);

    //save Meter config to file
    if(Meters > 0) {
        if ((hDatFile = fopen("meter.dat", "wb")) != NULL) {
            fwrite((void*)ecpiwwMeter, sizeof(ecwMBUSMeter), MAXMETER, hDatFile);
            fclose(hDatFile);
        }
    }
    return 0;
}