solved todo: cache symbols instead of decoded values, use cache for verbose and field-selective read as well, include names and comments in verbose find
This commit is contained in:
+38
-36
@@ -239,35 +239,49 @@ string MainLoop::executeRead(vector<string> &args)
|
|||||||
" FIELD only retrieve the field named FIELD\n"
|
" FIELD only retrieve the field named FIELD\n"
|
||||||
" N only retrieve the N'th field named FIELD (0-based)";
|
" N only retrieve the N'th field named FIELD (0-based)";
|
||||||
|
|
||||||
if (args.size() == argPos + 2)
|
string fieldName;
|
||||||
maxAge = 0; // force refresh to filter single field
|
signed char fieldIndex = -2;
|
||||||
|
if (args.size() == argPos + 2) {
|
||||||
|
fieldName = args[argPos + 1];
|
||||||
|
fieldIndex = -1;
|
||||||
|
size_t pos = fieldName.find_last_of('.');
|
||||||
|
if (pos != string::npos) {
|
||||||
|
result_t result = RESULT_OK;
|
||||||
|
fieldIndex = (char)parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result);
|
||||||
|
if (result == RESULT_OK)
|
||||||
|
fieldName = fieldName.substr(0, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
time_t now;
|
time_t now;
|
||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
Message* updateMessage = NULL;
|
ostringstream result;
|
||||||
if (maxAge > 0 && !verbose) {
|
|
||||||
updateMessage = m_messages->find(clazz, args[argPos], false, true);
|
|
||||||
|
|
||||||
if (updateMessage != NULL && updateMessage->getLastUpdateTime() + maxAge > now)
|
|
||||||
return updateMessage->getLastValue(); // TODO switch from last value to last master/slave to support verbose cached/polled values as well
|
|
||||||
// else: check poll data or read directly from bus
|
|
||||||
}
|
|
||||||
|
|
||||||
Message* message = m_messages->find(clazz, args[argPos], false);
|
Message* message = m_messages->find(clazz, args[argPos], false);
|
||||||
|
|
||||||
if (message == NULL) {
|
if (maxAge > 0) {
|
||||||
if (updateMessage != NULL)
|
Message* cacheMessage = m_messages->find(clazz, args[argPos], false, true);
|
||||||
|
bool hasCache = cacheMessage != NULL;
|
||||||
|
if (!hasCache || (message != NULL && message->getLastUpdateTime() > cacheMessage->getLastUpdateTime()))
|
||||||
|
cacheMessage = message; // message is newer/better
|
||||||
|
|
||||||
|
if (cacheMessage != NULL && cacheMessage->getLastUpdateTime() + maxAge > now) {
|
||||||
|
result_t ret = cacheMessage->decodeLastData(result, verbose, fieldIndex==-2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||||
|
if (ret != RESULT_OK)
|
||||||
|
return getResultCode(ret);
|
||||||
|
|
||||||
|
return result.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message == NULL && hasCache)
|
||||||
return "ERR: no data stored";
|
return "ERR: no data stored";
|
||||||
|
// else: read directly from bus
|
||||||
return getResultCode(RESULT_ERR_NOTFOUND);
|
|
||||||
}
|
}
|
||||||
if (maxAge > 0 && message->getPollPriority() > 0
|
|
||||||
&& message->getLastUpdateTime() + maxAge > now) {
|
|
||||||
// get poll data
|
|
||||||
return message->getLastValue();
|
|
||||||
} // else: read directly from bus
|
|
||||||
|
|
||||||
|
if (message == NULL)
|
||||||
|
return getResultCode(RESULT_ERR_NOTFOUND);
|
||||||
|
|
||||||
|
// read directly from bus
|
||||||
SymbolString master(true);
|
SymbolString master(true);
|
||||||
istringstream input;
|
istringstream input;
|
||||||
result_t ret = message->prepareMaster(m_address, master, input);
|
result_t ret = message->prepareMaster(m_address, master, input);
|
||||||
@@ -281,21 +295,8 @@ string MainLoop::executeRead(vector<string> &args)
|
|||||||
SymbolString slave(false);
|
SymbolString slave(false);
|
||||||
ret = m_busHandler->sendAndWait(master, slave);
|
ret = m_busHandler->sendAndWait(master, slave);
|
||||||
|
|
||||||
ostringstream result;
|
|
||||||
if (ret == RESULT_OK) {
|
if (ret == RESULT_OK) {
|
||||||
if (args.size() == argPos + 2) {
|
ret = message->decode(pt_slaveData, slave, result, false, verbose, fieldIndex==-2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||||
string fieldName = args[argPos + 1];
|
|
||||||
size_t pos = fieldName.find_last_of('.');
|
|
||||||
char fieldIndex = -1;
|
|
||||||
if (pos != string::npos) {
|
|
||||||
result_t result = RESULT_OK;
|
|
||||||
fieldIndex = (char)parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result);
|
|
||||||
if (result == RESULT_OK)
|
|
||||||
fieldName = fieldName.substr(0, pos);
|
|
||||||
}
|
|
||||||
ret = message->decode(pt_slaveData, slave, result, false, verbose, fieldName.c_str(), fieldIndex);
|
|
||||||
} else
|
|
||||||
ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data
|
|
||||||
}
|
}
|
||||||
if (ret != RESULT_OK) {
|
if (ret != RESULT_OK) {
|
||||||
logError(lf_main, "read: %s", getResultCode(ret));
|
logError(lf_main, "read: %s", getResultCode(ret));
|
||||||
@@ -507,7 +508,7 @@ string MainLoop::executeFind(vector<string> &args)
|
|||||||
if (lastup == 0)
|
if (lastup == 0)
|
||||||
result << "no data stored";
|
result << "no data stored";
|
||||||
else
|
else
|
||||||
result << message->getLastValue();
|
message->decodeLastData(result, verbose);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (lastup == 0)
|
if (lastup == 0)
|
||||||
sprintf(str, "%02x", dstAddress);
|
sprintf(str, "%02x", dstAddress);
|
||||||
@@ -716,7 +717,8 @@ string MainLoop::getUpdates(time_t since, time_t until)
|
|||||||
if (lastchg < since || lastchg >= until)
|
if (lastchg < since || lastchg >= until)
|
||||||
continue;
|
continue;
|
||||||
result << message->getClass() << " " << message->getName() << " = ";
|
result << message->getClass() << " " << message->getName() << " = ";
|
||||||
result << message->getLastValue() << endl;
|
message->decodeLastData(result);
|
||||||
|
result << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.str();
|
return result.str();
|
||||||
|
|||||||
@@ -1288,14 +1288,15 @@ result_t DataFieldSet::read(const PartType partType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findFieldIndex && !found)
|
if (!found) {
|
||||||
return RESULT_ERR_NOTFOUND;
|
return RESULT_EMPTY;
|
||||||
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (m_comment.length() > 0)
|
if (m_comment.length() > 0)
|
||||||
output << " [" << m_comment << "]";
|
output << " [" << m_comment << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
return found ? RESULT_OK : RESULT_EMPTY;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
result_t DataFieldSet::write(istringstream& input,
|
result_t DataFieldSet::write(istringstream& input,
|
||||||
|
|||||||
+56
-14
@@ -289,6 +289,10 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma
|
|||||||
result = m_data->write(input, pt_masterData, master, (unsigned char)(m_id.size() - 2), separator);
|
result = m_data->write(input, pt_masterData, master, (unsigned char)(m_id.size() - 2), separator);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
|
if (master != m_lastMasterData) {
|
||||||
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
|
m_lastMasterData = master;
|
||||||
|
}
|
||||||
masterData.addAll(master);
|
masterData.addAll(master);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -307,6 +311,11 @@ result_t Message::prepareSlave(SymbolString& slaveData)
|
|||||||
result = m_data->write(input, pt_slaveData, slave, 0);
|
result = m_data->write(input, pt_slaveData, slave, 0);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
|
time(&m_lastUpdateTime);
|
||||||
|
if (slave != m_lastSlaveData) {
|
||||||
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
|
m_lastSlaveData = slave;
|
||||||
|
}
|
||||||
slaveData.addAll(slave);
|
slaveData.addAll(slave);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -321,16 +330,24 @@ result_t Message::decode(const PartType partType, SymbolString& data,
|
|||||||
offset = (unsigned char)(m_id.size() - 2);
|
offset = (unsigned char)(m_id.size() - 2);
|
||||||
else
|
else
|
||||||
offset = 0;
|
offset = 0;
|
||||||
size_t startPos = output.str().length();
|
|
||||||
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||||
if (result < RESULT_OK) {
|
if (result < RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
if (result == RESULT_EMPTY)
|
||||||
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
|
||||||
time(&m_lastUpdateTime);
|
time(&m_lastUpdateTime);
|
||||||
string value = output.str().substr(startPos);
|
if (partType == pt_masterData) {
|
||||||
if (value != m_lastValue)
|
if (data != m_lastMasterData) {
|
||||||
m_lastChangeTime = m_lastUpdateTime;
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
m_lastValue = value;
|
m_lastMasterData = data;
|
||||||
|
}
|
||||||
|
} else if (partType == pt_slaveData) {
|
||||||
|
if (data != m_lastSlaveData) {
|
||||||
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
|
m_lastSlaveData = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,23 +358,48 @@ result_t Message::decode(SymbolString& masterData, SymbolString& slaveData,
|
|||||||
unsigned char offset = (unsigned char)(m_id.size() - 2);
|
unsigned char offset = (unsigned char)(m_id.size() - 2);
|
||||||
size_t startPos = output.str().length();
|
size_t startPos = output.str().length();
|
||||||
result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
||||||
if (result < RESULT_OK) {
|
if (result < RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
bool empty = result==RESULT_EMPTY;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
leadingSeparator = output.str().length() > startPos;
|
leadingSeparator = output.str().length() > startPos;
|
||||||
result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, verbose, NULL, -1, separator);
|
||||||
if (result < RESULT_OK) {
|
if (result < RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
if (empty && result == RESULT_EMPTY)
|
||||||
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
|
||||||
time(&m_lastUpdateTime);
|
time(&m_lastUpdateTime);
|
||||||
string value = output.str().substr(startPos);
|
if (masterData != m_lastMasterData) {
|
||||||
if (value != m_lastValue)
|
|
||||||
m_lastChangeTime = m_lastUpdateTime;
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
m_lastValue = value;
|
m_lastMasterData = masterData;
|
||||||
|
}
|
||||||
|
if (slaveData != m_lastSlaveData) {
|
||||||
|
m_lastChangeTime = m_lastUpdateTime;
|
||||||
|
m_lastSlaveData = slaveData;
|
||||||
|
}
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t Message::decodeLastData(ostringstream& output,
|
||||||
|
bool verbose, const char* fieldName, signed char fieldIndex,
|
||||||
|
char separator)
|
||||||
|
{
|
||||||
|
bool leadingSeparator = false;
|
||||||
|
unsigned char offset = (unsigned char)(m_id.size() - 2);
|
||||||
|
size_t startPos = output.str().length();
|
||||||
|
result_t result = m_data->read(pt_masterData, m_lastMasterData, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||||
|
if (result < RESULT_OK)
|
||||||
|
return result;
|
||||||
|
bool empty = result==RESULT_EMPTY;
|
||||||
|
offset = 0;
|
||||||
|
leadingSeparator = output.str().length() > startPos;
|
||||||
|
result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator);
|
||||||
|
if (empty && result == RESULT_EMPTY)
|
||||||
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool Message::isLessPollWeight(const Message* other)
|
bool Message::isLessPollWeight(const Message* other)
|
||||||
{
|
{
|
||||||
unsigned int tw = m_pollPriority * m_pollCount;
|
unsigned int tw = m_pollPriority * m_pollCount;
|
||||||
|
|||||||
+16
-5
@@ -209,10 +209,18 @@ public:
|
|||||||
bool verbose=false, char separator=UI_FIELD_SEPARATOR);
|
bool verbose=false, char separator=UI_FIELD_SEPARATOR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the last decoded value.
|
* Decode the value from the last stored data.
|
||||||
* @return the last decoded value, or the empty string if it was not successful.
|
* @param output the @a ostringstream to append the formatted value to.
|
||||||
|
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||||
|
* the comment in square brackets (if present).
|
||||||
|
* @param fieldName the optional name of a field to limit the output to.
|
||||||
|
* @param fieldIndex the optional index of the named field to limit the output to, or -1.
|
||||||
|
* @param separator the separator character between multiple fields.
|
||||||
|
* @return @a RESULT_OK on success, or an error code.
|
||||||
*/
|
*/
|
||||||
string getLastValue() { return m_lastValue; }
|
result_t decodeLastData(ostringstream& output,
|
||||||
|
bool verbose=false, const char* fieldName=NULL, signed char fieldIndex=-1,
|
||||||
|
char separator=UI_FIELD_SEPARATOR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time when @a m_lastValue was last stored.
|
* Get the time when @a m_lastValue was last stored.
|
||||||
@@ -281,8 +289,11 @@ private:
|
|||||||
/** the priority for polling, or 0 for no polling at all. */
|
/** the priority for polling, or 0 for no polling at all. */
|
||||||
const unsigned char m_pollPriority;
|
const unsigned char m_pollPriority;
|
||||||
|
|
||||||
/** the last decoded value. */
|
/** the last seen master data. */
|
||||||
string m_lastValue;
|
SymbolString m_lastMasterData;
|
||||||
|
|
||||||
|
/** the last seen slave data. */
|
||||||
|
SymbolString m_lastSlaveData;
|
||||||
|
|
||||||
/** the system time when @a m_lastValue was last stored, 0 for never. */
|
/** the system time when @a m_lastValue was last stored, 0 for never. */
|
||||||
time_t m_lastUpdateTime;
|
time_t m_lastUpdateTime;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ int main()
|
|||||||
// message= [type];class;name;[comment];[QQ];ZZ;PBSB;fields...
|
// message= [type];class;name;[comment];[QQ];ZZ;PBSB;fields...
|
||||||
// field= name;[pos];type[;[divisor|values][;[unit][;[comment]]]]
|
// field= name;[pos];type[;[divisor|values][;[unit][;[comment]]]]
|
||||||
string checks[][5] = {
|
string checks[][5] = {
|
||||||
// "message", "flags"
|
// "message", "decoded", "master", "slave", "flags"
|
||||||
{"date,HDA:3,,,Datum", "", "", "", "t"},
|
{"date,HDA:3,,,Datum", "", "", "", "t"},
|
||||||
{"time,VTI,,,", "", "", "", "t"},
|
{"time,VTI,,,", "", "", "", "t"},
|
||||||
{"dcfstate,UCH,0=nosignal;1=ok;2=sync;3=valid,,", "", "", "", "t"},
|
{"dcfstate,UCH,0=nosignal;1=ok;2=sync;3=valid,,", "", "", "", "t"},
|
||||||
@@ -56,6 +56,7 @@ int main()
|
|||||||
{"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "t"},
|
{"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "t"},
|
||||||
{"tempsensor,temp;sensor", "", "", "", "t"},
|
{"tempsensor,temp;sensor", "", "", "", "t"},
|
||||||
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
{"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,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", "m"},
|
||||||
{"r,ehp,time,,,08,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md"},
|
{"r,ehp,time,,,08,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md"},
|
||||||
{"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"},
|
{"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"},
|
||||||
|
|||||||
Reference in New Issue
Block a user