diff --git a/DMRLookup.cpp b/DMRLookup.cpp index 8fc67c3..41f6831 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 callsign, name; if (id == 0xFFFFFFU) return std::string("ALL"); @@ -100,9 +100,15 @@ std::string CDMRLookup::findWithName(unsigned int id) callsign = std::string(text); } + try { + name = " " + m_tableName.at(id); + } catch (...) { + name = ""; + } + m_mutex.unlock(); - return callsign; + return callsign + name; } std::string CDMRLookup::find(unsigned int id) { @@ -137,6 +143,37 @@ 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(); + + try { + name = m_tableName.at(id); + } catch (...) { + name = ""; + } + + 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 +197,36 @@ bool CDMRLookup::load() // Remove the old entries m_table.clear(); + m_tableName.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; + } + + // no index - set default + if (makeindex(buffer)) { + strncpy(buffer, "RADIO_ID,CALLSIGN,FIRST_NAME", sizeof(buffer)); + makeindex(buffer); + rewind(fp); + } - char buffer[100U]; - while (::fgets(buffer, 100U, fp) != NULL) { + while (::fgets(buffer, sizeof(buffer), 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); - } + if (extract(buffer)) + continue; + + makeentry((unsigned int)::atoi(m_pId)); } m_mutex.unlock(); @@ -195,4 +240,83 @@ 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) +{ + int i; + char *p1, *p2; + + m_ixId = m_ixCall = m_ixFName = m_ixLName = m_ixCity = m_ixState = m_ixCountry = -1; + + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + if (!::strcmp("RADIO_ID", p1)) m_ixId = i; + else if (!::strcmp("CALLSIGN", p1)) m_ixCall = i; + else if (!::strcmp("FIRST_NAME", p1)) m_ixFName = i; + else if (!::strcmp("LAST_NAME", p1)) m_ixLName = i; + else if (!::strcmp("CITY", p1)) m_ixCity = i; + else if (!::strcmp("STATE", p1)) m_ixState = i; + else if (!::strcmp("COUNTRY", p1)) m_ixCountry = i; + } + + return (m_ixId == -1 || m_ixCall == -1); +} + +bool CDMRLookup::extract(char *buf) +{ + int i; + char *p1, *p2; + + m_pId = m_pCall = m_pFName = m_pLName = m_pCity = m_pState = m_pCountry = NULL; + + for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; + i++, p1 = tokenize(p2, &p2)) { + if (i == m_ixId) m_pId = p1; + else if (i == m_ixCall) m_pCall = p1; + else if (i == m_ixFName) m_pFName = p1; + else if (i == m_ixLName) m_pLName = p1; + else if (i == m_ixCity) m_pCity = p1; + else if (i == m_ixState) m_pState = p1; + else if (i == m_ixCountry) m_pCountry = p1; + } + + return (m_pId == NULL || m_pCall == NULL); +} + +void CDMRLookup::makeentry(unsigned int id) +{ + for (char* p = m_pCall; *p != '\0'; p++) + *p = ::toupper(*p); + m_table[id] = std::string(m_pCall); + if (m_pFName != NULL && m_pLName != NULL) { + m_tableName[id] = std::string(m_pFName) + " " + + std::string(m_pLName); + } else if (m_pFName != NULL) { + m_tableName[id] = std::string(m_pFName); + } else if (m_pLName != NULL) { + m_tableName[id] = std::string(m_pLName); + } + if (m_pCity != NULL) + m_tableCity[id] = std::string(m_pCity); + if (m_pState != NULL) + m_tableState[id] = std::string(m_pState); + if (m_pCountry != NULL) + m_tableCountry[id] = std::string(m_pCountry); +} + +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..54e7695 100644 --- a/DMRLookup.h +++ b/DMRLookup.h @@ -36,6 +36,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 +46,32 @@ private: std::string m_filename; unsigned int m_reloadTime; std::unordered_map m_table; + std::unordered_map m_tableName; + std::unordered_map m_tableCity; + std::unordered_map m_tableState; + std::unordered_map m_tableCountry; CMutex m_mutex; bool m_stop; + int m_ixId; + int m_ixCall; + int m_ixFName; + int m_ixLName; + int m_ixCity; + int m_ixState; + int m_ixCountry; + char* m_pId; + char* m_pCall; + char* m_pFName; + char* m_pLName; + char* m_pCity; + char* m_pState; + char* m_pCountry; bool load(); + bool makeindex(char* buf); + bool extract(char *buf); + void makeentry(unsigned int id); + 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); --- 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);