| 1 | #include "NetworkReader.h" |
|---|
| 2 | /** |
|---|
| 3 | * Constructor |
|---|
| 4 | * @param networkFileName input xml file |
|---|
| 5 | */ |
|---|
| 6 | NetworkReader::NetworkReader(const char * networkFileName) |
|---|
| 7 | { |
|---|
| 8 | ldsIndex = 0; |
|---|
| 9 | loadLines(networkFileName); |
|---|
| 10 | } |
|---|
| 11 | |
|---|
| 12 | /** |
|---|
| 13 | * Parses a station xml element into an "LDS_LOOP" |
|---|
| 14 | * |
|---|
| 15 | * @param stationElem the station xml element |
|---|
| 16 | * @param the parent line |
|---|
| 17 | * @return the new station |
|---|
| 18 | */ |
|---|
| 19 | LDS_LOOP NetworkReader::parseStation(TiXmlElement *stationElem, FEP_LINE line) |
|---|
| 20 | { |
|---|
| 21 | LDS_LOOP station; |
|---|
| 22 | |
|---|
| 23 | TiXmlElement *stationSubElem = stationElem->FirstChildElement(); |
|---|
| 24 | cout << "Station id: " << stationSubElem->GetText() << endl; |
|---|
| 25 | station.lds = atol(stationSubElem->GetText()); |
|---|
| 26 | line.lds.push_back(station.lds); |
|---|
| 27 | line.ldsIndex.push_back(ldsIndex++); |
|---|
| 28 | stationSubElem = stationSubElem->NextSiblingElement(); |
|---|
| 29 | station.line_num = atoi(stationSubElem->GetText()); |
|---|
| 30 | stationSubElem = stationSubElem->NextSiblingElement(); |
|---|
| 31 | station.drop = atoi(stationSubElem->GetText()); |
|---|
| 32 | stationSubElem = stationSubElem->NextSiblingElement(); |
|---|
| 33 | stationSubElem = stationSubElem->NextSiblingElement(); // skip location |
|---|
| 34 | stationSubElem = stationSubElem->NextSiblingElement(); // skip postmile |
|---|
| 35 | stationSubElem = stationSubElem->NextSiblingElement(); // skip direction |
|---|
| 36 | stationSubElem = stationSubElem->NextSiblingElement(); // skip freeway |
|---|
| 37 | station.MlTotVol = atoi(stationSubElem->GetText()); |
|---|
| 38 | stationSubElem = stationSubElem->NextSiblingElement(); |
|---|
| 39 | station.OppTotVol = atoi(stationSubElem->GetText()); |
|---|
| 40 | |
|---|
| 41 | station.pos = 0; |
|---|
| 42 | // Add loops to station |
|---|
| 43 | TiXmlElement *loopsElem = stationSubElem->NextSiblingElement(); |
|---|
| 44 | TiXmlElement *loopElem = loopsElem->FirstChildElement(); |
|---|
| 45 | TiXmlElement *saveLoopElem = loopElem; |
|---|
| 46 | // get number of loops in station and assign to station.num |
|---|
| 47 | station.num = 0; |
|---|
| 48 | for(loopElem; loopElem; loopElem = loopElem->NextSiblingElement()) |
|---|
| 49 | { |
|---|
| 50 | station.num += 1; |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | // get loopIDS and locations |
|---|
| 54 | long int loopIDS[station.num]; |
|---|
| 55 | char * loopLocs[station.num]; |
|---|
| 56 | int index = 0; |
|---|
| 57 | for(saveLoopElem; saveLoopElem; saveLoopElem = saveLoopElem->NextSiblingElement() ) |
|---|
| 58 | { |
|---|
| 59 | TiXmlElement *subLoopElem = saveLoopElem->FirstChildElement(); |
|---|
| 60 | loopIDS[index] = atoi(subLoopElem->GetText()); |
|---|
| 61 | subLoopElem = subLoopElem->NextSiblingElement(); |
|---|
| 62 | loopLocs[index++] = (char *) subLoopElem->GetText(); |
|---|
| 63 | } |
|---|
| 64 | station.loopID = loopIDS; |
|---|
| 65 | station.loop_loc = loopLocs; |
|---|
| 66 | |
|---|
| 67 | // Data pack ATMS message |
|---|
| 68 | station.length = station.num * 2 + CONTROL_DATA_LEN; |
|---|
| 69 | station.dataPack = msgDataPack(station); |
|---|
| 70 | |
|---|
| 71 | return station; |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | /** |
|---|
| 75 | * Parses a "Line" xml element into an FEP_LINE |
|---|
| 76 | * @param lineElem the xml element |
|---|
| 77 | * @return FEP_LINE |
|---|
| 78 | */ |
|---|
| 79 | FEP_LINE NetworkReader::parseLine(TiXmlElement *lineElem) |
|---|
| 80 | { |
|---|
| 81 | FEP_LINE line; |
|---|
| 82 | TiXmlElement *lineSubElem = lineElem->FirstChildElement(); |
|---|
| 83 | line.lineNum = atoi(lineSubElem->GetText()); |
|---|
| 84 | cout << "Line: " << line.lineNum << endl; |
|---|
| 85 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 86 | line.count = atoi(lineSubElem->GetText()); |
|---|
| 87 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 88 | line.schedule = atoi(lineSubElem->GetText()); |
|---|
| 89 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 90 | line.lineInfo = atoi(lineSubElem->GetText()); |
|---|
| 91 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 92 | line.systemKey = atol(lineSubElem->GetText()); |
|---|
| 93 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 94 | line.globalSeq = atol(lineSubElem->GetText()); |
|---|
| 95 | lineSubElem = lineSubElem->NextSiblingElement(); |
|---|
| 96 | line.schedleSeq = atol(lineSubElem->GetText()); |
|---|
| 97 | |
|---|
| 98 | TiXmlElement *stationsElem = lineSubElem->NextSiblingElement(); |
|---|
| 99 | TiXmlElement *stationElem = stationsElem->FirstChildElement(); |
|---|
| 100 | for(stationElem; stationElem; stationElem = stationElem->NextSiblingElement()) |
|---|
| 101 | { |
|---|
| 102 | stations.push_back(parseStation(stationElem, line)); |
|---|
| 103 | } |
|---|
| 104 | return line; |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | /** |
|---|
| 108 | * Loads FEPLines from a specified xml file |
|---|
| 109 | * @param networkFileName the input xml file |
|---|
| 110 | */ |
|---|
| 111 | void NetworkReader::loadLines(const char * networkFileName) |
|---|
| 112 | { |
|---|
| 113 | // Load network xml file |
|---|
| 114 | TiXmlDocument doc(networkFileName); |
|---|
| 115 | if(!doc.LoadFile()) |
|---|
| 116 | { |
|---|
| 117 | cerr << "TiXmlDocument did not load network file..." << endl; |
|---|
| 118 | return; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | // grab <Network> element |
|---|
| 122 | TiXmlHandle hDoc(&doc); |
|---|
| 123 | TiXmlElement *networkElem = hDoc.FirstChildElement().Element(); |
|---|
| 124 | |
|---|
| 125 | // grab first <Line> element |
|---|
| 126 | TiXmlElement *lineElem = networkElem->FirstChildElement(); |
|---|
| 127 | |
|---|
| 128 | // iterate through each line element to create FEP_LINE list |
|---|
| 129 | for(lineElem; lineElem; lineElem=lineElem->NextSiblingElement()) |
|---|
| 130 | { |
|---|
| 131 | lines.push_back(parseLine(lineElem)); |
|---|
| 132 | } |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | // determine if a loop has data based on lane config data |
|---|
| 136 | bool NetworkReader::DataAvail(char flag, int num) |
|---|
| 137 | { |
|---|
| 138 | int mag, fel; |
|---|
| 139 | |
|---|
| 140 | // find mask value |
|---|
| 141 | if (num == 1) |
|---|
| 142 | mag = 0x01; |
|---|
| 143 | else if (num == 2) |
|---|
| 144 | mag = 0x02; |
|---|
| 145 | else if (num == 3) |
|---|
| 146 | mag = 0x04; |
|---|
| 147 | else if (num == 4) |
|---|
| 148 | mag = 0x08; |
|---|
| 149 | else if (num == 5) |
|---|
| 150 | mag = 0x10; |
|---|
| 151 | else if (num == 6) |
|---|
| 152 | mag = 0x20; |
|---|
| 153 | else if (num == 7) |
|---|
| 154 | mag = 0x40; |
|---|
| 155 | else if (num == 8) |
|---|
| 156 | mag = 0x80; |
|---|
| 157 | |
|---|
| 158 | fel = flag & mag; |
|---|
| 159 | fel = fel >> (num - 1); |
|---|
| 160 | |
|---|
| 161 | if (fel == 1) |
|---|
| 162 | return true; |
|---|
| 163 | else |
|---|
| 164 | return false; |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | // Initializes the LDS_LOOP dataPack with all necessary static data and default dynamic data |
|---|
| 168 | unsigned char * NetworkReader::msgDataPack(LDS_LOOP loop) |
|---|
| 169 | { |
|---|
| 170 | int j; |
|---|
| 171 | // Allocate memory for dataPack |
|---|
| 172 | unsigned char *dataPack = (unsigned char *) malloc(sizeof(unsigned char) * loop.length); |
|---|
| 173 | |
|---|
| 174 | // dataPack 5-8: lane config |
|---|
| 175 | char d5 = 0, d6 = 0, d7 = 0, d8 = 0; |
|---|
| 176 | for (j = 0; j < loop.num; j++) |
|---|
| 177 | { |
|---|
| 178 | for (int k = 0; k < 8; k++) |
|---|
| 179 | { |
|---|
| 180 | if (strcmp(loop.loop_loc[j], dp5[k]) == 0) |
|---|
| 181 | d5 += pow(2, k); |
|---|
| 182 | if (strcmp(loop.loop_loc[j], dp6[k]) == 0) |
|---|
| 183 | d6 += pow(2, k); |
|---|
| 184 | if (strcmp(loop.loop_loc[j], dp7[k]) == 0) |
|---|
| 185 | d7 += pow(2, k); |
|---|
| 186 | if (strcmp(loop.loop_loc[j], dp8[k]) == 0) |
|---|
| 187 | d8 += pow(2, k); |
|---|
| 188 | } |
|---|
| 189 | } |
|---|
| 190 | dataPack[5-1] = d5; |
|---|
| 191 | dataPack[6-1] = d6; |
|---|
| 192 | dataPack[7-1] = d7; |
|---|
| 193 | dataPack[8-1] = d8; |
|---|
| 194 | |
|---|
| 195 | // dataPack 1: Drop number, i.e. station address |
|---|
| 196 | dataPack[1-1] = loop.drop; |
|---|
| 197 | |
|---|
| 198 | // dataPack2 (2 bytes per loop) |
|---|
| 199 | dataPack[2-1] = loop.num * 2 + Fixed_Byte_To_Checksum; |
|---|
| 200 | |
|---|
| 201 | // dataPacket 3 (lowbyte: # of mainline loops, highbyte: # of opposite loops) |
|---|
| 202 | int low = 0, high = 0; |
|---|
| 203 | for (j = 1; j <= 6; j++) |
|---|
| 204 | { |
|---|
| 205 | low += DataAvail(dataPack[5-1], j); |
|---|
| 206 | high += DataAvail(dataPack[6-1], j); |
|---|
| 207 | } |
|---|
| 208 | high = high << 4; |
|---|
| 209 | dataPack[3-1] = high | low; |
|---|
| 210 | |
|---|
| 211 | // dataPack4 (Miscl. flags: samples are: 80, A0, E0, 00) |
|---|
| 212 | dataPack[4-1] = 0xA0; |
|---|
| 213 | |
|---|
| 214 | // dataPack 9: initialized as 00 (meaning no metering); need to be updated every 30 sec |
|---|
| 215 | dataPack[9-1] = 0; |
|---|
| 216 | |
|---|
| 217 | // datadataPack 10-13: lane malfunction? Assuming all functional |
|---|
| 218 | dataPack[10-1] = 0; |
|---|
| 219 | dataPack[11-1] = 0; |
|---|
| 220 | dataPack[12-1] = 0; |
|---|
| 221 | dataPack[13-1] = 0; |
|---|
| 222 | |
|---|
| 223 | // dataPack 14-22: ramp metering data |
|---|
| 224 | // BYTE 16 and 22 need to be updated every 30 sec |
|---|
| 225 | bool found = false; |
|---|
| 226 | for (j = 0; j < loop.num; j++) |
|---|
| 227 | { |
|---|
| 228 | if (strcmp(loop.loop_loc[j], "DEMAND") == 0) |
|---|
| 229 | { |
|---|
| 230 | found = true; |
|---|
| 231 | break; |
|---|
| 232 | } |
|---|
| 233 | } |
|---|
| 234 | if (found) |
|---|
| 235 | { |
|---|
| 236 | // BYTE 14: mostly 07, some are 05, 03, 00 |
|---|
| 237 | dataPack[14-1] = 0x07; |
|---|
| 238 | // mostly 06(TOD table 1); some are 0B (No metering) or 05(traffic responsive) |
|---|
| 239 | dataPack[15-1] = 0x06; |
|---|
| 240 | // most 00, some are 01 (queue override) or 80(Meter ON sign) |
|---|
| 241 | dataPack[16-1] = 0x00; |
|---|
| 242 | // Field Manual Rate |
|---|
| 243 | dataPack[17-1] = 0xFF; |
|---|
| 244 | // TOC Manual Rate |
|---|
| 245 | dataPack[18-1] = 0xFF; |
|---|
| 246 | // PSO Manual Rate |
|---|
| 247 | dataPack[19-1] = 0xFF; |
|---|
| 248 | // CORM Rate |
|---|
| 249 | dataPack[20-1] = 0xFF; |
|---|
| 250 | // Local Responsive Rate. DON'T UNDERSTAND YET |
|---|
| 251 | dataPack[21-1] = 0x00; |
|---|
| 252 | // TOD Rate: need to query RAMP plugin! |
|---|
| 253 | dataPack[22-1] = 0x00; |
|---|
| 254 | } |
|---|
| 255 | // LDS: NO Metering |
|---|
| 256 | else |
|---|
| 257 | { |
|---|
| 258 | dataPack[14-1] = 0x00; |
|---|
| 259 | dataPack[15-1] = 0x0B; |
|---|
| 260 | dataPack[16-1] = 0x00; |
|---|
| 261 | dataPack[17-1] = 0xFF; |
|---|
| 262 | dataPack[18-1] = 0xFF; |
|---|
| 263 | dataPack[19-1] = 0xFF; |
|---|
| 264 | dataPack[20-1] = 0xFF; |
|---|
| 265 | dataPack[21-1] = 0x00; |
|---|
| 266 | dataPack[22-1] = 0x00; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | // dataPack 23-24: sum of mainline/Oppsite traffic data; need to be updated every 30 sec |
|---|
| 270 | loop.MlTotVol = 0; |
|---|
| 271 | loop.OppTotVol = 0; |
|---|
| 272 | dataPack[23-1] = loop.MlTotVol; |
|---|
| 273 | dataPack[24-1] = loop.OppTotVol; |
|---|
| 274 | |
|---|
| 275 | // dataPack 25-26: BYTE 25 is fixed, i.e. 03; BYTE 26 is either 0xA2 or 0x84 |
|---|
| 276 | dataPack[25-1] = 0x03; |
|---|
| 277 | dataPack[26-1] = 0x84; |
|---|
| 278 | |
|---|
| 279 | /* printf("lds=%d (%d), p1=%2X, p2=%2X, p3=%2X, p5=%2X, p6=%X, p7=%X, p8=%2X\n", |
|---|
| 280 | loop.lds, loop.length, dataPack[1-1], dataPack[2-1], |
|---|
| 281 | dataPack[3-1], dataPack[5-1], |
|---|
| 282 | dataPack[6-1], dataPack[7-1], dataPack[8-1]); |
|---|
| 283 | */ |
|---|
| 284 | return dataPack; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | /** |
|---|
| 288 | * Getter for lines |
|---|
| 289 | * @return List of FEP_LINES |
|---|
| 290 | */ |
|---|
| 291 | vector<FEP_LINE> NetworkReader::getLines() |
|---|
| 292 | { |
|---|
| 293 | return lines; |
|---|
| 294 | } |
|---|
| 295 | |
|---|
| 296 | /** |
|---|
| 297 | * Getter for stations |
|---|
| 298 | * @return List of LDS_LOOPs |
|---|
| 299 | */ |
|---|
| 300 | vector<LDS_LOOP> NetworkReader::getStations() |
|---|
| 301 | { |
|---|
| 302 | return stations; |
|---|
| 303 | } |
|---|
| 304 | |
|---|
| 305 | NetworkReader::~NetworkReader() |
|---|
| 306 | { |
|---|
| 307 | |
|---|
| 308 | } |
|---|