diff --git a/DMRLookup.cpp b/DMRLookup.cpp index 8fc67c3..72a9dc2 100644 --- a/DMRLookup.cpp +++ b/DMRLookup.cpp @@ -83,7 +83,7 @@ void CDMRLookup::stop() std::string CDMRLookup::findWithName(unsigned int id) { - std::string callsign; + std::string result, callsign, fname, lname, name; if (id == 0xFFFFFFU) return std::string("ALL"); @@ -92,17 +92,30 @@ std::string CDMRLookup::findWithName(unsigned int id) try { callsign = m_table.at(id); - LogDebug("FindWithName =%s",callsign.c_str()); - } catch (...) { char text[10U]; ::sprintf(text, "%u", id); callsign = std::string(text); } + try { + fname = m_tableFName.at(id); + } catch (...) { + fname = ""; + } + try { + lname = m_tableLName.at(id); + } catch (...) { + lname = ""; + } + name = fname + ((fname.empty() || lname.empty()) ? "" : " ") + lname; + + result = callsign + (name.empty() ? "" : " ") + name; + LogDebug("FindWithName =%s", result.c_str()); + m_mutex.unlock(); - return callsign; + return result; } std::string CDMRLookup::find(unsigned int id) { @@ -137,6 +150,44 @@ std::string CDMRLookup::find(unsigned int id) return callsign; } +void CDMRLookup::findUserInfo(unsigned int id, std::string& name, std::string& city, std::string& state, std::string& country) +{ + m_mutex.lock(); + + std::string fname, lname; + try { + fname = m_tableFName.at(id); + } catch (...) { + fname = ""; + } + try { + lname = m_tableLName.at(id); + } catch (...) { + lname = ""; + } + name = fname + ((fname.empty() || lname.empty()) ? "" : " ") + lname; + + try { + city = m_tableCity.at(id); + } catch (...) { + city = ""; + } + + try { + state = m_tableState.at(id); + } catch (...) { + state = ""; + } + + try { + country = m_tableCountry.at(id); + } catch (...) { + country = ""; + } + + m_mutex.unlock(); +} + bool CDMRLookup::exists(unsigned int id) { m_mutex.lock(); @@ -160,28 +211,33 @@ bool CDMRLookup::load() // Remove the old entries m_table.clear(); + m_tableFName.clear(); + m_tableLName.clear(); + m_tableCity.clear(); + m_tableState.clear(); + m_tableCountry.clear(); + + char buffer[256U]; + + // set index for entries + if (::fgets(buffer, sizeof(buffer), fp) == NULL) { + LogWarning("DMR Id lookup file has no entry - %s", m_filename.c_str()); + m_mutex.unlock(); + ::fclose(fp); + return false; + } - char buffer[100U]; - while (::fgets(buffer, 100U, fp) != NULL) { - if (buffer[0U] == '#') - continue; - - char* p1 = ::strtok(buffer, " \t\r\n"); - char* p2 = ::strtok(NULL, " \r\n"); // tokenize to eol to capture name as well - - if (p1 != NULL && p2 != NULL) { - unsigned int id = (unsigned int)::atoi(p1); - for (char* p = p2; *p != 0x00U; p++) { - - if(*p == 0x09U) - *p = 0x20U; - - else - *p = ::toupper(*p); - - } - m_table[id] = std::string(p2); - } + // no index - set default + std::vector index; + if (makeindex(buffer, index)) { + strncpy(buffer, "RADIO_ID,CALLSIGN,FIRST_NAME", sizeof(buffer)); + makeindex(buffer, index); + rewind(fp); + } + + while (::fgets(buffer, sizeof(buffer), fp) != NULL) { + if (buffer[0U] != '#') + parse(buffer, index); } m_mutex.unlock(); @@ -195,4 +251,80 @@ bool CDMRLookup::load() LogInfo("Loaded %u Ids to the DMR callsign lookup table", size); return true; -} \ No newline at end of file +} + +bool CDMRLookup::makeindex(char* buf, std::vector& index) +{ + int i, j; + char *p1, *p2; + std::vector key = { + "RADIO_ID", "CALLSIGN", "FIRST_NAME", "LAST_NAME", + "CITY", "STATE", "COUNTRY", + }; + std::vector init(key.size(), -1); + + index = init; + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + + for (j = 0; j < key.size(); j++) { + if (key[j] == p1) { + index[j] = i; + break; + } + } + } + + return (index[0] == -1 || index[1] == -1); +} + +void CDMRLookup::parse(char *buf, std::vector& index) +{ + int i, j; + char *p1, *p2; + std::vector ptr(index.size(), NULL); + std::vector*> table = { + &m_table, &m_tableFName, &m_tableLName, + &m_tableCity, &m_tableState, &m_tableCountry, + }; + unsigned int id; + + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + + for (j = 0; j < index.size(); j++) { + if (index[j] == i) { + ptr[j] = p1; + break; + } + } + } + + if (ptr[0] == NULL || ptr[1] == NULL) + return; + + // XXX capitalize callsign + + id = (unsigned int)atoi(ptr[0]); + + for (i = 1; i < ptr.size(); i++) { + if (ptr[i] != NULL) + (*table[i - 1])[id] = std::string(ptr[i]); + } +} + +char* CDMRLookup::tokenize(char *str, char **next) +{ + if (*str == '\0') + return NULL; + + char* p = ::strpbrk(str, ",\t\r\n"); + if (p == NULL) { + *next = str + ::strlen(str); + } else { + *p = '\0'; + *next = p + 1; + } + + return str; +} diff --git a/DMRLookup.h b/DMRLookup.h index 1156270..8992d86 100644 --- a/DMRLookup.h +++ b/DMRLookup.h @@ -23,6 +23,7 @@ #include "Mutex.h" #include +#include #include class CDMRLookup : public CThread { @@ -36,6 +37,7 @@ public: std::string find(unsigned int id); std::string findWithName(unsigned int id); + void findUserInfo(unsigned int id, std::string& name, std::string& city, std::string& state, std::string& country); bool exists(unsigned int id); @@ -45,10 +47,18 @@ private: std::string m_filename; unsigned int m_reloadTime; std::unordered_map m_table; + std::unordered_map m_tableFName; + std::unordered_map m_tableLName; + std::unordered_map m_tableCity; + std::unordered_map m_tableState; + std::unordered_map m_tableCountry; CMutex m_mutex; bool m_stop; bool load(); + bool makeindex(char* buf, std::vector& index); + void parse(char *buf, std::vector& index); + char* tokenize(char *str, char **next); }; #endif diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 8dd4cd9..706a68e 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -1103,7 +1103,10 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) std::string src = m_lookup->find(srcId); std::string dst = m_lookup->find(dstId); std::string cn = m_lookup->findWithName(srcId); + std::string dst_name, dst_city, dst_state, dst_country; + m_lookup->findUserInfo(srcId, dst_name, dst_city, dst_state, dst_country); m_display->writeDMR(m_slotNo, cn, flco == FLCO_GROUP, dst, "N"); + m_display->writeDMRUser(m_slotNo, dst_name, dst_city, dst_state, dst_country); #if defined(DUMP_DMR) openFile(); diff --git a/Display.cpp b/Display.cpp index 39f72a8..3ef95ab 100644 --- a/Display.cpp +++ b/Display.cpp @@ -151,6 +151,11 @@ void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group, writeDMRInt(slotNo, src, group, dst, type); } +void CDisplay::writeDMRUser(unsigned int slotNo, const std::string& name, std::string& city, std::string& state, std::string& country) +{ + writeDMRUserInt(slotNo, name, city, state, country); +} + void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi) { if (rssi != 0U) @@ -386,6 +391,10 @@ void CDisplay::writeDStarBERInt(float ber) { } +void CDisplay::writeDMRUserInt(unsigned int slotNo, const std::string& name, std::string& city, std::string& state, std::string& country) +{ +} + void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) { } diff --git a/Display.h b/Display.h index 65515be..af96da3 100644 --- a/Display.h +++ b/Display.h @@ -48,6 +48,7 @@ public: void clearDStar(); void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); + void writeDMRUser(unsigned int slotNo, const std::string& name, std::string& city, std::string& state, std::string& country); void writeDMRRSSI(unsigned int slotNo, unsigned char rssi); void writeDMRBER(unsigned int slotNo, float ber); void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type); @@ -91,6 +92,7 @@ protected: virtual void clearDStarInt() = 0; virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0; + virtual void writeDMRUserInt(unsigned int slotNo, const std::string& name, std::string& city, std::string& state, std::string& country); virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi); virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type); virtual void writeDMRBERInt(unsigned int slotNo, float ber); diff --git a/TFTSurenoo.cpp b/TFTSurenoo.cpp index 73972c7..6e24862 100644 --- a/TFTSurenoo.cpp +++ b/TFTSurenoo.cpp @@ -49,7 +49,8 @@ enum LcdColour { #define FONT_MEDIUM 24 // 12x24 #define FONT_LARGE 32 // 16x32 -#define FG_COLOUR COLOUR_CYAN +#define INFO_COLOUR COLOUR_CYAN +#define EXT_COLOUR COLOUR_DARK_GREEN #define BG_COLOUR COLOUR_BLACK #define ERROR_COLOUR COLOUR_DARK_RED #define MODE_COLOUR COLOUR_YELLOW @@ -63,7 +64,8 @@ enum LcdColour { #define MODE_CHARS (X_WIDTH / (MODE_FONT_SIZE / 2)) #define STATUS_CHARS (X_WIDTH / (STATUS_FONT_SIZE / 2)) #define STATUS_LINES ((Y_WIDTH - STATUS_MARGIN) / STATUS_FONT_SIZE) -#define statusLine_offset(x) ((STATUS_CHARS + 1) * ((x) + 1)) +#define statusLine_offset(x) ((STATUS_CHARS + 1) * ((x) + 1)) +#define INFO_LINES 2 // This module sometimes ignores display command (too busy?), // so supress display refresh @@ -132,7 +134,7 @@ void CTFTSurenoo::setIdleInt() ::snprintf(m_temp, sizeof(m_temp), "%-6s / %u", m_callsign.c_str(), m_dmrid); setStatusLine(0, m_temp); - setStatusLine(2, "IDLE"); + setStatusLine(1, "IDLE"); m_mode = MODE_IDLE; } @@ -143,7 +145,7 @@ void CTFTSurenoo::setErrorInt(const char* text) setModeLine(STR_MMDVM); setStatusLine(0, text); - setStatusLine(2, "ERROR"); + setStatusLine(1, "ERROR"); m_mode = MODE_ERROR; } @@ -151,7 +153,7 @@ void CTFTSurenoo::setErrorInt(const char* text) void CTFTSurenoo::setLockoutInt() { setModeLine(STR_MMDVM); - setStatusLine(2, "LOCKOUT"); + setStatusLine(1, "LOCKOUT"); m_mode = MODE_LOCKOUT; } @@ -162,7 +164,7 @@ void CTFTSurenoo::setQuitInt() CThread::sleep(REFRESH_PERIOD); setModeLine(STR_MMDVM); - setStatusLine(2, "STOPPED"); + setStatusLine(1, "STOPPED"); refreshDisplay(); @@ -183,13 +185,13 @@ void CTFTSurenoo::writeDStarInt(const char* my1, const char* my2, const char* yo setStatusLine(0, m_temp); ::snprintf(m_temp, sizeof(m_temp), "%.8s", your); - setStatusLine(2, m_temp); + setStatusLine(1, m_temp); if (::strcmp(reflector, " ") != 0) ::snprintf(m_temp, sizeof(m_temp), "via %.8s", reflector); else ::strcpy(m_temp, ""); - setStatusLine(4, m_temp); + setStatusLine(2, m_temp); m_mode = MODE_DSTAR; } @@ -197,40 +199,53 @@ void CTFTSurenoo::writeDStarInt(const char* my1, const char* my2, const char* yo void CTFTSurenoo::clearDStarInt() { setStatusLine(0, "Listening"); + setStatusLine(1, ""); setStatusLine(2, ""); - setStatusLine(4, ""); } void CTFTSurenoo::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) { assert(type != NULL); - // slotNo comes 1 or 2, convert 0 or 1 - slotNo--; - setModeLine(STR_DMR); - ::snprintf(m_temp, sizeof(m_temp), "%d Listening", 2 - slotNo); - setStatusLine((1 - slotNo) * 2, m_temp); - - ::snprintf(m_temp, sizeof(m_temp), "%d %s %s", slotNo + 1, type, src.c_str()); - setStatusLine(slotNo * 2, m_temp); + ::snprintf(m_temp, sizeof(m_temp), "%s %s", type, src.c_str()); + /* + * XXX src comes callsign with username. we use writeDMRUserInt() + * XXX to show username, truncate username here. + * XXX if m_lookup->findWithName() replaced to m_lookup->find() + * XXX in DMRSlot.cpp, this workaround should be deleted. + */ + { + char *p; + p = strchr(m_temp, ' '); // 1st space + if (p != NULL) p = strchr(p + 1, ' '); // 2nd space + if (p != NULL) *p = '\0'; // truncate + } + setStatusLine(0, m_temp); - ::snprintf(m_temp, sizeof(m_temp), "%s%s", group ? "TG" : "", dst.c_str()); - setStatusLine(slotNo * 2 + 1, m_temp); + ::snprintf(m_temp, sizeof(m_temp), "TS%d %s%s", slotNo, group ? "TG" : "", dst.c_str()); + setStatusLine(1, m_temp); m_mode = MODE_DMR; } -void CTFTSurenoo::clearDMRInt(unsigned int slotNo) +void CTFTSurenoo::writeDMRUserInt(unsigned int slotNo, const std::string &name, std::string& city, std::string& state, std::string& country) { - // slotNo comes 1 or 2, convert 0 or 1 - slotNo--; - - ::snprintf(m_temp, sizeof(m_temp), "%d Listening", slotNo + 1); - setStatusLine(slotNo * 2, m_temp); + setStatusLine(2, name.c_str()); + setStatusLine(3, city.c_str()); + setStatusLine(4, state.c_str()); + setStatusLine(5, country.c_str()); +} - setStatusLine(slotNo * 2 + 1, ""); +void CTFTSurenoo::clearDMRInt(unsigned int slotNo) +{ + setStatusLine(0, "Listening"); + setStatusLine(1, ""); + setStatusLine(2, ""); + setStatusLine(3, ""); + setStatusLine(4, ""); + setStatusLine(5, ""); } void CTFTSurenoo::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) @@ -246,13 +261,13 @@ void CTFTSurenoo::writeFusionInt(const char* source, const char* dest, const cha setStatusLine(0, m_temp); ::snprintf(m_temp, sizeof(m_temp), " %.10s", dest); - setStatusLine(2, m_temp); + setStatusLine(1, m_temp); if (::strcmp(origin, " ") != 0) ::snprintf(m_temp, sizeof(m_temp), "at %.10s", origin); else ::strcpy(m_temp, ""); - setStatusLine(4, m_temp); + setStatusLine(2, m_temp); m_mode = MODE_YSF; } @@ -273,7 +288,7 @@ void CTFTSurenoo::writeP25Int(const char* source, bool group, unsigned int dest, setStatusLine(0, m_temp); ::snprintf(m_temp, sizeof(m_temp), " %s%u", group ? "TG" : "", dest); - setStatusLine(2, m_temp); + setStatusLine(1, m_temp); m_mode = MODE_P25; } @@ -294,7 +309,7 @@ void CTFTSurenoo::writeNXDNInt(const char* source, bool group, unsigned int dest setStatusLine(0, m_temp); ::snprintf(m_temp, sizeof(m_temp), " %s%u", group ? "TG" : "", dest); - setStatusLine(2, m_temp); + setStatusLine(1, m_temp); m_mode = MODE_NXDN; } @@ -306,26 +321,26 @@ void CTFTSurenoo::clearNXDNInt() void CTFTSurenoo::writePOCSAGInt(uint32_t ric, const std::string& message) { - setStatusLine(2, "POCSAG TX"); + setStatusLine(1, "POCSAG TX"); m_mode = MODE_POCSAG; } void CTFTSurenoo::clearPOCSAGInt() { - setStatusLine(2, "IDLE"); + setStatusLine(1, "IDLE"); } void CTFTSurenoo::writeCWInt() { - setStatusLine(2, "CW TX"); + setStatusLine(1, "CW TX"); m_mode = MODE_CW; } void CTFTSurenoo::clearCWInt() { - setStatusLine(2, "IDLE"); + setStatusLine(1, "IDLE"); } void CTFTSurenoo::close() @@ -391,8 +406,8 @@ void CTFTSurenoo::refreshDisplay(void) ::snprintf(m_temp, sizeof(m_temp), "DCV%d(%d,%d,'%s',%d);", STATUS_FONT_SIZE, 0, - STATUS_MARGIN + STATUS_FONT_SIZE * i, - p, FG_COLOUR); + STATUS_MARGIN + STATUS_FONT_SIZE * i, p, + (i < INFO_LINES) ? INFO_COLOUR : EXT_COLOUR); m_serial->write((unsigned char*)m_temp, (unsigned int)::strlen(m_temp)); } diff --git a/TFTSurenoo.h b/TFTSurenoo.h index c95c5c0..75f0b6c 100644 --- a/TFTSurenoo.h +++ b/TFTSurenoo.h @@ -46,6 +46,7 @@ protected: virtual void clearDStarInt(); virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); + virtual void writeDMRUserInt(unsigned int slotNo, const std::string& name, std::string& city, std::string& state, std::string& country); virtual void clearDMRInt(unsigned int slotNo); virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin);