From 0b55b2997d17bbce5bea3ebe1f5700dca184574f Mon Sep 17 00:00:00 2001 From: Serhii Voloshynov Date: Wed, 15 May 2024 16:20:54 +0300 Subject: [MTX-5302] MTR3 R.7.0: Serial IP functionality support GP-2336 --- src/Device/Device.cpp | 190 +++++++++++++++++++++++++++++++++++++------------- src/MtsIoSysfs.cpp | 17 +++-- 2 files changed, 150 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp index b2588eb..be198f1 100644 --- a/src/Device/Device.cpp +++ b/src/Device/Device.cpp @@ -42,16 +42,12 @@ std::map Device::capabilityList = { {"cell", false}, {"din", false}, {"dout", false}, - {"externalSerialPort", false}, {"gpio", false}, {"gps", false}, {"lora", false}, {"loraLbt", false}, {"loraNetworkServer", false}, {"nodeRed", false}, - {"rs232", false}, - {"rs422", false}, - {"rs485", false}, {"serial", false}, {"supercap", false}, {"wifi", false}, @@ -60,8 +56,8 @@ std::map Device::capabilityList = { {"userDataEncryption", false}}; std::map Device::ethSwitchList; -std::vector Device::dInputs; -std::vector Device::dOutputs; +std::string Device::extIoStr; +std::string Device::serialStr; std::map Device::deviceInfoList = { {"deviceId", ""}, @@ -179,19 +175,33 @@ void Device::getSystemTreeJson(const char *dir_name) { } else if (strcmp(d_name, "hw-version") == 0) { deviceInfoList["hardwareVersion"] = fileData; if (regex_match(fileData, mtcdt3HwVersionFilters)) { - capabilityList["rs232"] = true; - capabilityList["rs422"] = true; - capabilityList["rs485"] = true; capabilityList["serial"] = true; } if (regex_match(fileData, iotRtrVersionFilters)) { + mapMacAddress2Iotr(); /* The order of the elements is important! This array is used to access Digital IOs, in particular in SMS commands! */ - dInputs.push_back("USER_DIO_IN"); - dOutputs.push_back("USER_DIO_OUT"); - mapMacAddress2Iotr(); + extIoStr = "{\"dInputs\":[\"USER_DIO_IN\"],\"dOutputs\":[\"USER_DIO_OUT\"]}"; + capabilityList["serial"] = true; + serialStr = "[{" + "\"available\": true," + "\"id\": \"serial0\"," + "\"name\": \"RS232\"," + "\"device\": \"/dev/ttymxc1\"," + "\"role\": \"DCE\"," + "\"modes\": {\"RS-232\": [\"hw-flowcontrol\", \"dcd-dtr\"]}," + "\"speed\": [9600, 19200, 38400, 57600, 115200]" + "},{" + "\"available\": true," + "\"id\": \"serial1\"," + "\"name\": \"RS232/485\"," + "\"device\": \"/dev/ttymxc2\"," + "\"role\": \"DCE\"," + "\"modes\": {\"RS-232\": [\"hw-flowcontrol\"], \"RS-485-HALF\": [\"rs4xx-termination\"]}," + "\"speed\": [9600, 19200, 38400, 57600, 115200, 230400, 460800, 930600]" + "}]"; } } else if (strcmp(d_name, "mac-eth") == 0) { deviceInfoList["macAddress"] = fileData; @@ -318,28 +328,14 @@ void Device::load() { deviceInfo.AddMember("capabilities", capabilities, alloc); deviceInfo.AddMember("ethSwitch", ethSwitch, alloc); deviceInfo.AddMember("accessoryCards", accessoryCards, alloc); - rapidjson::Document inp; - auto &inpAlloc = inp.GetAllocator(); - inp.SetArray(); - for (const auto &input : dInputs) { - rapidjson::Value value; - value.SetString(input.c_str(), input.length(), inpAlloc); - inp.PushBack(value, inpAlloc); - } - rapidjson::Document out; - auto &outAlloc = out.GetAllocator(); - out.SetArray(); - for (const auto &output : dOutputs) { - rapidjson::Value value; - value.SetString(output.c_str(), output.length(), outAlloc); - out.PushBack(value, outAlloc); - } rapidjson::Document extIo; - extIo.SetObject(); + extIo.Parse<0>(extIoStr.c_str()); auto &extAlloc = extIo.GetAllocator(); - extIo.AddMember(KEY_DINPUTS, inp, extAlloc); - extIo.AddMember(KEY_DOUTPUTS, out, extAlloc); deviceInfo.AddMember(KEY_EXTIO, extIo, extAlloc); + rapidjson::Document serial; + serial.Parse<0>(serialStr.c_str()); + auto &serAlloc = serial.GetAllocator(); + deviceInfo.AddMember(KEY_SERIALS, serial, serAlloc); } void Device::mapFileToCapability() { @@ -350,10 +346,6 @@ void Device::mapFileToCapability() { S_IFREG) { /* lora-network-server is a regular file */ capabilityList["loraNetworkServer"] = true; } - if (fileType("/dev/ext_serial") == - S_IFCHR) { /* ext_serial is a character device */ - capabilityList["externalSerialPort"] = true; - } if (fileType("/usr/bin/dockerd") == S_IFREG) { /* Docker is a regular file */ capabilityList["docker"] = true; @@ -450,9 +442,10 @@ void Device::printVersion(std::string name) { exitHandler(0); } -void Device::printUsage(std::string program) { + +void Device::printUsage() { std::vector showResults; - printf("Usage: %s [ OPTIONS ] OBJECT [--] [ ARGUMENTS ]\n", program.c_str()); + printf("Usage: %s [ OPTIONS ] OBJECT [--] [ ARGUMENTS ]\n", program_name.c_str()); printf("Legacy OBJECT options:\n"); printf(" init : init & make device info json\n"); printf(" json : init & make device info json\n"); @@ -489,7 +482,7 @@ void Device::printUsage(std::string program) { printf("\n"); printf("show-name:\n"); printf("Usage:\n"); - printf("--show-name \n"); + printf("--show \n"); printDir("", showResults); sort(showResults.begin(), showResults.end()); // Unix file tree is not sorted @@ -498,10 +491,15 @@ void Device::printUsage(std::string program) { if (!regex_match(showResult, showFilters)) printf(" %s\n", showResult.c_str()); } + if (regex_match(hw_version, iotRtrVersionFilters)) { + printf(" serial1/%s\n", SERIAL_TERMINATION.c_str()); + printf(" serial1/%s\n", SERIAL_MODE.c_str()); + printf("}\n"); + } printf("\n"); printf("store-name:\n"); printf("Usage:\n"); - printf("--store-name \n"); + printf("--store \n"); for (std::string showResult : showResults) { if (showResult == "radio-reset") { printf(" %s { 0 }\n", showResult.c_str()); @@ -512,14 +510,23 @@ void Device::printUsage(std::string program) { } else if (showResult == "reset-monitor-intervals") { printf(" %s { short-interval long-interval }\n", showResult.c_str()); - } else if (regex_match(showResult, serialModeFilter)) { - printf(" %s { loopback | rs232 | rs485-half | " - "rs422-485-full }\n", - showResult.c_str()); } else if (!regex_match(showResult, storeFilters)) { printf(" %s BOOLEAN\n", showResult.c_str()); } } + if (regex_match(hw_version, iotRtrVersionFilters)) { + printf(" serial1/%s { 0 | 1 }\n", SERIAL_TERMINATION.c_str()); + printf(" serial1/%s {", SERIAL_MODE.c_str()); + unsigned int c = 1; + for (auto const &m : mModes) { + printf(" %s ", m.first.c_str()); + if (c != mModes.size()) { + printf("|"); + } + c++; + }; + printf("}\n"); + } printf("\n"); exitHandler(0); } @@ -697,7 +704,8 @@ unsigned int Device::gpio_request::offset() * driver. GPIOs can only be zero * or one, never a text string. */ -void Device::show(std::string name) { + +int Device::getPinValue(const std::string &name) { std::string fileData; if(isupper(name[0])) { gpio_request gr(this, name); @@ -705,10 +713,9 @@ void Device::show(std::string name) { enum gpiod_line_value lv = gpiod_line_request_get_value(gr.request(),gr.offset()); if(lv != GPIOD_LINE_VALUE_ERROR) { if(lv == GPIOD_LINE_VALUE_INACTIVE) - std::cout << "0\n"; + return 0; else - std::cout << "1\n"; - exitHandler(0); + return 1; } else simpleError("Invalid GPIO line value", errno, 109); } @@ -716,12 +723,24 @@ void Device::show(std::string name) { int32_t code = MTS::System::readFile(SYSFS_PLATFORM + name, fileData); if (code == 0) { - printf("%s", fileData.c_str()); - exitHandler(0); + if (fileData == "1") { + return 1; + } else { + return 0; + } } printError("cat: can't open %s%s: %s", SYSFS_PLATFORM, name.c_str(),strerror(errno)); exitHandler(99); + return 99; // never be returned +} + +void Device::show(std::string name) { + if (regex_match(hw_version, iotRtrVersionFilters)) { + showSerialModesMTR3(name); + } + printf("%i", getPinValue(name)); + exitHandler(0); } // End of show void Device::showTrigger(std::string name) { @@ -745,7 +764,9 @@ void Device::store(std::string name, std::string value) { } printDebug("Setting %s to %s", name.c_str(), value.c_str()); - + if (regex_match(hw_version, iotRtrVersionFilters)) { + setSerialModesMTR3(name, value); + } if(isupper(name[0])) { enum gpiod_line_value lv = GPIOD_LINE_VALUE_ERROR; @@ -872,3 +893,72 @@ void Device::storeOutputStateToNonvolatile(const std::string& name, const std::s } writeJson(stateIo, STORED_DIGITAL_OUTPUTS_STATE_FILE); } + +void Device::setSerialModesMTR3(const std::string ¶meter, const std::string &value) { + std::vector parts = MTS::Text::split(parameter, '/'); + if (parts.size() < 2) { + return; + } + const std::string &serialName = parts[0]; + const std::string &mode = parts[1]; + if (serialName != "serial1") { + printUsage(); + } + if ((mode != SERIAL_MODE) && (mode != SERIAL_TERMINATION)) { + printUsage(); + } + if (mode == SERIAL_MODE) { + if ((value != SERIAL_MODE_RS232) && (value != SERIAL_MODE_RS485)) { + printUsage(); + } + if (value == SERIAL_MODE_RS232) { + store(CONTROL_PIN_SERIAL_MODE, "0"); + } + if (value == SERIAL_MODE_RS485) { + store(CONTROL_PIN_SERIAL_MODE, "1"); + } + exitHandler(0); + } else if (mode == SERIAL_TERMINATION) { + store(CONTROL_PIN_TERMINATION, value); + exitHandler(0); + } +} + +void Device::showSerialModesMTR3(const std::string ¶meter) { + std::vector parts = MTS::Text::split(parameter, '/'); + if (parts.size() < 2) { + return; + } + const std::string &serialName = parts[0]; + const std::string &mode = parts[1]; + if (serialName != "serial1") { + printUsage(); + } + if ((mode != SERIAL_MODE) && (mode != SERIAL_TERMINATION)) { + printUsage(); + } + if (mode == SERIAL_MODE) { + if (getPinValue(CONTROL_PIN_SERIAL_MODE) == 1) { + std::cout << SERIAL_MODE_RS485 << std::endl; + } else { + std::cout << SERIAL_MODE_RS232 << std::endl; + } + exitHandler(0); + } else if (mode == SERIAL_TERMINATION) { + std::cout << getPinValue(CONTROL_PIN_TERMINATION) << std::endl; + exitHandler(0); + } +} + +void Device::setProgramName(const std::string &name){ + program_name = name; +} + +void Device::setHWVersion(){ + std::ifstream is(HW_VERSION_FILE); + if (!is.is_open()) { + printDebug("Can't read to %s: %s", HW_VERSION_FILE, strerror(errno)); + return; + } + std::getline(is, hw_version); +} \ No newline at end of file diff --git a/src/MtsIoSysfs.cpp b/src/MtsIoSysfs.cpp index ab68c8c..20e2925 100644 --- a/src/MtsIoSysfs.cpp +++ b/src/MtsIoSysfs.cpp @@ -44,10 +44,9 @@ static enum action_code action; int main(int argc, char **argv) { Device m; + m.setProgramName(argv[0]); action = ACTION_NONE; - if (argc < 2) { - m.printUsage(argv[0]); - } + std::string fpgaFilePath = ""; std::string forcedAP = ""; std::string name = ""; @@ -55,6 +54,10 @@ int main(int argc, char **argv) { int duration = 0; MTS::Logger::setPrintLevel(MTS::Logger::PrintLevel::INFO_LEVEL, true); + m.setHWVersion(); + if (argc < 2) { + m.printUsage(); + } int c; static struct option long_options[] = { {"help", no_argument, nullptr, 'h'}, @@ -148,11 +151,11 @@ int main(int argc, char **argv) { exit(-1); } case 'h': { - m.printUsage(argv[0]); + m.printUsage(); exit(0); } default: - m.printUsage(argv[0]); + m.printUsage(); exit(-1); } } @@ -213,7 +216,7 @@ int main(int argc, char **argv) { switch (action) { case ACTION_NONE: { - m.printUsage(argv[0]); + m.printUsage(); } case ACTION_SHOW: { m.show(name); @@ -251,7 +254,7 @@ int main(int argc, char **argv) { case ACTION_VERSION: { m.printVersion(argv[0]); } - default: { m.printUsage(argv[0]); } + default: { m.printUsage(); } } return 0; -- cgit v1.2.3 From f8ba2f3dcc186f7474e0a5433e5971737cc37282 Mon Sep 17 00:00:00 2001 From: Serhii Voloshynov Date: Tue, 28 May 2024 11:01:19 +0300 Subject: fixes after review --- src/Device/Device.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp index be198f1..2d93ed7 100644 --- a/src/Device/Device.cpp +++ b/src/Device/Device.cpp @@ -56,8 +56,8 @@ std::map Device::capabilityList = { {"userDataEncryption", false}}; std::map Device::ethSwitchList; -std::string Device::extIoStr; -std::string Device::serialStr; +std::string Device::extIoStr = "{\"dInputs\":[],\"dOutputs\":[]}";; +std::string Device::serialStr = "[]"; std::map Device::deviceInfoList = { {"deviceId", ""}, @@ -725,9 +725,8 @@ int Device::getPinValue(const std::string &name) { if (code == 0) { if (fileData == "1") { return 1; - } else { - return 0; - } + }; + return 0; } printError("cat: can't open %s%s: %s", SYSFS_PLATFORM, name.c_str(),strerror(errno)); @@ -897,6 +896,8 @@ void Device::storeOutputStateToNonvolatile(const std::string& name, const std::s void Device::setSerialModesMTR3(const std::string ¶meter, const std::string &value) { std::vector parts = MTS::Text::split(parameter, '/'); if (parts.size() < 2) { + // it is not a serial things, return and compare to other options + // serial things look like `serial1/mode' return; } const std::string &serialName = parts[0]; @@ -917,16 +918,20 @@ void Device::setSerialModesMTR3(const std::string ¶meter, const std::string if (value == SERIAL_MODE_RS485) { store(CONTROL_PIN_SERIAL_MODE, "1"); } - exitHandler(0); } else if (mode == SERIAL_TERMINATION) { store(CONTROL_PIN_TERMINATION, value); - exitHandler(0); + } else { + printError("Unknown mode: %s", mode.c_str()); + exitHandler(98); } + exitHandler(0); } void Device::showSerialModesMTR3(const std::string ¶meter) { std::vector parts = MTS::Text::split(parameter, '/'); if (parts.size() < 2) { + // it is not a serial things, return and compare to other options + // serial things look like `serial1/mode' return; } const std::string &serialName = parts[0]; @@ -943,11 +948,13 @@ void Device::showSerialModesMTR3(const std::string ¶meter) { } else { std::cout << SERIAL_MODE_RS232 << std::endl; } - exitHandler(0); } else if (mode == SERIAL_TERMINATION) { std::cout << getPinValue(CONTROL_PIN_TERMINATION) << std::endl; - exitHandler(0); + } else { + printError("Unknown mode: %s", mode.c_str()); + exitHandler(98); } + exitHandler(0); } void Device::setProgramName(const std::string &name){ @@ -955,9 +962,9 @@ void Device::setProgramName(const std::string &name){ } void Device::setHWVersion(){ - std::ifstream is(HW_VERSION_FILE); + std::ifstream is(HW_VERSION_PATH); if (!is.is_open()) { - printDebug("Can't read to %s: %s", HW_VERSION_FILE, strerror(errno)); + printDebug("Can't read to %s: %s", HW_VERSION_PATH, strerror(errno)); return; } std::getline(is, hw_version); -- cgit v1.2.3