result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, SymbolString& master) { ostringstream msg; while (argPos < args.size()) { if ((args[argPos].length() % 2) != 0) { return RESULT_ERR_INVALID_NUM; } msg << args[argPos++]; } if (msg.str().size() < 4*2) // at least ZZ, PB, SB, NN return RESULT_ERR_INVALID_ARG; result_t ret; unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret); if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) return RESULT_ERR_INVALID_ARG; ret = master.push_back(m_address, false); if (ret == RESULT_OK) ret = master.parseHex(msg.str()); if (ret == RESULT_OK && !isValidAddress(master[1])) ret = RESULT_ERR_INVALID_ADDR; return ret; }
result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) { result_t result = RESULT_ERR_NO_SIGNAL; slave.clear(); ActiveBusRequest request(master, slave); logInfo(lf_bus, "send message: %s", master.getDataStr().c_str()); for (int sendRetries = m_failedSendRetries + 1; sendRetries >= 0; sendRetries--) { m_nextRequests.push(&request); bool success = m_finishedRequests.remove(&request, true); result = success ? request.m_result : RESULT_ERR_TIMEOUT; if (result == RESULT_OK) { Message* message = m_messages->find(master); if (message != NULL) m_messages->invalidateCache(message); break; } if (!success || result == RESULT_ERR_NO_SIGNAL || result == RESULT_ERR_SEND || result == RESULT_ERR_DEVICE) { logError(lf_bus, "send to %2.2x: %s, give up", master[1], getResultCode(result)); break; } logError(lf_bus, "send to %2.2x: %s%s", master[1], getResultCode(result), sendRetries>0 ? ", retry" : ""); request.m_busLostRetries = 0; } return result; }
deque<Message*> MessageMap::findAll(SymbolString& master) { deque<Message*> ret; if (master.size() < 5) return ret; unsigned char maxIdLength = master[4]; if (maxIdLength > m_maxIdLength) maxIdLength = m_maxIdLength; if (master.size() < 5+maxIdLength) return ret; for (int idLength = maxIdLength; ret.size()==0 && idLength >= 0; idLength--) { int exp = 7; unsigned long long key = (unsigned long long)idLength << (8 * exp + 5); key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--); key |= (unsigned long long)master[1] << (8 * exp--); key |= (unsigned long long)master[2] << (8 * exp--); key |= (unsigned long long)master[3] << (8 * exp--); for (unsigned char i = 0; i < idLength; i++) key |= (unsigned long long)master[5 + i] << (8 * exp--); map<unsigned long long , vector<Message*> >::iterator it = m_messagesByKey.find(key); if (it != m_messagesByKey.end()) { Message* message = getFirstAvailable(it->second); if (message) ret.push_back(message); } if ((key & ID_SOURCE_MASK) != 0) { key &= ~ID_SOURCE_MASK; it = m_messagesByKey.find(key & ~ID_SOURCE_MASK); // try again without specific source master if (it != m_messagesByKey.end()) { Message* message = getFirstAvailable(it->second); if (message) ret.push_back(message); } } it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_READ); // try again with special value for active read if (it != m_messagesByKey.end()) { Message* message = getFirstAvailable(it->second); if (message) ret.push_back(message); } it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_WRITE); // try again with special value for active write if (it != m_messagesByKey.end()) { Message* message = getFirstAvailable(it->second); if (message) ret.push_back(message); } } return ret; }
result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave) { if (!isValidAddress(dstAddress) || isMaster(dstAddress)) return RESULT_ERR_INVALID_ADDR; m_seenAddresses[dstAddress] |= SCAN_INIT; Message* scanMessage = m_messages->getScanMessage(); if (scanMessage==NULL) { return RESULT_ERR_NOTFOUND; } istringstream input; SymbolString master; result_t result = scanMessage->prepareMaster(m_ownMasterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress); if (result==RESULT_OK) { result = sendAndWait(master, slave); if (result==RESULT_OK) { Message* message = m_messages->getScanMessage(dstAddress); if (message!=NULL && message!=scanMessage) { scanMessage = message; scanMessage->storeLastData(pt_masterData, master, 0); // update the cache, expected to work since this is a clone } } if (result!=RESULT_ERR_NO_SIGNAL) m_seenAddresses[dstAddress] |= SCAN_DONE; } if (result != RESULT_OK || slave.size() == 0) // avoid "invalid position" during decode return result; return scanMessage->storeLastData(pt_slaveData, slave, 0); // update the cache }
result_t Message::decode(SymbolString& masterData, SymbolString& slaveData, ostringstream& output, OutputFormat outputFormat, bool leadingSeparator) { unsigned char offset = (unsigned char)(m_id.size() - 2); size_t startPos = output.str().length(); result_t result = m_data->read(pt_masterData, masterData, offset, output, outputFormat, leadingSeparator, NULL, -1); if (result < RESULT_OK) return result; bool empty = result == RESULT_EMPTY; offset = 0; leadingSeparator |= output.str().length() > startPos; result = m_data->read(pt_slaveData, slaveData, offset, output, outputFormat, leadingSeparator, NULL, -1); if (result < RESULT_OK) return result; if (result == RESULT_EMPTY && !empty) result = RESULT_OK; // OK if at least one part was non-empty time(&m_lastUpdateTime); switch (masterData.compareMaster(m_lastMasterData)) { case 1: // completely different m_lastChangeTime = m_lastUpdateTime; m_lastMasterData = masterData; break; case 2: // only master address is different m_lastMasterData = masterData; break; } if (slaveData != m_lastSlaveData) { m_lastChangeTime = m_lastUpdateTime; m_lastSlaveData = slaveData; } return result; }
result_t Message::decode(const PartType partType, SymbolString& data, ostringstream& output, OutputFormat outputFormat, bool leadingSeparator, const char* fieldName, signed char fieldIndex) { unsigned char offset; if (partType == pt_masterData) offset = (unsigned char)(m_id.size() - 2); else offset = 0; result_t result = m_data->read(partType, data, offset, output, outputFormat, leadingSeparator, fieldName, fieldIndex); if (result < RESULT_OK) return result; if (result == RESULT_EMPTY && fieldName != NULL) return RESULT_ERR_NOTFOUND; time(&m_lastUpdateTime); if (partType == pt_masterData) { switch (data.compareMaster(m_lastMasterData)) { case 1: // completely different m_lastChangeTime = m_lastUpdateTime; m_lastMasterData = data; break; case 2: // only master address is different m_lastMasterData = data; break; } } else if (partType == pt_slaveData) { if (data != m_lastSlaveData) { m_lastChangeTime = m_lastUpdateTime; m_lastSlaveData = data; } } return result; }
result_t SingleDataField::read(const PartType partType, SymbolString& data, unsigned char offset, unsigned int& output, const char* fieldName, signed char fieldIndex) { if (partType != m_partType) return RESULT_EMPTY; switch (m_partType) { case pt_masterData: offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN break; case pt_slaveData: offset++; // skip NN break; default: return RESULT_ERR_INVALID_PART; } bool remainder = m_length==REMAIN_LEN && m_dataType->isAdjustableLength(); if (offset + (remainder?1:m_length) > data.size()) { return RESULT_ERR_INVALID_POS; } if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { return RESULT_EMPTY; } return m_dataType->readRawValue(data, offset, m_length, output); }
Result* get_handler(SEXP call, const ILazySubsets& subsets, const Environment& env) { LOG_INFO << "Looking up hybrid handler for call of type " << type2name(call); if (TYPEOF(call) == LANGSXP) { int depth = Rf_length(call); HybridHandlerMap& handlers = get_handlers(); SEXP fun_symbol = CAR(call); if (TYPEOF(fun_symbol) != SYMSXP) { LOG_VERBOSE << "Not a function: " << type2name(fun_symbol); return 0; } LOG_VERBOSE << "Searching hybrid handler for function " << CHAR(PRINTNAME(fun_symbol)); HybridHandlerMap::const_iterator it = handlers.find(fun_symbol); if (it == handlers.end()) { LOG_VERBOSE << "Not found"; return 0; } LOG_INFO << "Using hybrid handler for " << CHAR(PRINTNAME(fun_symbol)); return it->second(call, subsets, depth - 1); } else if (TYPEOF(call) == SYMSXP) { SymbolString name = SymbolString(Symbol(call)); LOG_VERBOSE << "Searching hybrid handler for symbol " << name.get_cstring(); if (subsets.count(name)) { LOG_VERBOSE << "Using hybrid variable handler"; return variable_handler(subsets, name); } else { SEXP data = env.find(name.get_string()); // Constants of length != 1 are handled via regular evaluation if (Rf_length(data) == 1) { LOG_VERBOSE << "Using hybrid constant handler"; return constant_handler(data); } } } else { // TODO: perhaps deal with SYMSXP separately if (Rf_length(call) == 1) return constant_handler(call); } return 0; }
bool ActiveBusRequest::notify(result_t result, SymbolString& slave) { if (result == RESULT_OK) logDebug(lf_bus, "read res: %s", slave.getDataStr().c_str()); m_result = result; m_slave.addAll(slave); return false; }
result_t DataFieldSet::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, OutputFormat outputFormat, signed char outputIndex, bool leadingSeparator, const char* fieldName, signed char fieldIndex) { bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; if (!m_uniqueNames && outputIndex<0) outputIndex = 0; for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; if (partType != pt_any && field->getPartType() != partType) { if (outputIndex>=0 && !field->isIgnored()) outputIndex++; continue; } if (!previousFullByteOffset && !field->hasFullByteOffset(false)) offset--; result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex); if (result < RESULT_OK) return result; offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); previousFullByteOffset = field->hasFullByteOffset(true); if (result != RESULT_EMPTY) { found = true; leadingSeparator = true; } if (findFieldIndex && fieldName == field->getName()) { if (fieldIndex == 0) { if (!found) return RESULT_ERR_NOTFOUND; break; } fieldIndex--; } if (outputIndex>=0 && !field->isIgnored()) outputIndex++; } if (!found) { return RESULT_EMPTY; } if ((outputFormat & OF_COMMENTS) && m_comment.length() > 0) { if (outputFormat & OF_JSON) { output << ",\"comment\": \"" << m_comment << '"'; } else { output << " [" << m_comment << "]"; } } return RESULT_OK; }
result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& masterData, istringstream& input, char separator, const unsigned char dstAddress) { if (m_isPassive) return RESULT_ERR_INVALID_ARG; // prepare not possible SymbolString master(false); result_t result = master.push_back(srcAddress, false, false); if (result != RESULT_OK) return result; if (dstAddress == SYN) { if (m_dstAddress == SYN) return RESULT_ERR_INVALID_ADDR; result = master.push_back(m_dstAddress, false, false); } else result = master.push_back(dstAddress, false, false); if (result != RESULT_OK) return result; result = master.push_back(m_id[0], false, false); if (result != RESULT_OK) return result; result = master.push_back(m_id[1], false, false); if (result != RESULT_OK) return result; unsigned char addData = m_data->getLength(pt_masterData); result = master.push_back((unsigned char)(m_id.size() - 2 + addData), false, false); if (result != RESULT_OK) return result; for (size_t i = 2; i < m_id.size(); i++) { result = master.push_back(m_id[i], false, false); if (result != RESULT_OK) return result; } result = m_data->write(input, pt_masterData, master, (unsigned char)(m_id.size() - 2), separator); if (result != RESULT_OK) return result; time(&m_lastUpdateTime); switch (master.compareMaster(m_lastMasterData)) { case 1: // completely different m_lastChangeTime = m_lastUpdateTime; m_lastMasterData = master; break; case 2: // only master address is different m_lastMasterData = master; break; } masterData.addAll(master); return result; }
result_t DataFieldSet::read(const PartType partType, SymbolString& data, unsigned char offset, unsigned int& output, const char* fieldName, signed char fieldIndex) { bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; if (partType != pt_any && field->getPartType() != partType) continue; if (!previousFullByteOffset && !field->hasFullByteOffset(false)) offset--; result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex); if (result < RESULT_OK) return result; offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); previousFullByteOffset = field->hasFullByteOffset(true); if (result != RESULT_EMPTY) { found = true; } if (findFieldIndex && fieldName == field->getName()) { if (fieldIndex == 0) { if (!found) return RESULT_ERR_NOTFOUND; break; } fieldIndex--; } } if (!found) { return RESULT_EMPTY; } return RESULT_OK; }
result_t Message::prepareSlave(SymbolString& slaveData) { if (!m_isPassive || m_isWrite) return RESULT_ERR_INVALID_ARG; // prepare not possible SymbolString slave(false); unsigned char addData = m_data->getLength(pt_slaveData); result_t result = slave.push_back(addData, false, false); if (result != RESULT_OK) return result; istringstream input; // TODO create input from database of internal variables result = m_data->write(input, pt_slaveData, slave, 0); if (result != RESULT_OK) return result; time(&m_lastUpdateTime); if (slave != m_lastSlaveData) { m_lastChangeTime = m_lastUpdateTime; m_lastSlaveData = slave; } slaveData.addAll(slave); return result; }
int main() { // message: [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields... // field: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]] // template: name,type[:len][,[divisor|values][,[unit][,[comment]]]] // condition: name,circuit,messagename,[comment],[fieldname],[ZZ],values string checks[][5] = { // "message", "decoded", "master", "slave", "flags" {"date,HDA:3,,,Datum", "", "", "", "template"}, {"time,VTI,,,", "", "", "", "template"}, {"dcfstate,UCH,0=nosignal;1=ok;2=sync;3=valid,,", "", "", "", "template"}, {"temp,D2C,,°C,Temperatur", "", "", "", "template"}, {"temp1,D1C,,°C,Temperatur", "", "", "", "template"}, {"temp2,D2B,,°C,Temperatur", "", "", "", "template"}, {"power,UCH,,kW", "", "", "", "template"}, {"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "template"}, {"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"}, {"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"}, {"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate","28.0;24.0;4.938;35.0;41.0;4","ff08b5110101","093830f00446520400ff","d"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00},\n \"sensor\": {\"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"}, {"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor", "\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"}, {"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"}, {"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""}, {"w,,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", "m"}, {"w,,first,,,15,b509", "", "ff15b50900", "00", "m"}, {"w,,,,,,b505,2d", "", "", "", "defaults"}, {"w,,offset,,,50,,,,,temp", "0.50", "ff50b505042d080000", "00", "md"}, {"r,ehp,time,,,08,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md"}, {"r,ehp,time,,,08;10,b509,0d2800,,,time", "", "", "", "c"}, {"r,ehp,time,,,08;09,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md*"}, {"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"}, {"r,700,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"}, {"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"}, {"", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"}, {"", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"}, {"w,700,date,,,15,b524,020000003400,,,date", "23.11.2015", "ff15b52409020000003400170b0f", "00", "m"}, {"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "3;15:00:17", "ff08b509040d280003", "0311000f", "mdi"}, {"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f", "mD"}, {"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"}, {"uw,ehp,test,Test,,08,B5de,ab,,,power,,,,,s,hex:1", "8;39", "1008b5de02ab08", "0139", "pm"}, {"u,ehp,hwTankTemp,Speichertemperatur IST,,25,B509,290000,,,IGN:2,,,,,,tempsensor", "","","","M"}, {"", "55.50;ok","1025b50903290000","050000780300","d"}, {"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2", "valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" }, {"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, {"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, {"r,ehp,ApplianceCode,,,08,b509,0d4301,,,UCH,", "9", "ff08b509030d4301", "0109", "d" }, {"r,ehp,,,,08,b509,0d", "", "", "", "defaults" }, {"w,ehp,,,,08,b509,0e", "", "", "", "defaults" }, {"[brinetowater],ehp,ApplianceCode,,,,4;6;8;9;10", "", "", "", "condition" }, {"[airtowater]r,ehp,notavailable,,,,,0100,,,uch", "1", "", "", "c" }, {"[brinetowater]r,ehp,available,,,,,0100,,,uch", "1", "ff08b509030d0100", "0101", "d" }, {"r,,x,,,,,\"6800\",,,UCH,,,bit0=\"comment, continued comment", "", "", "", "c" }, {"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]", "ff08b509030d6800", "0101", "mD" }, {"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" }, {"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02", "084142434445464748;054b4c4d4e4f;02494a", "mdC" }, {"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" }, {"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" }, {"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8", "ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127", "09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" }, }; templates = std::make_unique<DataFieldTemplates>(); auto messages = std::make_unique<MessageMap>(); vector< vector<string> > defaultsRows; map<string, Condition*> &conditions = messages->getConditions(); shared_ptr<Message> message = NULL; vector<shared_ptr<Message>> deleteMessages; vector<std::unique_ptr<SymbolString>> mstrs; vector<std::unique_ptr<SymbolString>> sstrs; mstrs.resize(1); sstrs.resize(1); for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) { auto check = checks[i]; string inputStr = check[1]; string flags = check[4]; bool isTemplate = flags == "template"; bool isCondition = flags == "condition"; bool isDefaults = isCondition || flags == "defaults"; bool dontMap = flags.find('m') != string::npos; bool onlyMap = flags.find('M') != string::npos; bool failedCreate = flags.find('c') != string::npos; bool isChain = flags.find('C') != string::npos; bool decodeJson = flags.find('j') != string::npos || flags.find('J') != string::npos; bool decodeVerbose = flags.find('D') != string::npos || flags.find('J') != string::npos; bool decode = decodeJson || decodeVerbose || (flags.find('d') != string::npos); bool failedPrepare = flags.find('p') != string::npos; bool failedPrepareMatch = flags.find('P') != string::npos; bool multi = flags.find('*') != string::npos; bool withInput = flags.find('i') != string::npos; result_t result = RESULT_EMPTY; if (isChain) { size_t pos = 0; string token; istringstream stream(check[2]); while (getline(stream, token, VALUE_SEPARATOR)) { if (pos >= mstrs.size()) mstrs.resize(pos+1); mstrs[pos] = std::make_unique<SymbolString>(false); result = mstrs[pos]->parseHex(token); if (result != RESULT_OK) { cout << "\"" << check[0] << "\": parse \"" << token << "\" error: " << getResultCode(result) << endl; break; } pos++; } pos = 0; stream.str(check[3]); stream.clear(); while (getline(stream, token, VALUE_SEPARATOR)) { if (pos >= sstrs.size()) sstrs.resize(pos+1); sstrs[pos] = std::make_unique<SymbolString>(false); result = sstrs[pos]->parseHex(token); if (result != RESULT_OK) { cout << "\"" << check[0] << "\": parse \"" << token << "\" error: " << getResultCode(result) << endl; break; } pos++; } if (result != RESULT_OK) continue; } else { mstrs[0] = std::make_unique<SymbolString>(true); result = mstrs[0]->parseHex(check[2]); if (result != RESULT_OK) { cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl; continue; } sstrs[0] = std::make_unique<SymbolString>(true); result = sstrs[0]->parseHex(check[3]); if (result != RESULT_OK) { cout << "\"" << check[0] << "\": parse \"" << check[3] << "\" error: " << getResultCode(result) << endl; continue; } } vector<string> entries; istringstream ifs(check[0]); unsigned int lineNo = 0; if (!FileReader::splitFields(ifs, entries, lineNo)) { entries.clear(); } deleteMessages.clear(); if (isTemplate) { // store new template shared_ptr<DataField> fields; auto it = entries.begin(); result = DataField::create(it, entries.end(), templates.get(), fields, false, true, false); if (result != RESULT_OK) cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl; else if (it != entries.end()) { cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl; } else { cout << "\"" << check[0] << "\": create template OK" << endl; result = templates->add(fields, "", true); if (result == RESULT_OK) cout << " store template OK" << endl; else { cout << " store template error: " << getResultCode(result) << endl; } } continue; } if (isDefaults) { // store defaults or condition vector<string>::iterator it = entries.begin(); size_t oldSize = conditions.size(); result = messages->addDefaultFromFile(defaultsRows, entries, it, "", "", "", "no file", 1); if (result != RESULT_OK) cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl; else if (it != entries.end()) cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl; else { cout << "\"" << check[0] << "\": read defaults OK" << endl; if (isCondition) { if (conditions.size()==oldSize) { cout << " create condition error" << endl; } else { result = messages->resolveConditions(); if (result != RESULT_OK) cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl; else cout << " resolve conditions OK" << endl; } } } continue; } if (entries.size() == 0) { message = messages->find(*mstrs[0]); if (message == NULL) { cout << "\"" << check[2] << "\": find error: NULL" << endl; continue; } cout << "\"" << check[2] << "\": find OK" << endl; } else { auto it = entries.begin(); string types = *it; Condition* condition = NULL; result = messages->readConditions(types, "no file", condition); if (result==RESULT_OK) { *it = types; result = Message::create(it, entries.end(), &defaultsRows, condition, "no file", templates.get(), deleteMessages); } if (failedCreate) { if (result == RESULT_OK) cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl; else cout << "\"" << check[0] << "\": failed create OK" << endl; continue; } if (result != RESULT_OK) { cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl; printErrorPos(cout, entries.begin(), entries.end(), it, "", 0, result); continue; } if (deleteMessages.size()==0) { cout << "\"" << check[0] << "\": create error: NULL" << endl; continue; } if (it != entries.end()) { cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl; continue; } if (multi && deleteMessages.size()==1) { cout << "\"" << check[0] << "\": create error: single message instead of multiple" << endl; continue; } if (!multi && deleteMessages.size()>1) { cout << "\"" << check[0] << "\": create error: multiple messages instead of single" << endl; continue; } cout << "\"" << check[0] << "\": create OK" << endl; if (!dontMap) { result_t result = RESULT_OK; for (auto msgToDelete : deleteMessages) { auto deleteMessage = msgToDelete; result_t result = messages->add(deleteMessage); if (result != RESULT_OK) { cout << "\"" << check[0] << "\": add error: " << getResultCode(result) << endl; break; } } if (result != RESULT_OK) continue; cout << " map OK" << endl; message = deleteMessages.front(); deleteMessages.clear(); if (onlyMap) continue; auto foundMessage = messages->find(*mstrs[0]); if (foundMessage == message) cout << " find OK" << endl; else if (foundMessage == NULL) cout << " find error: NULL" << endl; else cout << " find error: different" << endl; } else message = deleteMessages.front(); } if (message->isPassive() || decode) { ostringstream output; for (unsigned char index=0; index<message->getCount(); index++) { message->storeLastData(*mstrs[index], *sstrs[index]); } result = message->decodeLastData(output, (decodeVerbose?OF_VERBOSE:0)|(decodeJson?OF_JSON:0), false); if (result != RESULT_OK) { cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: " << getResultCode(result) << endl; continue; } cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode OK" << endl; bool match = inputStr == output.str(); verify(false, "decode", check[2] + "/" + check[3], match, inputStr, output.str()); } if (!message->isPassive() && (withInput || !decode)) { istringstream input(inputStr); SymbolString writeMstr; result = message->prepareMaster(0xff, writeMstr, input); if (failedPrepare) { if (result == RESULT_OK) cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl; else cout << " \"" << inputStr << "\": failed prepare OK" << endl; continue; } if (result != RESULT_OK) { cout << " \"" << inputStr << "\": prepare error: " << getResultCode(result) << endl; continue; } cout << " \"" << inputStr << "\": prepare OK" << endl; bool match = writeMstr==*mstrs[0]; verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(), writeMstr.getDataStr()); } } deleteMessages.clear(); return 0; }
result_t SingleDataField::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, OutputFormat outputFormat, signed char outputIndex, bool leadingSeparator, const char* fieldName, signed char fieldIndex) { if (partType != m_partType) { return RESULT_OK; } switch (m_partType) { case pt_masterData: offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN break; case pt_slaveData: offset++; // skip NN break; default: return RESULT_ERR_INVALID_PART; } bool remainder = m_length==REMAIN_LEN && m_dataType->isAdjustableLength(); if (offset + (remainder?1:m_length) > data.size()) { return RESULT_ERR_INVALID_POS; } if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { return RESULT_EMPTY; } if (outputFormat & OF_JSON) { if (leadingSeparator) { output << ","; } if (outputIndex>=0 || m_name.empty() || !(outputFormat & OF_NAMES)) { output << "\n \"" << static_cast<signed int>(outputIndex<0?0:outputIndex) << "\": {\"name\": \"" << m_name << "\"" << ", \"value\": "; } else { output << "\n \"" << m_name << "\": {\"value\": "; } } else { if (leadingSeparator) { output << UI_FIELD_SEPARATOR; } if (outputFormat & OF_NAMES) { output << m_name << "="; } } result_t result = readSymbols(data, m_partType==pt_masterData, offset, output, outputFormat); if (result != RESULT_OK) { return result; } if ((outputFormat & OF_UNITS) && m_unit.length() > 0) { if (outputFormat & OF_JSON) { output << ", \"unit\": \"" << m_unit << '"'; } else { output << " " << m_unit; } } if ((outputFormat & OF_COMMENTS) && m_comment.length() > 0) { if (outputFormat & OF_JSON) { output << ", \"comment\": \"" << m_comment << '"'; } else { output << " [" << m_comment << "]"; } } if (outputFormat & OF_JSON) { output << "}"; } return RESULT_OK; }
// execute script static inline int script_main(int argc, char** argv) { if(argc<=1) { usage(argv[0]); return -1; } bool bShowSymbols = 0; bool bInteractive = 0; unsigned int uiDebugLevel = 3; #ifndef NDEBUG uiDebugLevel = 4; #endif unsigned int iStartArg = 1; for(iStartArg=1; iStartArg<unsigned(argc); ++iStartArg) { t_string strArg = STR_TO_WSTR(argv[iStartArg]); tl::trim(strArg); // end of arguments to hermelin if(strArg[0] != T_STR'-') break; if(strArg=="-s" || strArg == "--symbols") bShowSymbols = 1; else if(strArg=="-i" || strArg == "--interactive") bInteractive = 1; else if(strArg=="-h" || strArg == "--help") { usage(argv[0]); return 0; } else if(strArg=="-d0") uiDebugLevel = 0; else if(strArg=="-d1") uiDebugLevel = 1; else if(strArg=="-d2") uiDebugLevel = 2; else if(strArg=="-d3") uiDebugLevel = 3; else if(strArg=="-d4") uiDebugLevel = 4; } const std::array<tl::Log*, 5> arrLogs{{&tl::log_crit, &tl::log_err, &tl::log_warn, &tl::log_info, &tl::log_debug}}; for(unsigned int iLog=0; iLog<arrLogs.size(); ++iLog) arrLogs[iLog]->SetEnabled(uiDebugLevel>=iLog); // debug in script.yy needs to be set yydebug = (uiDebugLevel>=4); if(bInteractive) return interactive(bShowSymbols, uiDebugLevel); if(iStartArg >= unsigned(argc)) { tl::log_err("No input file given."); return -1; } // loading of input file const char* pcFile = argv[iStartArg]; t_string strFile = STR_TO_WSTR(pcFile); t_char* pcInput = load_file(pcFile); if(!pcInput) return -2; ParseObj par; ParseInfo info; RuntimeInfo runinfo; info.bEnableDebug = (uiDebugLevel>=4); // lexing par.strCurFile = strFile; par.pLexer = new Lexer(pcInput, strFile.c_str()); delete[] pcInput; pcInput = 0; if(!par.pLexer->IsOk()) { tl::log_err("Lexer returned with errors."); return -3; } init_global_syms(info.pGlobalSyms); // parsing int iParseRet = yyparse(&par); delete par.pLexer; par.pLexer = 0; if(iParseRet != 0) { tl::log_err("Parser returned with error code ", iParseRet, "."); return -4; } // optimizing par.pRoot = par.pRoot->optimize(); // executing SymbolArray *parrMainArgs = new SymbolArray(); for(int iArg=iStartArg; iArg<argc; ++iArg) { SymbolString *pSymArg = new SymbolString(); pSymArg->SetVal(STR_TO_WSTR(argv[iArg])); parrMainArgs->GetArr().push_back(pSymArg); } //std::vector<Symbol*> vecMainArgs = { &arrMainArgs }; SymbolTable *pTableSup = new SymbolTable(); info.pmapModules->insert(ParseInfo::t_mods::value_type(strFile, par.pRoot)); runinfo.strExecFkt = T_STR"main"; //info.pvecExecArg = &vecMainArgs; runinfo.strInitScrFile = strFile; SymbolArray arrMainArgs; arrMainArgs.GetArr().push_back(parrMainArgs); pTableSup->InsertSymbol(T_STR"<args>", &arrMainArgs); par.pRoot->eval(info, runinfo, pTableSup); pTableSup->RemoveSymbolNoDelete(T_STR"<args>"); delete pTableSup; if(bShowSymbols) { tl::log_info("================================================================================"); tl::log_info("Global symbols:"); info.pGlobalSyms->print(); std::ostringstream ostrFkts; for(const NodeFunction* pFunc : info.vecFuncs) ostrFkts << pFunc->GetName() << ", "; tl::log_info("Script functions: ", ostrFkts.str()); const t_mapFkts* pExtFkts = get_ext_calls(); std::ostringstream ostrSysFkts; for(const auto& fktpair : *pExtFkts) ostrSysFkts << fktpair.first << ", "; tl::log_info("System functions: ", ostrSysFkts.str()); tl::log_info("================================================================================"); } return 0; }
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile) { PartType partType; if (isMaster(address)) { address = (unsigned char)(data[0]+5); // slave address of sending master partType = pt_masterData; if (data.size()<5+1+5+2+2) // skip QQ ZZ PB SB NN return RESULT_EMPTY; } else { partType = pt_slaveData; if (data.size()<1+1+5+2+2) // skip NN return RESULT_EMPTY; } DataFieldSet* identFields = DataFieldSet::getIdentFields(); // MANUFACTURER/ZZ. ( C.S.H., C.H., C.S., S.H., C., S., H., "" ) .*csv string path, prefix, ident, sw, hw; // path: cfgpath/MANUFACTURER, prefix: ZZ., ident: C[C[C[C[C]]]], sw: xxxx, hw: xxxx ostringstream out; unsigned char offset = 0; size_t field = 0; result_t result = (*identFields)[field]->read(partType, data, offset, out, 0); // manufacturer name if (result==RESULT_ERR_NOTFOUND) result = (*identFields)[field]->read(partType, data, offset, out, OF_NUMERIC); // manufacturer name if (result==RESULT_OK) { path = out.str(); transform(path.begin(), path.end(), path.begin(), ::tolower); path = string(opt.configPath) + "/" + path; out.str(""); out << setw(2) << hex << setfill('0') << nouppercase << static_cast<unsigned>(address) << "."; prefix = out.str(); out.str(""); out.clear(); offset = (unsigned char)(offset+(*identFields)[field++]->getLength(partType)); result = (*identFields)[field]->read(partType, data, offset, out, 0); // identification string } if (result==RESULT_OK) { ident = out.str(); out.str(""); offset = (unsigned char)(offset+(*identFields)[field++]->getLength(partType)); result = (*identFields)[field]->read(partType, data, offset, out, 0); // software version number } if (result==RESULT_OK) { sw = out.str(); out.str(""); offset = (unsigned char)(offset+(*identFields)[field++]->getLength(partType)); result = (*identFields)[field]->read(partType, data, offset, out, 0); // hardware version number } if (result!=RESULT_OK) { logDebug(lf_main, "load scan config files: %s", getResultCode(result)); return result; } vector<string> files; bool hasTemplates = false; if (result==RESULT_OK) { hw = out.str(); result = collectConfigFiles(path, prefix, ".csv", files, NULL, &hasTemplates); } logDebug(lf_main, "found %d matching scan config files from %s with prefix %s: %s", files.size(), path.c_str(), prefix.c_str(), getResultCode(result)); if (result!=RESULT_OK) return result; if (files.empty()) return RESULT_ERR_NOTFOUND; // complete name: cfgpath/MANUFACTURER/ZZ[.C[C[C[C[C]]]]][.SWxxxx][.HWxxxx][.*].csv for (string::iterator it = ident.begin(); it!=ident.end(); it++) { if (::isspace(*it)) { ident.erase(it--); } else { *it = (char)::tolower(*it); } } size_t prefixLen = path.length()+1+prefix.length()-1; size_t bestMatch = 0; string best; for (vector<string>::iterator it = files.begin(); it!=files.end(); it++) { string name = *it; name = name.substr(prefixLen, name.length()-prefixLen+1-strlen(".csv")); // .*. size_t match = 1; if (name.length()>2) { // more than just "." size_t pos = name.rfind(".SW"); // check for ".SWxxxx." if (pos!=string::npos && name.find(".", pos+1)==pos+7) { if (name.substr(pos+3, 4)==sw) match += 6; else { continue; // SW mismatch } } pos = name.rfind(".HW"); // check for ".HWxxxx." if (pos!=string::npos && name.find(".", pos+1)==pos+7) { if (name.substr(pos+3, 4)==hw) match += 6; else { continue; // HW mismatch } } pos = name.find(".", 1); // check for ".C[C[C[C[C]]]]." if (ident.length()>0 && pos!=string::npos && pos>1 && pos<=6) { // up to 5 chars between two "."s, immediately after "ZZ." string check = name.substr(1, pos-1); string remain = ident; bool matches = false; while (remain.length()>0 && remain.length()>=check.length()) { if (check==remain) { matches = true; break; } if (remain[remain.length()-1]!='0') break; remain.erase(remain.length()-1); } if (matches) match += remain.length(); else { continue; // IDENT mismatch } } } if (match>=bestMatch) { bestMatch = match; best = *it; } } if (best.length()==0) return RESULT_ERR_NOTFOUND; // found the right file. load the templates if necessary, then load the file itself bool readCommon = false; DataFieldTemplates* templates = getTemplates(path, ".csv", hasTemplates, false, &readCommon); if (readCommon) { result = collectConfigFiles(path, "", ".csv", files); if (result==RESULT_OK && !files.empty()) { for (vector<string>::iterator it = files.begin(); it!=files.end(); it++) { string name = *it; name = name.substr(path.length()+1, name.length()-path.length()-strlen(".csv")); // *. if (name=="_templates.") // skip templates continue; if (name.length()<3 || name.find_first_of('.')!=2) { // different from the scheme "ZZ." name = *it; result = messages->readFromFile(name, templates); if (result==RESULT_OK) logNotice(lf_main, "read common config file %s for scan %s", name.c_str(), ident.c_str()); else logError(lf_main, "error reading common config file %s for scan %s: %s", name.c_str(), ident.c_str(), getResultCode(result)); } } } } result = messages->readFromFile(best, templates); if (result!=RESULT_OK) { logError(lf_main, "error reading config file %s for scan %s: %s", best.c_str(), ident.c_str(), getResultCode(result)); return result; } logNotice(lf_main, "read config file %s for scan %s", best.c_str(), ident.c_str()); result = messages->resolveConditions(false); if (result != RESULT_OK) logError(lf_main, "error resolving conditions: %s, %s", getResultCode(result), messages->getLastError().c_str()); logNotice(lf_main, "found messages: %d (%d conditional on %d conditions, %d poll, %d update)", messages->size(), messages->sizeConditional(), messages->sizeConditions(), messages->sizePoll(), messages->sizePassive()); relativeFile = best.substr(strlen(opt.configPath)+1); return RESULT_OK; }
SEXP mutate_grouped(const DataFrame& df, const QuosureList& dots) { LOG_VERBOSE << "checking zero rows"; // special 0 rows case if (df.nrows() == 0) { DataFrame res = mutate_not_grouped(df, dots); copy_vars(res, df); set_class(res, get_class(df)); return Data(res).data(); } LOG_VERBOSE << "initializing proxy"; typedef GroupedCallProxy<Data, Subsets> Proxy; Data gdf(df); int nexpr = dots.size(); check_not_groups(dots, gdf); Proxy proxy(gdf); LOG_VERBOSE << "copying data to accumulator"; NamedListAccumulator<Data> accumulator; int ncolumns = df.size(); CharacterVector column_names = df.names(); for (int i = 0; i < ncolumns; i++) { accumulator.set(column_names[i], df[i]); } LOG_VERBOSE << "processing " << nexpr << " variables"; List variables(nexpr); for (int i = 0; i < nexpr; i++) { Rcpp::checkUserInterrupt(); const NamedQuosure& quosure = dots[i]; Environment env = quosure.env(); Shield<SEXP> call_(quosure.expr()); SEXP call = call_; SymbolString name = quosure.name(); proxy.set_env(env); LOG_VERBOSE << "processing " << name.get_utf8_cstring(); if (TYPEOF(call) == LANGSXP || TYPEOF(call) == SYMSXP) { proxy.set_call(call); boost::scoped_ptr<Gatherer> gather(gatherer<Data, Subsets>(proxy, gdf, name)); SEXP variable = variables[i] = gather->collect(); proxy.input(name, variable); accumulator.set(name, variable); } else if (Rf_length(call) == 1) { boost::scoped_ptr<Gatherer> gather(constant_gatherer(call, gdf.nrows())); SEXP variable = variables[i] = gather->collect(); proxy.input(name, variable); accumulator.set(name, variable); } else if (Rf_isNull(call)) { accumulator.rm(name); continue; } else { stop("cannot handle"); } } return structure_mutate(accumulator, df, get_class(df)); }
// nthread(iNumThreads, strFunc, vecArgs, ...) static Symbol* fkt_nthread(const std::vector<Symbol*>& vecSyms, ParseInfo& info, RuntimeInfo &runinfo, SymbolTable* pSymTab) { if(vecSyms.size()<3) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "nthread needs at least 3 arguments: N, func, arg." << std::endl; throw tl::Err(ostrErr.str(),0); } Symbol* _pSymN = vecSyms[0]; if(_pSymN->GetType() != SYMBOL_INT) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Number of threads has to be integer." << std::endl; throw tl::Err(ostrErr.str(),0); } SymbolInt *pSymN = (SymbolInt*)_pSymN; t_int iNumThreads = pSymN->GetVal(); Symbol* _pSymIdent = vecSyms[1]; if(_pSymIdent->GetType() != SYMBOL_STRING) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc identifier needs to be a string." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolString *pSymIdent = (SymbolString*)_pSymIdent; const t_string& strIdent = pSymIdent->GetVal(); Symbol* _pSymArr = vecSyms[2]; if(_pSymArr->GetType() != SYMBOL_ARRAY) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread arg has to be an array." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolArray *pSymArr = (SymbolArray*)_pSymArr; const std::vector<Symbol*>& vecArr = pSymArr->GetArr(); NodeFunction* pFunc = info.GetFunction(strIdent); if(pFunc == 0) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc \"" << strIdent << "\" not defined." << std::endl; throw tl::Err(ostrErr.str(), 0); } if(iNumThreads > int(vecArr.size())) { iNumThreads = vecArr.size(); tl::log_warn(linenr(runinfo), "More threads requested in nthread than necessary, ", "reducing to array size (", iNumThreads, ")."); } std::vector<SymbolArray*> vecSymArrays; vecSymArrays.resize(iNumThreads); t_int iCurTh = 0; for(Symbol* pThisSym : vecArr) { if(!vecSymArrays[iCurTh]) vecSymArrays[iCurTh] = new SymbolArray(); vecSymArrays[iCurTh]->GetArr().push_back(pThisSym->clone()); vecSymArrays[iCurTh]->UpdateLastNIndices(1); ++iCurTh; if(iCurTh == iNumThreads) iCurTh = 0; } std::vector<std::thread*> vecThreads; vecThreads.reserve(iNumThreads); for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { std::vector<Symbol*>* vecThreadSyms = new std::vector<Symbol*>; vecThreadSyms->reserve(vecSyms.size()-3+1); vecThreadSyms->push_back(vecSymArrays[iCurTh]); for(unsigned int iSym=3; iSym<vecSyms.size(); ++iSym) vecThreadSyms->push_back(vecSyms[iSym]->clone()); std::thread *pth = new std::thread(::thread_proc, pFunc, &info, vecThreadSyms); vecThreads.push_back(pth); } /* // automatically join for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { vecThreads[iCurTh]->join(); delete vecThreads[iCurTh]; vecThreads[iCurTh] = 0; }*/ SymbolArray* pArrThreads = new SymbolArray(); for(iCurTh=0; iCurTh<iNumThreads; ++iCurTh) { std::thread* pCurThread = vecThreads[iCurTh]; t_int iHandle = info.phandles->AddHandle(new HandleThread(pCurThread)); SymbolInt *pSymThreadHandle = new SymbolInt(iHandle); pArrThreads->GetArr().push_back(pSymThreadHandle); } pArrThreads->UpdateIndices(); return pArrThreads; }
static Symbol* fkt_thread_task(const std::vector<Symbol*>& vecSyms, ParseInfo& info, RuntimeInfo &runinfo, SymbolTable* pSymTab, bool bTask=0) { if(vecSyms.size()<1) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Need thread proc identifier." << std::endl; throw tl::Err(ostrErr.str(), 0); } Symbol* _pSymIdent = vecSyms[0]; if(_pSymIdent->GetType() != SYMBOL_STRING) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc identifier needs to be a string." << std::endl; throw tl::Err(ostrErr.str(), 0); } SymbolString *pSymIdent = (SymbolString*)_pSymIdent; const t_string& strIdent = pSymIdent->GetVal(); NodeFunction* pFunc = info.GetFunction(strIdent); if(pFunc == 0) { std::ostringstream ostrErr; ostrErr << linenr(runinfo) << "Thread proc \"" << strIdent << "\" not defined." << std::endl; throw tl::Err(ostrErr.str(), 0); } std::vector<Symbol*>* vecThreadSymsClone = clone_symbols(&vecSyms, 1); t_int iHandle = -1; if(bTask) { bool bIsThread = 1; std::launch policy = std::launch::async /*| std::launch::deferred*/; unsigned int iNumThreads = info.phandles->CountAllThreads(); //log_debug("Number of threads running: ", iNumThreads); // start deferred if(iNumThreads >= std::thread::hardware_concurrency()) { bIsThread = 0; // let system decide policy |= std::launch::deferred; //log_debug("starting (probably) deferred"); } //else log_debug("starting as thread"); std::future<Symbol*> *pFuture = new std::future<Symbol*>( std::async(policy, ::task_proc, pFunc, &info, vecThreadSymsClone)); iHandle = info.phandles->AddHandle(new HandleTask(pFuture, bIsThread)); } else { std::thread* pThread = new std::thread(::thread_proc, pFunc, &info, vecThreadSymsClone); iHandle = info.phandles->AddHandle(new HandleThread(pThread)); } return new SymbolInt(iHandle); }
void BusHandler::receiveCompleted() { unsigned char srcAddress = m_command[0], dstAddress = m_command[1]; if (srcAddress == dstAddress) { logError(lf_bus, "invalid self-addressed message from %2.2x", srcAddress); return; } addSeenAddress(srcAddress); addSeenAddress(dstAddress); bool master = isMaster(dstAddress); if (dstAddress == BROADCAST) { logInfo(lf_update, "update BC cmd: %s", m_command.getDataStr().c_str()); if (m_command.size()>=5+9 && m_command[2]==0x07 && m_command[3]==0x04) { unsigned char slaveAddress = (unsigned char)((srcAddress+5)&0xff); addSeenAddress(slaveAddress); Message* message = m_messages->getScanMessage(slaveAddress); if (message && (message->getLastUpdateTime()==0 || message->getLastSlaveData().size()<10)) { // e.g. 10fe07040a b5564149303001248901 m_seenAddresses[slaveAddress] |= SCAN_INIT; SymbolString idData; istringstream input; result_t result = message->prepareMaster(m_ownMasterAddress, idData, input); if (result==RESULT_OK) { idData.clear(); idData.push_back(9); for (size_t i = 5; i <= 5+9; i++) { idData.push_back(m_command[i]); } result = message->storeLastData(pt_slaveData, idData, 0); } if (result==RESULT_OK) { m_seenAddresses[slaveAddress] |= SCAN_DONE; } logNotice(lf_update, "store BC ident: %s", getResultCode(result)); } } } else if (master) { logInfo(lf_update, "update MM cmd: %s", m_command.getDataStr().c_str()); } else { logInfo(lf_update, "update MS cmd: %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); } Message* message = m_messages->find(m_command); if (m_grabMessages) { unsigned long long key; if (message) { key = message->getKey(); } else { key = Message::createKey(m_command, 4); // up to 4 DD bytes } m_grabbedMessages[key].setLastData(m_command, m_response); } if (message == NULL) { if (dstAddress == BROADCAST) { logNotice(lf_update, "unknown BC cmd: %s", m_command.getDataStr().c_str()); } else if (master) { logNotice(lf_update, "unknown MM cmd: %s", m_command.getDataStr().c_str()); } else { logNotice(lf_update, "unknown MS cmd: %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); } } else { m_messages->invalidateCache(message); string circuit = message->getCircuit(); string name = message->getName(); result_t result = message->storeLastData(m_command, m_response); ostringstream output; if (result==RESULT_OK) { result = message->decodeLastData(output); } if (result < RESULT_OK) { logError(lf_update, "unable to parse %s %s from %s / %s: %s", circuit.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result)); } else { string data = output.str(); if (m_answer && dstAddress == (master ? m_ownMasterAddress : m_ownSlaveAddress)) { logNotice(lf_update, "self-update %s %s QQ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress, data.c_str()); // TODO store in database of internal variables } else if (message->getDstAddress() == SYN) { // any destination if (message->getSrcAddress() == SYN) { // any destination and any source logNotice(lf_update, "update %s %s QQ=%2.2x ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress, dstAddress, data.c_str()); } else { logNotice(lf_update, "update %s %s ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), dstAddress, data.c_str()); } } else if (message->getSrcAddress() == SYN) { // any source logNotice(lf_update, "update %s %s QQ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress, data.c_str()); } else { logNotice(lf_update, "update %s %s: %s", circuit.c_str(), name.c_str(), data.c_str()); } } } }