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

#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
//
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
//
#include <map>
#include <set>
#include <string>
#include "gpio_key_channel.hpp"
#include "utils/stringutils.hpp"
using namespace nlohmann;
using namespace iflytop;
using namespace std;
void GpioKeyChannel::execCmd(string cmd) {
logger->info("execCmd {}", cmd);
system(cmd.c_str());
}
GpioKeyChannel::GpioKeyChannel(string chname, vector<string> pins, vector<string> alias, vector<bool> mirror) {
logger = LoggerFactory.createRotatingFileLogger(chname);
m_chname = chname;
m_pins = pins;
m_mirror = mirror;
m_alias = alias;
}
void GpioKeyChannel::initialize() {
// vector<GPIO> m_gpios;
if (m_mirror.size() != m_pins.size()) {
logger->error("mirror size not match with pins size");
exit(1);
}
if (m_alias.size() != m_pins.size()) {
logger->error("alias size not match with pins size");
exit(1);
}
int offset = 0;
for (auto pinstr : m_pins) {
// GPIO3_A2
auto result = LinuxGpioUitils::parseGpioStr(pinstr);
GPIO gpio;
gpio.blank = result.blank;
gpio.port = result.port;
gpio.pin = result.pin;
gpio.linuxIndex = result.linuxIndex;
gpio.offset = offset;
if (gpio.linuxIndex == -1) {
logger->error("parse gpio {} failed", pinstr);
exit(1);
} else {
logger->info("parse gpio {} --> gpio{}", pinstr, gpio.linuxIndex);
m_gpios.push_back(gpio);
}
offset++;
}
if (m_mirror.size() != 0) {
for (size_t i = 0; i < m_gpios.size(); i++) {
m_gpios[i].mirror = m_mirror[i];
m_gpios[i].alias = m_alias[i];
}
}
// init gpio
for (auto& gpio : m_gpios) {
execCmd(fmt::format("echo {} > /sys/class/gpio/export", gpio.linuxIndex));
execCmd(fmt::format("echo in > /sys/class/gpio/gpio{}/direction", gpio.linuxIndex));
gpio.fd = open(fmt::format("/sys/class/gpio/gpio{}/value", gpio.linuxIndex).c_str(), O_RDONLY);
if (gpio.fd < 0) {
logger->error("open gpio{} failed", gpio.linuxIndex);
exit(1);
}
}
// read gpio
m_rxthread.reset(new Thread(fmt::format("{}-rxthread", m_chname), [this]() {
logger->info("{} rxthread start", m_chname);
ThisThread thisThread;
int syncCount = 0;
while (!thisThread.getExitFlag()) {
for (auto& gpio : m_gpios) {
char value;
lseek(gpio.fd, 0, SEEK_SET);
read(gpio.fd, &value, 1);
bool nowstate = value == '1' ? true : false;
nowstate = gpio.mirror ? !nowstate : nowstate;
gpio.laststate = gpio.state;
gpio.state = nowstate;
if (gpio.laststate != gpio.state) {
gpio.duration = 0;
} else {
gpio.duration += 20;
if (gpio.duration <= 0) gpio.duration = INT32_MAX;
}
}
// report
for (auto& gpio : m_gpios) {
bool reportthisloop = false;
if (gpio.duration == 0 || syncCount % 50 == 0) {
json report;
report["name"] = gpio.alias;
report["index"] = gpio.linuxIndex;
report["state"] = (bool)gpio.state;
report["duration"] = gpio.duration;
report["event"] = gpio.state == gpio.laststate ? "sync" : (gpio.state ? "press" : "release");
string reportstr = report.dump();
if (m_ondata) m_ondata(this, false, reportstr.data(), reportstr.size());
if (gpio.duration == 0) {
logger->info("{}", reportstr);
}
}
}
usleep(20 * 1000);
syncCount++;
} // end while
}));
return;
}
void GpioKeyChannel::senddata(bool binary, const char* data, size_t len) {}
void GpioKeyChannel::registerOnDataCallback(OnData_t ondata) { m_ondata = ondata; }
void GpioKeyChannel::callcmd(string cmd, unordered_map<string, string> param, json& receipt) {}
list<string> GpioKeyChannel::getCmdList() {
list<string> cmdlist;
return cmdlist;
}
json GpioKeyChannel::getChannelInfo() {
json info;
info["name"] = m_chname;
info["alias"] = getAlias();
info["type"] = "gpio-key";
info["pins"] = m_pins;
info["pinAlias"] = m_alias;
info["mirror"] = m_mirror;
return info;
}