Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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);
}
Exemple #8
0
  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;
  }
Exemple #9
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;

}
Exemple #15
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;
}
Exemple #16
0
// 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;
}
Exemple #17
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;
}
Exemple #18
0
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));
}
Exemple #19
0
// 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;
}
Exemple #20
0
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);
}
Exemple #21
0
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());
			}
		}
	}
}