summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhii Voloshynov <serhii.voloshynov@globallogic.com>2023-11-22 17:18:06 +0200
committerSerhii Voloshynov <serhii.voloshynov@globallogic.com>2023-11-24 16:32:29 +0200
commitee0e497a8fdb840bf63018372d101a0396913b15 (patch)
tree91d23f7e99a9059d74f3d4e11e769f96470b35ea
parenta826d13ae7b3e20648566ddecca23bd6fe8f856b (diff)
downloadmts-io-sysfs-ee0e497a8fdb840bf63018372d101a0396913b15.tar.gz
mts-io-sysfs-ee0e497a8fdb840bf63018372d101a0396913b15.tar.bz2
mts-io-sysfs-ee0e497a8fdb840bf63018372d101a0396913b15.zip
[MTX-5095][GP-2116] add DigitalIO, store output state(s) to set after reboot
-rw-r--r--include/Device/Device.h11
-rw-r--r--include/General.h4
-rw-r--r--src/Device/Device.cpp119
3 files changed, 118 insertions, 16 deletions
diff --git a/include/Device/Device.h b/include/Device/Device.h
index e02c352..42dad24 100644
--- a/include/Device/Device.h
+++ b/include/Device/Device.h
@@ -23,12 +23,15 @@ class Device {
static std::map<std::string, bool> capabilityList;
static std::map<std::string, std::string> ethSwitchList;
static std::map<std::string, std::string> deviceInfoList;
+ static std::vector<std::string> dInputs;
+ static std::vector<std::string> dOutputs;
static const std::regex apFilters;
static const std::regex serialModeFilter;
static const std::regex storeFilters;
static const std::regex showFilters;
static const std::regex mtcdt3HwVersionFilters;
+ static const std::regex iotRtrVersionFilters;
static const std::regex mtrFilters;
const unsigned int accessoryCardsListSize = 7;
@@ -128,7 +131,7 @@ class Device {
void AddToDeviceInfo(const std::string Port,
const std::string ProductID);
};
-
+
class gpio_request {
private:
struct gpiod_request_config *request_config;
@@ -146,7 +149,7 @@ class Device {
};
std::vector<std::unique_ptr<AccessoryCard>> accessoryCardsList;
-
+
public:
Device();
void getSystemTreeJson(const char *dir_name);
@@ -171,9 +174,11 @@ class Device {
void sortAccessoryCards();
void store(std::string name, std::string value);
void storeTrigger(std::string name, std::string value);
+ void storeOutputStateToNonvolatile(const std::string& name, const std::string& value);
void Verbose(bool val);
bool Verbose();
- void writeJson();
+ void writeJson(const rapidjson::Document &json, const std::string &file);
+ bool readJson(rapidjson::Document &json, const std::string &file);
void simpleError(std::string msg, int error, int exitval);
};
diff --git a/include/General.h b/include/General.h
index 5e32f0b..4429b3d 100644
--- a/include/General.h
+++ b/include/General.h
@@ -72,6 +72,10 @@ typedef unsigned int uint; // 32 bit - even on 64 bit machines
#define RESET_SHORT_CMD "reset_short_handler"
#define RESET_LONG_CMD "reset_long_handler"
#define KILL_SIGNAL "kill -l "
+#define STORED_DIGITAL_OUTPUTS_STATE_FILE "/var/config/pin_states.json"
+#define KEY_EXTIO "extIo"
+#define KEY_DOUTPUTS "dOutputs"
+#define KEY_DINPUTS "dInputs"
enum HardwareType {
HARDWARE_MTCDT,
diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp
index 9a9e36c..e7e295b 100644
--- a/src/Device/Device.cpp
+++ b/src/Device/Device.cpp
@@ -25,6 +25,7 @@ const std::regex
Device::apFilters("(modalias)|(power)(.*)|(subsystem)|(uevent)");
const std::regex Device::serialModeFilter("(.*)(serial-mode)");
const std::regex Device::mtcdt3HwVersionFilters("(MTCDT3AC)(.*)");
+const std::regex Device::iotRtrVersionFilters("(MTCAP3)(.*)"); // TODO - change it after getting IOTROUTER hardware
const std::regex Device::mtrFilters("(MTR-)(.*)");
const std::regex Device::storeFilters(
"(.*)(mac-)(.*)|(.*)(-id)|(uuid)|(.*)(/eui)|(.*)(/"
@@ -61,6 +62,8 @@ std::map<std::string, bool> Device::capabilityList = {
{"userDataEncryption", false}};
std::map<std::string, std::string> Device::ethSwitchList;
+std::vector<std::string> Device::dInputs;
+std::vector<std::string> Device::dOutputs;
std::map<std::string, std::string> Device::deviceInfoList = {
{"deviceId", ""},
@@ -116,7 +119,6 @@ bool Device::isValidDirectory(const struct dirent *entry, std::string fullPath,
void Device::getSystemTreeJson(const char *dir_name) {
std::string fullPath = SYSFS_PLATFORM + std::string(dir_name);
DIR *d = opendir(fullPath.c_str());
-
if (!d) {
printError("Cannot open directory %s", fullPath);
exitHandler(99);
@@ -184,6 +186,16 @@ void Device::getSystemTreeJson(const char *dir_name) {
capabilityList["rs485"] = true;
capabilityList["serial"] = true;
}
+ if (regex_match(fileData, iotRtrVersionFilters)) {
+ capabilityList["din"] = true; // TODO - remove it when it will be in EEPROM
+ capabilityList["dout"] = true; // TODO - remove it when it will be in EEPROM
+ /*
+ The order of the elements is important! This array is used to access Digital IOs,
+ in particular in SMS commands!
+ */
+ dInputs.push_back("led-power"); //TODO - change it to real names after getting IOTRouter HW
+ dOutputs.push_back("led-lora"); //TODO - change it to real names after getting IOTRouter HW
+ }
} else if (strcmp(d_name, "mac-eth") == 0) {
deviceInfoList["macAddress"] = fileData;
} else if (strcmp(d_name, "has-radio") == 0 &&
@@ -208,8 +220,8 @@ void Device::getSystemTreeJson(const char *dir_name) {
getSystemTreeJson(d_name); /* Recursively call with the new path */
}
}
- if (closedir(
- d)) { /* After going through all the entries, close the directory */
+ if (closedir(d)) {
+ /* After going through all the entries, close the directory */
printError("Could not close %s", fullPath);
exitHandler(errno);
}
@@ -221,7 +233,7 @@ void Device::init() {
exitHandler(99);
}
load();
- writeJson();
+ writeJson(deviceInfo, DEVICE_INFO_FILE);
exitHandler(0);
}
@@ -309,6 +321,28 @@ 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();
+ auto &extAlloc = extIo.GetAllocator();
+ extIo.AddMember(KEY_DINPUTS, inp, extAlloc);
+ extIo.AddMember(KEY_DOUTPUTS, out, extAlloc);
+ deviceInfo.AddMember(KEY_EXTIO, extIo, extAlloc);
}
void Device::mapFileToCapability() {
@@ -563,7 +597,7 @@ struct gpiod_chip * Device::gpio_request::gpiod_ctxless_find_line(Device *device
gpiodevname = NULL;
break;
}
-
+
chip_info = gpiod_chip_get_info(found_chip);
if (!chip_info) {
int error = errno;
@@ -583,7 +617,7 @@ struct gpiod_chip * Device::gpio_request::gpiod_ctxless_find_line(Device *device
return found_chip; // Caller must close chip
}
gpiod_line_info_free(info);
-
+
}
gpiod_chip_close(found_chip);
}
@@ -635,7 +669,7 @@ Device::gpio_request:: gpio_request(Device *device, const std::string name)
device->simpleError("Could not request lines gpiod chip_request_lines", errno, 108);
}
Device::gpio_request:: ~gpio_request()
-{
+{
if(line_request)
gpiod_line_request_release(line_request);
if(settings)
@@ -731,8 +765,10 @@ void Device::store(std::string name, std::string value) {
if (gr.request()) {
retval = gpiod_line_request_set_value(gr.request(),gr.offset(),lv);
- if(retval != -1)
+ if(retval != -1) {
+ storeOutputStateToNonvolatile(name, value);
exitHandler(0);
+ }
else
simpleError("Could not set GPIO value",errno,111);
}
@@ -747,6 +783,7 @@ void Device::store(std::string name, std::string value) {
name.c_str(),strerror(errno));
exitHandler(98);
}
+ storeOutputStateToNonvolatile(name, value);
fileToWrite.close();
exitHandler(0);
}
@@ -777,15 +814,71 @@ void Device::storeTrigger(std::string name, std::string value) {
exitHandler(99);
}
-void Device::writeJson() {
+void Device::writeJson(const rapidjson::Document &json, const std::string &file) {
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
- deviceInfo.Accept(writer);
- std::ofstream os(DEVICE_INFO_FILE);
- if (!os) {
- printError("Can't write to %s: %s", DEVICE_INFO_FILE,strerror(errno));
+ json.Accept(writer);
+ std::ofstream os(file);
+ if (!os.is_open()) {
+ printError("Can't write to %s: %s", file.c_str(),strerror(errno));
exitHandler(99);
} else {
os << buffer.GetString();
}
}
+
+bool Device::readJson(rapidjson::Document &json, const std::string &file) {
+ std::ifstream is(file);
+ if (!is.is_open()) {
+ printWarning("Can't read to %s: %s", file.c_str(), strerror(errno));
+ return false;
+ }
+ rapidjson::IStreamWrapper isw { is };
+ json.ParseStream(isw);
+ if (json.HasParseError()) {
+ printError("%s Parse error", file.c_str());
+ return false;
+ }
+ return true;
+}
+
+void Device::storeOutputStateToNonvolatile(const std::string& name, const std::string& value) {
+ rapidjson::Document deviceInfo;
+ if (!readJson(deviceInfo, DEVICE_INFO_FILE)){
+ return;
+ }
+
+ if (!deviceInfo.HasMember(KEY_EXTIO)){
+ return;
+ }
+ if (!deviceInfo[KEY_EXTIO].HasMember(KEY_DOUTPUTS)){
+ return;
+ }
+ const rapidjson::Value &outputs = deviceInfo[KEY_EXTIO][KEY_DOUTPUTS];
+ bool found = false;
+ for (auto itr = outputs.Begin(); itr != outputs.End(); ++itr) {
+ auto listedOutput = (*itr).GetString();
+ if (name == listedOutput) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return;
+ }
+
+ rapidjson::Document stateIo;
+ rapidjson::Document::AllocatorType &alloc = stateIo.GetAllocator();
+ rapidjson::Value jname(name.c_str(), alloc);
+ rapidjson::Value jvalue(value.c_str(), alloc);
+ readJson( stateIo, STORED_DIGITAL_OUTPUTS_STATE_FILE);
+ if (stateIo.IsNull()) {
+ stateIo.SetObject();
+ };
+ if (!stateIo.HasMember(jname)) {
+ stateIo.AddMember(jname, jvalue, alloc);
+ } else {
+ stateIo[jname] = jvalue;
+ }
+ writeJson(stateIo, STORED_DIGITAL_OUTPUTS_STATE_FILE);
+}