#include "NetworkReader.h" /** * Constructor * @param networkFileName input xml file */ NetworkReader::NetworkReader(const char * networkFileName) { ldsIndex = 0; loadLines(networkFileName); } /** * Parses a station xml element into an "LDS_LOOP" * * @param stationElem the station xml element * @param the parent line * @return the new station */ LDS_LOOP NetworkReader::parseStation(TiXmlElement *stationElem, FEP_LINE *line) { LDS_LOOP station; TiXmlElement *stationSubElem = stationElem->FirstChildElement(); cout << "Station id: " << stationSubElem->GetText() << endl; station.lds = atol(stationSubElem->GetText()); line->lds.push_back(station.lds); line->ldsIndex.push_back(ldsIndex++); stationSubElem = stationSubElem->NextSiblingElement(); station.line_num = atoi(stationSubElem->GetText()); stationSubElem = stationSubElem->NextSiblingElement(); station.drop = atoi(stationSubElem->GetText()); stationSubElem = stationSubElem->NextSiblingElement(); stationSubElem = stationSubElem->NextSiblingElement(); // skip location stationSubElem = stationSubElem->NextSiblingElement(); // skip postmile stationSubElem = stationSubElem->NextSiblingElement(); // skip direction stationSubElem = stationSubElem->NextSiblingElement(); // skip freeway station.MlTotVol = atoi(stationSubElem->GetText()); stationSubElem = stationSubElem->NextSiblingElement(); station.OppTotVol = atoi(stationSubElem->GetText()); station.pos = 0; // Add loops to station TiXmlElement *loopsElem = stationSubElem->NextSiblingElement(); TiXmlElement *loopElem = loopsElem->FirstChildElement(); TiXmlElement *saveLoopElem = loopElem; // get number of loops in station and assign to station.num station.num = 0; for (loopElem; loopElem; loopElem = loopElem->NextSiblingElement()) { station.num += 1; } // get loopIDS and locations long int loopIDS[station.num]; char * loopLocs[station.num]; int index = 0; for (saveLoopElem; saveLoopElem; saveLoopElem = saveLoopElem->NextSiblingElement()) { TiXmlElement *subLoopElem = saveLoopElem->FirstChildElement(); loopIDS[index] = atoi(subLoopElem->GetText()); subLoopElem = subLoopElem->NextSiblingElement(); loopLocs[index++] = (char *) subLoopElem->GetText(); } station.loopID = loopIDS; station.loop_loc = loopLocs; // Data pack ATMS message station.length = station.num * 2 + CONTROL_DATA_LEN; station.dataPack = staticDataPack(station); /* // fill in dynamic data to dataPack[] for (i = 0; i < g_ldsNum; i++) { // Loop detector data int pos = 26; pos = pp_data_packing(i, 5, pos); pos = pp_data_packing(i, 6, pos); pos = pp_data_packing(i, 7, pos); pos = pp_data_packing(i, 8, pos); // Update data for BYTE 9, 16, 21, 22, 23, 24 // what is the current metering rate? // check each LDS, if there is demand detector, the downstream node the // ldsMap[i].dataPack[22-1] = ldsMap[i].dataPack[9-1] = ; // will need to check if queue override is enabled (Currently, no queue // ldsMap[i].dataPack[16-1] = ; // byte 23: MAINLINE total volume ldsMap[i].dataPack[23 - 1] = ldsMap[i].MlTotVol; // byte 24: opposite total volume ldsMap[i].dataPack[24 - 1] = ldsMap[i].OppTotVol; // last BYTE: checksum ldsMap[i].dataPack[ldsMap[i].length - 1] = chksum(ldsMap[i].dataPack, ldsMap[i].length - 1 - 1); // print out // print out for (j = 0; j < ldsMap[i].length; j++) { fprintf(fi_lds, "%02X", ldsMap[i].dataPack[j]); } fprintf(fi_lds, "\n"); fflush(fi_lds); */ return station; } /** * Parses a "Line" xml element into an FEP_LINE * @param lineElem the xml element * @return FEP_LINE */ FEP_LINE NetworkReader::parseLine(TiXmlElement * lineElem) { FEP_LINE line; TiXmlElement *lineSubElem = lineElem->FirstChildElement(); line.lineNum = atoi(lineSubElem->GetText()); cout << "Line: " << line.lineNum << endl; lineSubElem = lineSubElem->NextSiblingElement(); line.count = atoi(lineSubElem->GetText()); lineSubElem = lineSubElem->NextSiblingElement(); line.schedule = atoi(lineSubElem->GetText()); lineSubElem = lineSubElem->NextSiblingElement(); line.lineInfo = atoi(lineSubElem->GetText()); lineSubElem = lineSubElem->NextSiblingElement(); line.systemKey = atol(lineSubElem->GetText()); lineSubElem = lineSubElem->NextSiblingElement(); line.globalSeq = atol(lineSubElem->GetText()); lineSubElem = lineSubElem->NextSiblingElement(); line.schedleSeq = atol(lineSubElem->GetText()); TiXmlElement *stationsElem = lineSubElem->NextSiblingElement(); TiXmlElement *stationElem = stationsElem->FirstChildElement(); for (stationElem; stationElem; stationElem = stationElem->NextSiblingElement()) { stations.push_back(parseStation(stationElem, &line)); } return line; } /** * Loads FEPLines from a specified xml file * @param networkFileName the input xml file */ void NetworkReader::loadLines(const char * networkFileName) { // Load network xml file TiXmlDocument doc(networkFileName); if (!doc.LoadFile()) { cerr << "TiXmlDocument did not load network file..." << endl; return; } // grab element TiXmlHandle hDoc(&doc); TiXmlElement *networkElem = hDoc.FirstChildElement().Element(); // grab first element TiXmlElement *lineElem = networkElem->FirstChildElement(); // iterate through each line element to create FEP_LINE list for (lineElem; lineElem; lineElem = lineElem->NextSiblingElement()) { lines.push_back(parseLine(lineElem)); } } // determine if a loop has data based on lane config data bool NetworkReader::DataAvail(char flag, int num) { int mag, fel; // find mask value if (num == 1) mag = 0x01; else if (num == 2) mag = 0x02; else if (num == 3) mag = 0x04; else if (num == 4) mag = 0x08; else if (num == 5) mag = 0x10; else if (num == 6) mag = 0x20; else if (num == 7) mag = 0x40; else if (num == 8) mag = 0x80; fel = flag & mag; fel = fel >> (num - 1); if (fel == 1) return true; else return false; } /* int pp_data_packing(int index, int packNo, int pos) { int i, j, k, vol, occ, lane, haveData; LOOPAGG in; DETECTOR *aaa; VOLOCC bbb; long loop; i = index; //used for data byte 23 and 24 ldsMap[i].MlTotVol = 0; ldsMap[i].OppTotVol = 0; for (j = 1; j <= 8; j++) { if (DataAvail(ldsMap[i].dataPack[packNo - 1], j)) { // loop at bit j has data for (k = 0; k < ldsMap[i].num; k++) { // what's the corresponding loop of bit j if (packNo == 5) haveData = strcmp(ldsMap[i].loop_loc[k], dp5[j - 1]); else if (packNo == 6) haveData = strcmp(ldsMap[i].loop_loc[k], dp6[j - 1]); else if (packNo == 7) haveData = strcmp(ldsMap[i].loop_loc[k], dp7[j - 1]); else if (packNo == 8) haveData = strcmp(ldsMap[i].loop_loc[k], dp8[j - 1]); else return -1; if (haveData == 0) { loop = ldsMap[i].loopID[k]; if (strcmp(chu[loop].paramicsName, "?") == 0) { { vol = 0; occ = 900; } else { aaa = qpg_NET_detector(chu[loop].paramicsName); Bool status = uci_loop_aggregation(qpg_DTC_index(aaa), POLLING if (status) { if (chu[loop].paramicsLane == 0) lane = 0; else lane = chu[loop].paramicsLane - 1; vol = in.vol[lane]; occ = (int) (in.occ[lane] * 900 + 0.5); // qps_GUI_printf("%d(%s), lane=%d, vol=%d(%d), occ=%.3f(%.3f, // qpg_DTC_index(aaa), chu[loop].paramicsName, in.lane, in. // vol, in.g_occ, in.occ[lane], occ); } else qps_GUI_printf("Data query error for %s\n", chu[loop].param } bbb = pp_vol_occ_word(vol, occ); pos++; ldsMap[i].dataPack[pos - 1] = bbb.high; pos++; ldsMap[i].dataPack[pos - 1] = bbb.low; if (packNo == 5) { ldsMap[i].MlTotVol += vol; } else if (packNo == 6) { ldsMap[i].OppTotVol += vol; } fprintf(fi_lds, "lds=%d, loop=%d, paramics=%s, lane=%d, vol=%d(%X ldsMap[i].lds, loop, chu[loop].paramicsName, chu[loop].paramic bbb.high, occ, bbb.low); fflush(fi_lds); } } } } return pos; } */ // Initializes the LDS_LOOP dataPack with all necessary static data and default dynamic data unsigned char * NetworkReader::staticDataPack(LDS_LOOP loop) { int j; // Allocate memory for dataPack unsigned char *dataPack = (unsigned char *) calloc(1, sizeof (unsigned char) * loop.length); // dataPack 5-8: lane config char d5 = 0, d6 = 0, d7 = 0, d8 = 0; for (j = 0; j < loop.num; j++) { for (int k = 0; k < 8; k++) { if (strcmp(loop.loop_loc[j], dp5[k]) == 0) d5 += pow(2, k); if (strcmp(loop.loop_loc[j], dp6[k]) == 0) d6 += pow(2, k); if (strcmp(loop.loop_loc[j], dp7[k]) == 0) d7 += pow(2, k); if (strcmp(loop.loop_loc[j], dp8[k]) == 0) d8 += pow(2, k); } } dataPack[5 - 1] = d5; dataPack[6 - 1] = d6; dataPack[7 - 1] = d7; dataPack[8 - 1] = d8; // dataPack 1: Drop number, i.e. station address dataPack[1 - 1] = loop.drop; // dataPack2 (2 bytes per loop) dataPack[2 - 1] = loop.num * 2 + Fixed_Byte_To_Checksum; // dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops) int low = 0, high = 0; for (j = 1; j <= 6; j++) { low += DataAvail(dataPack[5 - 1], j); high += DataAvail(dataPack[6 - 1], j); } high = high << 4; dataPack[3 - 1] = high | low; // dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00) dataPack[4 - 1] = 0xA0; // dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec dataPack[9 - 1] = 0; // datadataPack 10-13: lane malfunction? Assuming all functional dataPack[10 - 1] = 0; dataPack[11 - 1] = 0; dataPack[12 - 1] = 0; dataPack[13 - 1] = 0; // dataPack 14-22: ramp metering data // BYTE 16 and 22 need to be updated every 30 sec bool found = false; for (j = 0; j < loop.num; j++) { if (strcmp(loop.loop_loc[j], "DEMAND") == 0) { found = true; break; } } if (found) { // BYTE 14: mostly 07, some are 05, 03, 00 dataPack[14 - 1] = 0x07; // mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive) dataPack[15 - 1] = 0x06; // most 00, some are 01 (queue override) or 80(Meter ON sign) dataPack[16 - 1] = 0x00; // Field Manual Rate dataPack[17 - 1] = 0xFF; // TOC Manual Rate dataPack[18 - 1] = 0xFF; // PSO Manual Rate dataPack[19 - 1] = 0xFF; // CORM Rate dataPack[20 - 1] = 0xFF; // Local Responsive Rate. DON'T UNDERSTAND YET dataPack[21 - 1] = 0x00; // TOD Rate: need to query RAMP plugin! dataPack[22 - 1] = 0x00; } // LDS: NO Metering else { dataPack[14 - 1] = 0x00; dataPack[15 - 1] = 0x0B; dataPack[16 - 1] = 0x00; dataPack[17 - 1] = 0xFF; dataPack[18 - 1] = 0xFF; dataPack[19 - 1] = 0xFF; dataPack[20 - 1] = 0xFF; dataPack[21 - 1] = 0x00; dataPack[22 - 1] = 0x00; } // dataPack 23-24: sum of mainline/Oppsite traffic data; need to be updated every 30 sec loop.MlTotVol = 0; loop.OppTotVol = 0; dataPack[23 - 1] = loop.MlTotVol; dataPack[24 - 1] = loop.OppTotVol; // dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84 dataPack[25 - 1] = 0x03; dataPack[26 - 1] = 0x84; return dataPack; } /** * Getter for lines * @return List of FEP_LINES */ vector NetworkReader::getLines() { return lines; } /** * Getter for stations * @return List of LDS_LOOPs */ vector NetworkReader::getStations() { return stations; } NetworkReader::~NetworkReader() { }