You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.3 KiB

4 months ago
  1. #include <fcntl.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <termios.h>
  7. #include <unistd.h>
  8. //
  9. #include <arpa/inet.h>
  10. #include <netinet/in.h>
  11. #include <sys/socket.h>
  12. #include <sys/types.h>
  13. //
  14. #include <map>
  15. #include <set>
  16. #include <string>
  17. #include "gpio_key_channel.hpp"
  18. #include "utils/stringutils.hpp"
  19. using namespace nlohmann;
  20. using namespace iflytop;
  21. using namespace std;
  22. void GpioKeyChannel::execCmd(string cmd) {
  23. logger->info("execCmd {}", cmd);
  24. system(cmd.c_str());
  25. }
  26. GpioKeyChannel::GpioKeyChannel(string chname, vector<string> pins, vector<string> alias, vector<bool> mirror) {
  27. logger = LoggerFactory.createRotatingFileLogger(chname);
  28. m_chname = chname;
  29. m_pins = pins;
  30. m_mirror = mirror;
  31. m_alias = alias;
  32. }
  33. void GpioKeyChannel::initialize() {
  34. // vector<GPIO> m_gpios;
  35. if (m_mirror.size() != m_pins.size()) {
  36. logger->error("mirror size not match with pins size");
  37. exit(1);
  38. }
  39. if (m_alias.size() != m_pins.size()) {
  40. logger->error("alias size not match with pins size");
  41. exit(1);
  42. }
  43. int offset = 0;
  44. for (auto pinstr : m_pins) {
  45. // GPIO3_A2
  46. auto result = LinuxGpioUitils::parseGpioStr(pinstr);
  47. GPIO gpio;
  48. gpio.blank = result.blank;
  49. gpio.port = result.port;
  50. gpio.pin = result.pin;
  51. gpio.linuxIndex = result.linuxIndex;
  52. gpio.offset = offset;
  53. if (gpio.linuxIndex == -1) {
  54. logger->error("parse gpio {} failed", pinstr);
  55. exit(1);
  56. } else {
  57. logger->info("parse gpio {} --> gpio{}", pinstr, gpio.linuxIndex);
  58. m_gpios.push_back(gpio);
  59. }
  60. offset++;
  61. }
  62. if (m_mirror.size() != 0) {
  63. for (size_t i = 0; i < m_gpios.size(); i++) {
  64. m_gpios[i].mirror = m_mirror[i];
  65. m_gpios[i].alias = m_alias[i];
  66. }
  67. }
  68. // init gpio
  69. for (auto& gpio : m_gpios) {
  70. execCmd(fmt::format("echo {} > /sys/class/gpio/export", gpio.linuxIndex));
  71. execCmd(fmt::format("echo in > /sys/class/gpio/gpio{}/direction", gpio.linuxIndex));
  72. gpio.fd = open(fmt::format("/sys/class/gpio/gpio{}/value", gpio.linuxIndex).c_str(), O_RDONLY);
  73. if (gpio.fd < 0) {
  74. logger->error("open gpio{} failed", gpio.linuxIndex);
  75. exit(1);
  76. }
  77. }
  78. // read gpio
  79. m_rxthread.reset(new Thread(fmt::format("{}-rxthread", m_chname), [this]() {
  80. logger->info("{} rxthread start", m_chname);
  81. ThisThread thisThread;
  82. int syncCount = 0;
  83. while (!thisThread.getExitFlag()) {
  84. for (auto& gpio : m_gpios) {
  85. char value;
  86. lseek(gpio.fd, 0, SEEK_SET);
  87. read(gpio.fd, &value, 1);
  88. bool nowstate = value == '1' ? true : false;
  89. nowstate = gpio.mirror ? !nowstate : nowstate;
  90. gpio.laststate = gpio.state;
  91. gpio.state = nowstate;
  92. if (gpio.laststate != gpio.state) {
  93. gpio.duration = 0;
  94. } else {
  95. gpio.duration += 20;
  96. if (gpio.duration <= 0) gpio.duration = INT32_MAX;
  97. }
  98. }
  99. // report
  100. for (auto& gpio : m_gpios) {
  101. bool reportthisloop = false;
  102. if (gpio.duration == 0 || syncCount % 50 == 0) {
  103. json report;
  104. report["name"] = gpio.alias;
  105. report["index"] = gpio.linuxIndex;
  106. report["state"] = (bool)gpio.state;
  107. report["duration"] = gpio.duration;
  108. report["event"] = gpio.state == gpio.laststate ? "sync" : (gpio.state ? "press" : "release");
  109. string reportstr = report.dump();
  110. if (m_ondata) m_ondata(this, false, reportstr.data(), reportstr.size());
  111. if (gpio.duration == 0) {
  112. logger->info("{}", reportstr);
  113. }
  114. }
  115. }
  116. usleep(20 * 1000);
  117. syncCount++;
  118. } // end while
  119. }));
  120. return;
  121. }
  122. void GpioKeyChannel::senddata(bool binary, const char* data, size_t len) {}
  123. void GpioKeyChannel::registerOnDataCallback(OnData_t ondata) { m_ondata = ondata; }
  124. void GpioKeyChannel::callcmd(string cmd, unordered_map<string, string> param, json& receipt) {}
  125. list<string> GpioKeyChannel::getCmdList() {
  126. list<string> cmdlist;
  127. return cmdlist;
  128. }
  129. json GpioKeyChannel::getChannelInfo() {
  130. json info;
  131. info["name"] = m_chname;
  132. info["alias"] = getAlias();
  133. info["type"] = "gpio-key";
  134. info["pins"] = m_pins;
  135. info["pinAlias"] = m_alias;
  136. info["mirror"] = m_mirror;
  137. return info;
  138. }