diff --git a/server/gpio.cpp b/server/gpio.cpp new file mode 100644 index 00000000..a7511365 --- /dev/null +++ b/server/gpio.cpp @@ -0,0 +1,208 @@ +#include "gpio.h" +#include + +Gpio::Gpio(QObject *parent, int gpio) : + QObject(parent),m_gpio(gpio) +{ + exportGpio(); +} + +Gpio::~Gpio() +{ + unexportGpio(); +} + +bool Gpio::exportGpio() +{ + char buf[64]; + + int fd = open("/sys/class/gpio/export", O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio/export"; + return false; + } + + int len = snprintf(buf, sizeof(buf), "%d", m_gpio); + write(fd, buf, len); + close(fd); + + return true; +} + +bool Gpio::unexportGpio() +{ + char buf[64]; + + int fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio/unexport"; + return false; + } + int len = snprintf(buf, sizeof(buf), "%d", m_gpio); + write(fd, buf, len); + close(fd); + + return true; +} + +int Gpio::openGpio() +{ + char buf[64]; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio); + + int fd = open(buf, O_RDONLY | O_NONBLOCK ); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; + return fd; + } + return fd; +} + +bool Gpio::setDirection(int dir) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", m_gpio); + + int fd = open(buf, O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; + return false; + } + if(dir == INPUT){ + write(fd, "in", 3); + m_dir = INPUT; + close(fd); + return true; + } + if(dir == OUTPUT){ + write(fd, "out", 4); + m_dir = OUTPUT; + close(fd); + return true; + } + close(fd); + return false; +} + +bool Gpio::setValue(unsigned int value) +{ + // check if gpio is a output + if( m_dir == OUTPUT){ + char buf[64]; + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio); + + int fd = open(buf, O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; + return false; + } + + if(value == LOW){ + write(fd, "0", 2); + close(fd); + return true; + } + if(value == HIGH){ + write(fd, "1", 2); + close(fd); + return true; + } + close(fd); + return false; + }else{ + qDebug() << "ERROR: Gpio" << m_gpio << "is not a OUTPUT."; + return false; + } +} + +int Gpio::getValue() +{ + char buf[64]; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio); + + int fd = open(buf, O_RDONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; + return -1; + } + + char ch; + int value = -1; + + read(fd, &ch, 1); + + if (ch != '0') { + value = 1; + }else{ + value = 0; + } + close(fd); + + qDebug() << "gpio" << m_gpio << "value = " << value; + return value; +} + +bool Gpio::setEdgeInterrupt(int edge) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/edge", m_gpio); + + int fd = open(buf, O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge"; + return false; + } + + if(edge == EDGE_FALLING){ + write(fd, "falling", 8); + close(fd); + return true; + } + if(edge == EDGE_RISING){ + write(fd, "rising", 7); + close(fd); + return true; + } + if(edge == EDGE_BOTH){ + write(fd, "both", 5); + close(fd); + return true; + } + close(fd); + return false; +} + +void Gpio::enableInterrupt() +{ + struct pollfd fdset[2]; + int gpio_fd = openGpio(); + int nfds = 2; + int rc; + int timeout = 3000; + char buf[64]; + + while(1){ + memset((void*)fdset, 0, sizeof(fdset)); + fdset[0].fd = STDIN_FILENO; + fdset[0].events = POLLIN; + + fdset[1].fd = gpio_fd; + fdset[1].events = POLLPRI; + + rc = poll(fdset, nfds, timeout); + + if (rc < 0) { + qDebug() << "ERROR: poll failed"; + return; + } + if(rc == 0){ + //timeout + } + if (fdset[1].revents & POLLPRI) { + read(fdset[1].fd, buf, 64); + emit pinInterrupt(); + } + } +} diff --git a/server/gpio.h b/server/gpio.h new file mode 100644 index 00000000..2836f52b --- /dev/null +++ b/server/gpio.h @@ -0,0 +1,83 @@ +#ifndef GPIO_H +#define GPIO_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define INPUT 0 +#define OUTPUT 1 +#define LOW 0 +#define HIGH 1 + +#define EDGE_FALLING 0 +#define EDGE_RISING 1 +#define EDGE_BOTH 2 + +/********************************** + * ______________________ + * |______________________| + * | File NR. | PIN NR. | + * |___________|__________| + * | GPIO 2 | 3 | + * | GPIO 3 | 5 | + * | GPIO 4 | 7 | + * | GPIO 7 | 26 | + * | GPIO 8 | 24 | + * | GPIO 9 | 21 | + * | GPIO 10 | 19 | + * | GPIO 11 | 23 | + * | GPIO 14 | 8 | + * | GPIO 15 | 10 | + * | GPIO 17 | 11 | + * | GPIO 18 | 12 | + * | GPIO 22 | 15 | + * | GPIO 23 | 16 | + * | GPIO 24 | 18 | + * | GPIO 25 | 22 | + * | GPIO 27 | 13 | + * |___________|__________| + * + ********************************** + */ + +class Gpio : public QObject +{ + Q_OBJECT +public: + explicit Gpio(QObject *parent = 0, int gpio = 0); + ~Gpio(); + + bool exportGpio(); + bool unexportGpio(); + + int openGpio(); + + bool setDirection(int dir); + + bool setValue(unsigned int value); + int getValue(); + + bool setEdgeInterrupt(int edge); + + + + +private: + int m_gpio; + int m_dir; + +signals: + void pinInterrupt(); + +public slots: + void enableInterrupt(); + +}; + +#endif // GPIO_H diff --git a/server/hivecore.cpp b/server/hivecore.cpp index ee4e118b..7fc8b9c6 100644 --- a/server/hivecore.cpp +++ b/server/hivecore.cpp @@ -31,20 +31,112 @@ HiveCore::HiveCore(QObject *parent) : // start the server m_jsonServer = new JsonRPCServer(this); + m_radio433 = new Radio433(this); + + //============================================== + int pulseLenght = 350; + QList signal; + //sync + signal.append(pulseLenght); + signal.append(pulseLenght*31); + + //============================================== + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + //============================================== + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + //============================================== + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 1 + signal.append(pulseLenght*3); + signal.append(pulseLenght); + + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + // 0 + signal.append(pulseLenght); + signal.append(pulseLenght*3); + //============================================== + + qDebug() << "sendsignal"; + + m_radio433->sendData(signal); + m_radio433->sendData(signal); + m_radio433->sendData(signal); + m_radio433->sendData(signal); -// // create 433.92 MHz sender -// m_sender = new RadioSender(this); -// m_sender->setFrequency(RadioSender::RF433MHz); -// m_sender->setLineCode(RadioSender::SWITCH); -// m_sender->setPulseLength(320); -//// //m_sender->sendBin("000000000000010101010001"); - -// // create 433.92 MHz receiver -// m_reciver = new RadioReciver(this); -// m_reciver->setFrequency(RadioReciver::RF433MHz); -// m_reciver->setPin(2); -// m_reciver->enableReceiver(); } diff --git a/server/hivecore.h b/server/hivecore.h index 27ae72a1..bacb590b 100644 --- a/server/hivecore.h +++ b/server/hivecore.h @@ -2,11 +2,7 @@ #define HIVECORE_H #include -//#include "server.h" -//#include "devicemanager.h" -//#include -//#include "radio/radioreciver.h" -//#include "radio/radiosender.h" +#include class JsonRPCServer; class Device; @@ -25,6 +21,7 @@ private: static HiveCore *s_instance; JsonRPCServer *m_jsonServer; + Radio433 *m_radio433; // Server *m_server; // RadioReciver *m_reciver; diff --git a/server/main.cpp b/server/main.cpp index 692d95bd..98021730 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); - + HiveCore::instance(); return a.exec(); diff --git a/server/radio433.cpp b/server/radio433.cpp index f2185759..4b0bf0b7 100644 --- a/server/radio433.cpp +++ b/server/radio433.cpp @@ -1,10 +1,145 @@ #include "radio433.h" +#include +#include -Radio433::Radio433(QObject *parent) + +Radio433::Radio433(QObject *parent) : + QObject(parent) { + // Set up receiver + m_receiverThread = new QThread(this); + m_receiver = new Gpio(0,27); + m_receiver->setDirection(INPUT); + m_receiver->setEdgeInterrupt(EDGE_BOTH); + m_receiver->moveToThread(m_receiverThread); + // Set up transmitter + m_transmitter = new Gpio(this,22); + m_transmitter->setDirection(OUTPUT); + m_transmitter->setValue(LOW); + + connect(m_receiverThread,SIGNAL(finished()),this,SLOT(deleteLater())); + connect(m_receiver,SIGNAL(pinInterrupt()),this,SLOT(handleInterrupt())); + + enableReceiver(); +} + +Radio433::~Radio433() +{ + m_receiverThread->quit(); + m_receiverThread->wait(); } void Radio433::sendData(QList rawData) { + + //first we have to disable our receiver, to prevent reading the hive signal it self + disableReceiver(); + + m_transmitter->setValue(LOW); + delayMicroseconds(500); + + int flag=1; + foreach (int delay, rawData) { + // 1 = High, 0 = Low + m_transmitter->setValue(flag++ %2); + delayMicroseconds(delay); + } + + // reenable it + enableReceiver(); + +} + +int Radio433::micros() +{ + struct timeval tv ; + int now ; + + gettimeofday (&tv, NULL) ; + now = (int)tv.tv_sec * (int)1000000 + (int)tv.tv_usec ; + + return (int)(now - m_epochMicro) ; +} + +void Radio433::delayMicroseconds(int pulseLength) +{ + struct timespec sleeper ; + + if(pulseLength <= 0){ + return; + }else { + if(pulseLength < 100){ + struct timeval tNow, tLong, tEnd ; + + gettimeofday (&tNow, NULL) ; + tLong.tv_sec = pulseLength / 1000000 ; + tLong.tv_usec = pulseLength % 1000000 ; + timeradd (&tNow, &tLong, &tEnd) ; + + while (timercmp (&tNow, &tEnd, <)){ + gettimeofday (&tNow, NULL) ; + } + } + sleeper.tv_sec = 0 ; + sleeper.tv_nsec = (long)(pulseLength * 1000) ; + nanosleep (&sleeper, NULL) ; + } +} + + +void Radio433::handleInterrupt() +{ + long currentTime = micros(); + m_duration = currentTime - m_lastTime; + + // filter nois + if (m_duration > 5000 && m_duration > m_timings[0] - 200 && m_duration < m_timings[0] + 200) { + m_repeatCount++; + m_changeCount--; + + if(m_repeatCount == 2) { + // if we have a regular signal (1 bit sync + 48 bit data) + if(m_changeCount == RC_MAX_CHANGES){ + // write rawdata to a List and reset values to 0 + QList rawData; + for(int i = 0; i < RC_MAX_CHANGES; i++ ){ + rawData.append(m_timings[i]); + m_timings[i] = 0; + } + qDebug() << "-----------------------------------------------------------"; + qDebug() << "| GENERIC signal |"; + qDebug() << "-----------------------------------------------------------"; + qDebug() << "delay :" << rawData.first() /31; + qDebug() << rawData; + + emit dataReceived(rawData); + } + m_repeatCount = 0; + } + m_changeCount = 0; + + }else if(m_duration > 5000){ + m_changeCount = 0; + } + if (m_changeCount > RC_MAX_CHANGES) { + m_changeCount = 0; + m_repeatCount = 0; + } + m_timings[m_changeCount++] = m_duration; + m_lastTime = currentTime; +} + +void Radio433::enableReceiver() +{ + m_receiverThread->start(); + m_receiver->enableInterrupt(); + qDebug() << "receiver enabeld."; +} + +void Radio433::disableReceiver() +{ + m_receiverThread->quit(); + m_receiverThread->wait(); + qDebug() << "receiver disabeld."; } diff --git a/server/radio433.h b/server/radio433.h index 2cb119ce..6324866b 100644 --- a/server/radio433.h +++ b/server/radio433.h @@ -2,6 +2,10 @@ #define RADIO433_h #include +#include +#include + +#define RC_MAX_CHANGES 49 class Radio433: public QObject { @@ -9,10 +13,34 @@ class Radio433: public QObject public: Radio433(QObject *parent = 0); + ~Radio433(); public: void sendData(QList rawData); +private: + Gpio *m_receiver; + Gpio *m_transmitter; + QThread *m_receiverThread; + + unsigned int m_timings[RC_MAX_CHANGES]; + unsigned int m_duration; + unsigned int m_changeCount; + unsigned long m_lastTime; + unsigned int m_repeatCount; + unsigned int m_epochMicro; + + int micros(); + void delayMicroseconds(int pulseLength); + + void enableReceiver(); + void disableReceiver(); + + +private slots: + void handleInterrupt(); + + signals: void dataReceived(QList rawData); }; diff --git a/server/server.pro b/server/server.pro index afc2ca81..88f169b5 100644 --- a/server/server.pro +++ b/server/server.pro @@ -1,10 +1,11 @@ -include(../common.pri) - TARGET = hive TEMPLATE = app INCLUDEPATH += ../libhive +target.path = /usr/bin +INSTALLS += target + QT += network LIBS += -L../libhive/ -lhive @@ -13,9 +14,11 @@ SOURCES += main.cpp \ hivecore.cpp \ jsonrpcserver.cpp \ radio433.cpp \ - tcpserver.cpp + tcpserver.cpp \ + gpio.cpp HEADERS += hivecore.h \ jsonrpcserver.h \ radio433.h \ - tcpserver.h + tcpserver.h \ + gpio.h