fixed radio433 and added Radio 433 brennenstuhl LAN gateway

This commit is contained in:
Simon Stürz 2014-10-09 16:04:43 +02:00 committed by Michael Zanetti
parent 6db7e97940
commit 0fda5f99e1
21 changed files with 600 additions and 298 deletions

View File

@ -75,7 +75,7 @@
#include "devicemanager.h"
#include "hardware/radio433.h"
#include "hardware/radio433/radio433.h"
#include "plugin/device.h"
#include "plugin/deviceclass.h"
@ -845,8 +845,10 @@ QPair<DeviceManager::DeviceSetupStatus,QString> DeviceManager::setupDevice(Devic
if (plugin->requiredHardware().testFlag(HardwareResourceRadio433)) {
if (!m_radio433) {
m_radio433 = new Radio433();
m_radio433 = new Radio433(this);
connect(m_radio433, &Radio433::dataReceived, this, &DeviceManager::radio433SignalReceived);
m_radio433->enable();
// TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something...
}
}

View File

@ -58,6 +58,7 @@ public:
DeviceErrorDuplicateUuid,
DeviceErrorCreationMethodNotSupported,
DeviceErrorActionParameterError,
DeviceErrorHardwareNotAvailable,
DeviceErrorDeviceDescriptorNotFound,
DeviceErrorAsync,
DeviceErrorPairingTransactionIdNotFound,

View File

@ -57,7 +57,7 @@ bool Gpio::exportGpio()
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio/export";
//qDebug() << "ERROR: could not open /sys/class/gpio/export";
return false;
}
@ -75,7 +75,7 @@ bool Gpio::unexportGpio()
int fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio/unexport";
//qDebug() << "ERROR: could not open /sys/class/gpio/unexport";
return false;
}
int len = snprintf(buf, sizeof(buf), "%d", m_gpio);
@ -94,10 +94,10 @@ int Gpio::openGpio()
int fd = open(buf, O_RDONLY | O_NONBLOCK );
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction";
return false;
//qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction";
return fd;
}
return true;
return fd;
}
/*! Returns true, if the direction \a dir of the GPIO could be set correctly.
@ -122,7 +122,7 @@ bool Gpio::setDirection(int dir)
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction";
//qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction";
return false;
}
if(dir == INPUT){
@ -164,7 +164,7 @@ bool Gpio::setValue(unsigned int value)
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value";
//qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value";
return false;
}
@ -208,7 +208,7 @@ int Gpio::getValue()
int fd = open(buf, O_RDONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value";
//qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value";
return -1;
}
char ch;
@ -222,7 +222,7 @@ int Gpio::getValue()
}
close(fd);
qDebug() << "gpio" << m_gpio << "value = " << value;
//qDebug() << "gpio" << m_gpio << "value = " << value;
return value;
}
@ -252,7 +252,7 @@ bool Gpio::setEdgeInterrupt(int edge)
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge";
//qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge";
return false;
}

View File

@ -42,6 +42,7 @@
#define EDGE_BOTH 2
/**********************************
* Raspberry Pi Rev. 2.0
* ______________________
* |______________________|
* | File NR. | PIN NR. |

View File

@ -0,0 +1,111 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class Radio433
\brief The Radio433 class helps to interact with the 433 MHz Receiver and Transmitter.
\inmodule libguh
*/
#include "radio433.h"
Radio433::Radio433(QObject *parent) :
QObject(parent)
{
m_receiver = new Radio433Receiver(this,27);
m_transmitter = new Radio433Trasmitter(this,22);
m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this);
connect(m_receiver, &Radio433Receiver::readingChanged, this, &Radio433::readingChanged);
connect(m_receiver, &Radio433Receiver::dataReceived, this, &Radio433::dataReceived);
connect(m_brennenstuhlTransmitter, &Radio433BrennenstuhlGateway::availableChanged, this, &Radio433::brennenstuhlAvailableChanged);
}
Radio433::~Radio433()
{
m_receiver->quit();
m_transmitter->quit();
}
bool Radio433::enable()
{
m_brennenstuhlTransmitter->enable();
bool receiverAvailable = m_receiver->startReceiver();
if(!receiverAvailable){
//qWarning() << "ERROR: radio 433 MHz receiver not available on GPIO's";
}
bool transmitterAvailable = m_transmitter->startTransmitter();
if(!transmitterAvailable){
//qWarning() << "ERROR: radio 433 MHz transmitter not available on GPIO's";
}
if(!receiverAvailable && !transmitterAvailable){
qWarning() << "--> Radio 433 MHz GPIO's not available.";
return false;
}
qDebug() << "--> Radio 433 MHz GPIO's enabled.";
return true;
}
bool Radio433::disabel()
{
m_brennenstuhlTransmitter->disable();
if(m_receiver->stopReceiver()){
return true;
}
return false;
}
void Radio433::readingChanged(bool reading)
{
if(reading){
m_transmitter->allowSending(false);
}else{
m_transmitter->allowSending(true);
}
}
void Radio433::brennenstuhlAvailableChanged()
{
if(m_brennenstuhlTransmitter->available()){
qDebug() << "--> Radio 433 MHz Brennenstuhl LAN Gateway available.";
}else{
qDebug() << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available.";
}
}
bool Radio433::sendData(int delay, QList<int> rawData)
{
bool sendGpio = false;
bool sendBrennenstuhl = false;
if(m_brennenstuhlTransmitter->available()){
sendBrennenstuhl = m_brennenstuhlTransmitter->sendData(delay, rawData);
}
if(m_transmitter->available()){
m_transmitter->sendData(delay, rawData);
sendGpio = true;
}
return (sendGpio || sendBrennenstuhl);
}

View File

@ -23,6 +23,7 @@
#include "radio433receiver.h"
#include "radio433transmitter.h"
#include "radio433brennenstuhlgateway.h"
class Radio433 : public QObject
{
@ -32,21 +33,23 @@ public:
~Radio433();
bool available();
bool enabel();
bool enable();
bool disabel();
private:
Radio433Receiver *m_receiver;
Radio433Trasmitter *m_transmitter;
Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter;
signals:
void dataReceived(QList<int> rawData);
private slots:
void readingChanged(bool reading);
void brennenstuhlAvailableChanged();
public slots:
void sendData(QList<int> rawData);
bool sendData(int delay, QList<int> rawData);
};

View File

@ -0,0 +1,154 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "radio433brennenstuhlgateway.h"
Radio433BrennenstuhlGateway::Radio433BrennenstuhlGateway(QObject *parent) :
QObject(parent)
{
m_gatewayDiscovery = new QUdpSocket(this);
m_gateway = new QUdpSocket(this);
// connect(m_gateway, &QUdpSocket::error, this, &Radio433BrennenstuhlGateway::gatewayError) -> does not work...runtime connection error.
connect(m_gateway, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(gatewayError(QAbstractSocket::SocketError)));
m_available = false;
// TODO: maby enable or disable hardware search if the usern knows that he has not this gateway...
// TODO: auto rediscover if lost connection
}
bool Radio433BrennenstuhlGateway::sendData(int delay, QList<int> rawData)
{
if(m_gateway){
QByteArray data;
QByteArray message;
// bring rawData list to a single ByteArray, values separated by ','
foreach (int value, rawData) {
data.append(QString::number(value) + ",");
}
/* Protocol:
* Elro Example
* "TXP:0,0,10,0,350,25, 1,31,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,1,3,1,3,3,1,1,3,3,1,1,3,3,1,1,3,1,3,1,3,3,1, ;"
*
* TXP: | send command
* 0,0 | unknown
* 10, | repeatings of command
* 0 | pause between 2 commands [us]
* 350 | delayLength [us]
* 25 | number of bits to send (2 sync timings + 48 data timings = 50 timongis ..... 1 bit = 2 timings -> 25 bit)
* 1,3,3,...| pulse data starting with HIGH (1* delayLength HIGH, 3 * delayLength LOW ....)
* ; | end of command
*/
message.append("TXP:0,0,10,0," + QString::number(delay) + "," + QString::number(rawData.count()/2) + "," + data + ";");
if(m_gateway->writeDatagram(message,m_gatewayAddress,m_gatewayPort) > 0){
m_available = true;
return true;
}else{
return false;
}
}
}
bool Radio433BrennenstuhlGateway::enable()
{
if(!m_gatewayDiscovery->bind(49880, QUdpSocket::ShareAddress)){
qWarning() << "ERROR: Radio 433 MHz Brennenstuhl LAN Gateway discovery could not bind to port 49880";
return false;
}
connect(m_gatewayDiscovery, &QUdpSocket::readyRead, this, &Radio433BrennenstuhlGateway::readDataDiscovery);
discover();
}
bool Radio433BrennenstuhlGateway::disable()
{
m_gateway->close();
m_gatewayDiscovery->close();
}
void Radio433BrennenstuhlGateway::discover()
{
// send search string to broadcast over port 49880
m_gatewayDiscovery->writeDatagram("SEARCH HCGW", QHostAddress::Broadcast, 49880);
}
bool Radio433BrennenstuhlGateway::available()
{
return m_available;
}
void Radio433BrennenstuhlGateway::gatewayDiscovered(QHostAddress address, int port)
{
m_gatewayAddress = address;
m_gatewayPort = port;
if(!m_gateway->bind(m_gatewayPort,QUdpSocket::ShareAddress)){
qWarning() << "ERROR: Radio 433 MHz Brennenstuhl LAN Gateway could not bind to port " << m_gatewayPort;
m_available = false;
emit availableChanged();
return;
}
m_available = true;
emit availableChanged();
connect(m_gateway, &QUdpSocket::readyRead, this, &Radio433BrennenstuhlGateway::readDataGateway);
}
void Radio433BrennenstuhlGateway::readDataDiscovery()
{
QByteArray data;
QHostAddress address;
quint16 port;
// read the answere from the
while (m_gatewayDiscovery->hasPendingDatagrams()) {
data.resize(m_gatewayDiscovery->pendingDatagramSize());
m_gatewayDiscovery->readDatagram(data.data(), data.size(), &address, &port);
}
if(data.startsWith("HCGW:")){
// qDebug() << "found Brennenstuhl LAN gateway: " << address.toString() << port;
gatewayDiscovered(address,port);
}
}
void Radio433BrennenstuhlGateway::readDataGateway()
{
QByteArray data;
QHostAddress sender;
quint16 udpPort;
// read the answere from the
while (m_gateway->hasPendingDatagrams()) {
data.resize(m_gateway->pendingDatagramSize());
m_gateway->readDatagram(data.data(), data.size(), &sender, &udpPort);
}
}
void Radio433BrennenstuhlGateway::gatewayError(QAbstractSocket::SocketError error)
{
QUdpSocket *gateway = static_cast<QUdpSocket*>(sender());
qDebug() << "--> ERROR: Radio 433 MHz Brennenstuhl LAN Gateway disabled: " << gateway->errorString();
m_available = false;
}

View File

@ -16,68 +16,43 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class Radio433
\brief The Radio433 class helps to interact with the 433 MHz Receiver and Transmitter.
#ifndef RADIO433BRENNENSTUHLGATEWAY_H
#define RADIO433BRENNENSTUHLGATEWAY_H
\inmodule libguh
#include <QObject>
#include <QUdpSocket>
#include <QHostAddress>
*/
#include "radio433.h"
Radio433::Radio433(QObject *parent) :
QObject(parent)
class Radio433BrennenstuhlGateway : public QObject
{
m_receiver = new Radio433Receiver();
m_transmitter = new Radio433Trasmitter();
Q_OBJECT
public:
explicit Radio433BrennenstuhlGateway(QObject *parent = 0);
connect(m_receiver,SIGNAL(readingChanged(bool)),this,SLOT(readingChanged(bool)));
}
bool sendData(int delay, QList<int> rawData);
bool enable();
bool disable();
bool available();
Radio433::~Radio433()
{
m_receiver->wait();
m_receiver->quit();
private:
bool m_available;
QUdpSocket *m_gatewayDiscovery;
QUdpSocket *m_gateway;
m_transmitter->wait();
m_transmitter->quit();
}
int m_gatewayPort;
QHostAddress m_gatewayAddress;
bool Radio433::available()
{
if(m_receiver->setUpGpio() && m_transmitter->setUpGpio()){
return true;
}
return false;
}
void discover();
void gatewayDiscovered(QHostAddress address, int port);
bool Radio433::enabel()
{
if(m_receiver->startReceiver() && m_transmitter->startTransmitter()){
return true;
}
return false;
}
signals:
void availableChanged();
bool Radio433::disabel()
{
if(m_receiver->stopReceiver() && m_transmitter->stopTransmitter()){
return true;
}
return false;
}
private slots:
void readDataDiscovery();
void readDataGateway();
void gatewayError(QAbstractSocket::SocketError error);
void Radio433::readingChanged(bool reading)
{
if(reading){
m_transmitter->allowSending(false);
}else{
m_transmitter->allowSending(true);
}
}
};
void Radio433::sendData(QList<int> rawData)
{
m_transmitter->sendData(rawData);
}
#endif // RADIO433BRENNENSTUHLGATEWAY_H

View File

@ -26,35 +26,21 @@
Radio433Receiver::Radio433Receiver(QObject *parent, int gpio) :
QThread(parent),m_gpioPin(gpio)
{
m_gpio = new Gpio(this,m_gpioPin);
stopReceiver();
m_timings.clear();
m_available = false;
connect(this,SIGNAL(timingReady(int)),this,SLOT(handleTiming(int)),Qt::DirectConnection);
m_mutex.lock();
m_enabled = false;
m_mutex.unlock();
connect(this, &Radio433Receiver::timingReady, this, &Radio433Receiver::handleTiming, Qt::DirectConnection);
}
Radio433Receiver::~Radio433Receiver()
{
}
bool Radio433Receiver::setUpGpio()
{
if(!m_gpio->exportGpio()){
return false;
}else{
m_gpio->setDirection(INPUT);
m_gpio->setEdgeInterrupt(EDGE_BOTH);
}
return true;
}
bool Radio433Receiver::startReceiver()
{
if(setUpGpio()){
m_timings.clear();
run();
return true;
}
return false;
quit();
wait();
deleteLater();
}
bool Radio433Receiver::stopReceiver()
@ -62,10 +48,14 @@ bool Radio433Receiver::stopReceiver()
m_mutex.lock();
m_enabled = false;
m_mutex.unlock();
return true;
}
bool Radio433Receiver::available()
{
return m_available;
}
void Radio433Receiver::run()
{
struct pollfd fdset[2];
@ -73,13 +63,12 @@ void Radio433Receiver::run()
char buf[1];
bool enabled = true;
m_mutex.lock();
m_enabled = true;
m_mutex.unlock();
int lastTime = micros();
// poll the gpio file, if something changes...emit the signal wit the current pulse length
// poll the gpio file, if something changes...emit the signal with the current pulse length
while(enabled){
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
@ -87,7 +76,7 @@ void Radio433Receiver::run()
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
int rc = poll(fdset, 2, 3000);
int rc = poll(fdset, 2, 1000);
if (rc < 0) {
qDebug() << "ERROR: poll failed";
@ -110,6 +99,34 @@ void Radio433Receiver::run()
}
}
bool Radio433Receiver::setUpGpio()
{
if(!m_gpio){
m_gpio = new Gpio(this,m_gpioPin);
}
if(!m_gpio->exportGpio() || !m_gpio->setDirection(INPUT) || !m_gpio->setEdgeInterrupt(EDGE_BOTH)){
return false;
}
return true;
}
bool Radio433Receiver::startReceiver()
{
if(!setUpGpio()){
m_available = false;
return false;
}
m_mutex.lock();
m_enabled = true;
m_mutex.unlock();
m_available = true;
start();
return true;
}
int Radio433Receiver::micros()
{
struct timeval tv ;
@ -122,8 +139,8 @@ int Radio433Receiver::micros()
bool Radio433Receiver::valueInTolerance(int value, int sollValue)
{
// in in range of +- 35% of sollValue return true, eles return false
if(value >= (double)sollValue-200 && value <= (double)sollValue+200){
// in in range of +- 200 [us] of sollValue return true, eles return false
if(value >= (double)sollValue - 200 && value <= (double)sollValue + 200){
return true;
}
return false;
@ -167,15 +184,17 @@ void Radio433Receiver::changeReading(bool reading)
{
if(reading != m_reading){
m_reading = reading;
emit readingChanged(reading);
//TODO: create colission detection
//emit readingChanged(reading);
}
}
void Radio433Receiver::handleTiming(int duration)
{
// to short...
if(duration < 50){
if(duration < 60){
changeReading(false);
m_timings.clear();
return;
@ -192,14 +211,14 @@ void Radio433Receiver::handleTiming(int duration)
if(!m_timings.isEmpty() && sync){
// 1 sync bit + 48 data bit
if(m_timings.count() == 49 && checkValues(Protocol48)){
qDebug() << "48 bit ->" << m_timings << "\n--------------------------";
//qDebug() << "48 bit ->" << m_timings << "\n--------------------------";
changeReading(false);
emit dataReceived(m_timings);
}
// 1 sync bit + 64 data bit
if(m_timings.count() == 65 && checkValues(Protocol64)){
qDebug() << "64 bit ->" << m_timings << "\n--------------------------";
//qDebug() << "64 bit ->" << m_timings << "\n--------------------------";
changeReading(false);
emit dataReceived(m_timings);
}
@ -224,22 +243,23 @@ void Radio433Receiver::handleTiming(int duration)
// check if it could be a signal -> if we have a sync and 15 valid values
// set reading true to prevent a collision from own transmitter
if(m_timings.count() > 20 && (checkValues(Protocol48) || checkValues(Protocol64))){
if(m_timings.count() == 20 && (checkValues(Protocol48) || checkValues(Protocol64))){
changeReading(true);
}
// check if we have allready a vallid protocol
// 1 sync bit + 48 data bit
if(m_timings.count() == 49 && checkValues(Protocol48)){
qDebug() << "48 bit -> " << m_timings << "\n--------------------------";
//qDebug() << "48 bit -> " << m_timings << "\n--------------------------";
emit dataReceived(m_timings);
}
// 1 sync bit + 64 data bit
if(m_timings.count() == 65 && checkValues(Protocol64)){
qDebug() << "64 bit -> " << m_timings << "\n--------------------------";
//qDebug() << "64 bit -> " << m_timings << "\n--------------------------";
changeReading(false);
emit dataReceived(m_timings);
m_timings.clear();
}
}
}

View File

@ -21,7 +21,7 @@
#include <QThread>
#include "gpio.h"
#include "../gpio.h"
class Radio433Receiver : public QThread
{
@ -36,9 +36,12 @@ public:
ProtocolNone
};
bool setUpGpio();
bool startReceiver();
bool stopReceiver();
bool available();
protected:
void run() override;
private:
int m_gpioPin;
@ -52,9 +55,10 @@ private:
QMutex m_mutex;
bool m_enabled;
bool m_available;
bool m_reading;
void run();
bool setUpGpio();
int micros();
bool valueInTolerance(int value, int sollValue);
bool checkValue(int value);

View File

@ -21,105 +21,50 @@
Radio433Trasmitter::Radio433Trasmitter(QObject *parent, int gpio) :
QThread(parent),m_gpioPin(gpio)
{
m_gpio = new Gpio(this,m_gpioPin);
stopTransmitter();
}
Radio433Trasmitter::~Radio433Trasmitter()
{
quit();
wait();
deleteLater();
}
bool Radio433Trasmitter::startTransmitter()
{
if(setUpGpio()){
run();
return true;
}
return false;
return setUpGpio();
}
bool Radio433Trasmitter::stopTransmitter()
bool Radio433Trasmitter::available()
{
m_mutex.lock();
m_enabled = false;
m_mutex.unlock();
return true;
}
bool Radio433Trasmitter::setUpGpio()
{
if(!m_gpio->exportGpio()){
return false;
}else{
m_gpio->setDirection(OUTPUT);
m_gpio->setValue(LOW);
}
return true;
}
void Radio433Trasmitter::sendData(QList<int> rawData)
{
m_queueMutex.lock();
m_rawDataQueue.enqueue(rawData);
m_queueMutex.unlock();
return m_available;
}
void Radio433Trasmitter::run()
{
bool enabled = true;
m_mutex.lock();
m_enabled = true;
m_mutex.unlock();
QList<int> rawData;
while(enabled){
m_queueMutex.lock();
while(!m_rawDataQueue.isEmpty()){
m_queueMutex.lock();
m_allowSendingMutex.lock();
//check if we have data in the sending queue and we are allowed to send...
if(!m_rawDataQueue.isEmpty() && m_allowSending){
m_allowSendingMutex.unlock();
rawData = m_rawDataQueue.dequeue();
m_queueMutex.unlock();
m_gpio->setValue(LOW);
int flag=1;
// send raw data 8 times
for(int i = 0; i <= 8; i++){
foreach (int delay, rawData) {
// 1 = High, 0 = Low
m_gpio->setValue(flag %2);
flag++;
usleep(delay);
}
//check if we can continue or we should stop
m_allowSendingMutex.lock();
if(!m_allowSending){
m_allowSendingMutex.unlock();
break;
}
m_allowSendingMutex.unlock();
}
m_gpio->setValue(LOW);
}else{
m_queueMutex.unlock();
m_allowSendingMutex.unlock();
break;
}
rawData = m_rawDataQueue.dequeue();
m_queueMutex.unlock();
m_allowSendingMutex.unlock();
m_mutex.lock();
enabled = m_enabled;
m_mutex.unlock();
m_gpio->setValue(LOW);
int flag=1;
// send raw data 10 times
for(int i = 0; i < 10; i++){
foreach (int delay, rawData) {
// 1 = High, 0 = Low
m_gpio->setValue(flag %2);
flag++;
usleep(delay);
}
}
m_gpio->setValue(LOW);
}
m_queueMutex.unlock();
}
void Radio433Trasmitter::allowSending(bool sending)
@ -128,3 +73,31 @@ void Radio433Trasmitter::allowSending(bool sending)
m_allowSending = sending;
m_allowSendingMutex.unlock();
}
bool Radio433Trasmitter::setUpGpio()
{
m_gpio = new Gpio(this,m_gpioPin);
if(!m_gpio->exportGpio() || !m_gpio->setDirection(OUTPUT) || !m_gpio->setValue(LOW)){
m_available = false;
return false;
}
m_available = true;
return true;
}
void Radio433Trasmitter::sendData(int delay, QList<int> rawData)
{
QList<int> timings;
foreach (int data, rawData) {
timings.append(delay*data);
}
m_queueMutex.lock();
m_rawDataQueue.enqueue(timings);
m_queueMutex.unlock();
if(!isRunning()){
start();
}
}

View File

@ -25,7 +25,7 @@
#include <QQueue>
#include <QDebug>
#include "gpio.h"
#include "../gpio.h"
class Radio433Trasmitter : public QThread
@ -36,10 +36,12 @@ public:
~Radio433Trasmitter();
bool startTransmitter();
bool stopTransmitter();
bool setUpGpio();
bool available();
void sendData(QList<int> rawData);
void sendData(int delay, QList<int> rawData);
protected:
void run();
private:
int m_gpioPin;
@ -51,16 +53,17 @@ private:
QMutex m_allowSendingMutex;
bool m_allowSending;
void run();
QMutex m_queueMutex;
QQueue<QList<int> > m_rawDataQueue;
bool m_available;
bool setUpGpio();
signals:
public slots:
void allowSending(bool sending);
};
#endif // RADIO433TRASMITTER_H

View File

@ -5,6 +5,8 @@ TEMPLATE = lib
CONFIG += c++11
QT += network
target.path = /usr/lib
INSTALLS += target
@ -14,9 +16,10 @@ SOURCES += plugin/device.cpp \
plugin/devicedescriptor.cpp \
devicemanager.cpp \
hardware/gpio.cpp \
hardware/radio433.cpp \
hardware/radio433transmitter.cpp \
hardware/radio433receiver.cpp \
hardware/radio433/radio433.cpp \
hardware/radio433/radio433transmitter.cpp \
hardware/radio433/radio433receiver.cpp \
hardware/radio433/radio433brennenstuhlgateway.cpp \
types/action.cpp \
types/actiontype.cpp \
types/state.cpp \
@ -28,7 +31,7 @@ SOURCES += plugin/device.cpp \
types/paramtype.cpp \
types/param.cpp \
types/paramdescriptor.cpp \
types/statedescriptor.cpp \
types/statedescriptor.cpp
HEADERS += plugin/device.h \
plugin/deviceclass.h \
@ -36,9 +39,10 @@ HEADERS += plugin/device.h \
plugin/devicedescriptor.h \
devicemanager.h \
hardware/gpio.h \
hardware/radio433.h \
hardware/radio433transmitter.h \
hardware/radio433receiver.h \
hardware/radio433/radio433.h \
hardware/radio433/radio433transmitter.h \
hardware/radio433/radio433receiver.h \
hardware/radio433/radio433brennenstuhlgateway.h \
types/action.h \
types/actiontype.h \
types/state.h \
@ -51,5 +55,5 @@ HEADERS += plugin/device.h \
types/paramtype.h \
types/param.h \
types/paramdescriptor.h \
types/statedescriptor.h \
types/statedescriptor.h

View File

@ -107,7 +107,7 @@ pure virtual methods: \l{DevicePlugin::pluginName()}, \l{DevicePlugin::pluginId(
#include "deviceplugin.h"
#include "devicemanager.h"
#include "hardware/radio433.h"
#include "hardware/radio433/radio433.h"
#include <QDebug>
@ -332,18 +332,19 @@ Device *DevicePlugin::findDeviceByParams(const ParamList &params) const
devices, depending on the hardware requested by this plugin.
\sa DevicePlugin::requiredHardware()
*/
void DevicePlugin::transmitData(QList<int> rawData)
bool DevicePlugin::transmitData(int delay, QList<int> rawData)
{
switch (requiredHardware()) {
case DeviceManager::HardwareResourceRadio433:
deviceManager()->m_radio433->sendData(rawData);
break;
return deviceManager()->m_radio433->sendData(delay, rawData);
case DeviceManager::HardwareResourceRadio868:
qDebug() << "Radio868 not connected yet";
break;
return false;
default:
qWarning() << "Unknown harware type. Cannot send.";
}
return false;
}
/*!

View File

@ -58,7 +58,7 @@ public:
virtual QPair<DeviceManager::DeviceSetupStatus, QString> confirmPairing(const QUuid &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params);
// Hardware input
virtual void radioData(QList<int> rawData) {Q_UNUSED(rawData)}
virtual void radioData(const QList<int> &rawData) {Q_UNUSED(rawData)}
virtual void guhTimer() {}
// Configuration
@ -88,7 +88,7 @@ protected:
QList<Device*> myDevices() const;
Device* findDeviceByParams(const ParamList &params) const;
void transmitData(QList<int> rawData);
bool transmitData(int delay, QList<int> rawData);
QPair<DeviceManager::DeviceError, QString> report(DeviceManager::DeviceError error = DeviceManager::DeviceErrorNoError, const QString &message = QString());
QPair<DeviceManager::DeviceSetupStatus, QString> reportDeviceSetup(DeviceManager::DeviceSetupStatus status = DeviceManager::DeviceSetupStatusSuccess, const QString &message = QString());

View File

@ -54,7 +54,6 @@
#include "devicemanager.h"
#include "plugin/device.h"
#include "hardware/radio433.h"
#include "types/paramtype.h"
#include <QDebug>
@ -64,7 +63,7 @@
VendorId conradVendorId = VendorId("986cf06f-3ef1-4271-b2a3-2cc277ebecb6");
DeviceClassId conradRemoteId = DeviceClassId("17cd2492-28ab-4827-ba6e-5ef35be23f1b");
EventTypeId conradRemoteButtonEventTypeId = EventTypeId("1f4050f5-4c90-4799-8d6d-e4069f3a2519");
ActionTypeId conradRemoteActionTypeId = ActionTypeId("2a3638b4-fbd6-4fdb-a3c9-7fa49705d1a3");
DevicePluginConrad::DevicePluginConrad()
{
}
@ -72,8 +71,7 @@ DevicePluginConrad::DevicePluginConrad()
QList<Vendor> DevicePluginConrad::supportedVendors() const
{
QList<Vendor> ret;
Vendor conrad(conradVendorId, "Conrad Electronic SE");
ret.append(conrad);
ret.append(Vendor(conradVendorId, "Conrad Electronic SE"));
return ret;
}
@ -96,6 +94,21 @@ QList<DeviceClass> DevicePluginConrad::supportedDevices() const
nameParam.insert("type", "string");
deviceParamRemote.append(nameParam);
QList<ParamType> actionParamsRemote;
ParamType actionParamRemote("power", QVariant::Bool);
actionParamsRemote.append(actionParamRemote);
// Actions
QList<ActionType> remoteActions;
ActionType powerAction(conradRemoteActionTypeId);
powerAction.setName("power");
powerAction.setParameters(actionParamsRemote);
remoteActions.append(powerAction);
deviceClassConradRemote.setActions(remoteActions);
// Events
QList<EventType> buttonEvents;
@ -138,31 +151,76 @@ PluginId DevicePluginConrad::pluginId() const
QPair<DeviceManager::DeviceError, QString> DevicePluginConrad::executeAction(Device *device, const Action &action)
{
QList<int> rawData;
QByteArray binCode;
return report();
if(action.param("power").value().toBool()){
binCode = "10010011";
}else{
binCode = "10100011";
}
// append ID
QByteArray remoteId = "100101010110011000000001";
QByteArray motionDetectorId = "100100100101101101101010";
QByteArray wallSwitchId = "000001001101000010110110";
QByteArray randomID = "100010101010111010101010";
binCode.append(wallSwitchId);
// =======================================
//create rawData timings list
int delay = 650;
// sync signal
rawData.append(1);
rawData.append(10);
// add the code
foreach (QChar c, binCode) {
if(c == '0'){
rawData.append(1);
rawData.append(2);
}
if(c == '1'){
rawData.append(2);
rawData.append(1);
}
}
// =======================================
// send data to driver
if(transmitData(delay, rawData)){
qDebug() << "action" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report();
}else{
qDebug() << "could not transmitt" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report(DeviceManager::DeviceErrorHardwareNotAvailable, "Radio 433 MHz transmitter not available.");
}
}
void DevicePluginConrad::radioData(QList<int> rawData)
void DevicePluginConrad::radioData(const QList<int> &rawData)
{
// filter right here a wrong signal length
if(rawData.length() != 65){
return;
}
// qDebug() << rawData;
int delay = rawData.first()/10;
QByteArray binCode;
// =======================================
// average 314
if(delay > 690 && delay < 750){
// average 650
if(delay > 600 && delay < 750){
// go trough all 64 timings (without sync signal)
for(int i = 1; i <= 64; i+=2 ){
int div;
int divNext;
// if short
if(rawData.at(i) <= 900){
div = 1;
@ -175,12 +233,12 @@ void DevicePluginConrad::radioData(QList<int> rawData)
}else{
divNext = 2;
}
// _
// if we have | |__ = 0 -> in 4 delays => 100
// __
// if we have | |_ = 1 -> in 4 delays => 110
if(div == 1 && divNext == 2){
binCode.append('0');
}else if(div == 2 && divNext == 1){
@ -193,20 +251,16 @@ void DevicePluginConrad::radioData(QList<int> rawData)
return;
}
qDebug() << "CONRAD plugin understands this protocol: " << binCode;
qDebug() << "CONRAD: " << binCode.left(binCode.length() - 24) << " ID = " << binCode.right(24);
// // FIXME: find a better way to get to the remote DeviceClass
// DeviceClass deviceClass = supportedDevices().first();
// foreach (const EventType &eventType, deviceClass.events()) {
// if (eventType.name() == buttonCode) {
// qDebug() << "emit event " << pluginName() << familyCode << eventType.name() << power;
// Event event = Event(eventType.id(), device->id(), params);
// emit emitEvent(event);
// return;
// }
// }
// // FIXME: find a better way to get to the remote DeviceClass
// DeviceClass deviceClass = supportedDevices().first();
// foreach (const EventType &eventType, deviceClass.events()) {
// if (eventType.name() == buttonCode) {
// qDebug() << "emit event " << pluginName() << familyCode << eventType.name() << power;
// Event event = Event(eventType.id(), device->id(), params);
// emit emitEvent(event);
// return;
// }
// }
}

View File

@ -38,7 +38,7 @@ public:
QString pluginName() const override;
PluginId pluginId() const override;
void radioData(QList<int> rawData) override;
void radioData(const QList<int> &rawData) override;
public slots:
QPair<DeviceManager::DeviceError, QString> executeAction(Device *device, const Action &action) override;

View File

@ -51,10 +51,7 @@
*/
#include "devicepluginelro.h"
#include "devicemanager.h"
#include "plugin/device.h"
#include "hardware/radio433.h"
#include <QDebug>
#include <QStringList>
@ -79,10 +76,6 @@ QList<Vendor> DevicePluginElro::supportedVendors() const
{
QList<Vendor> ret;
ret.append(Vendor(elroVendorId, "Elro"));
ret.append(Vendor(mumbiVendorId, "Mumbi"));
ret.append(Vendor(vivancoVendorId, "Vivanco"));
ret.append(Vendor(brennenstuhlVendorId, "Brennenstuhl"));
ret.append(Vendor(batVendorId, "BAT"));
return ret;
}
@ -97,15 +90,15 @@ QList<DeviceClass> DevicePluginElro::supportedDevices() const
deviceClassElroRemote.setName("Elro Remote");
QList<ParamType> deviceParamsRemote;
ParamType channelParam = ParamType("channel1", QVariant::Bool);
ParamType channelParam = ParamType("channel 1", QVariant::Bool);
deviceParamsRemote.append(channelParam);
channelParam = ParamType("channel2", QVariant::Bool);
channelParam = ParamType("channel 2", QVariant::Bool);
deviceParamsRemote.append(channelParam);
channelParam = ParamType("channel3", QVariant::Bool);
channelParam = ParamType("channel 3", QVariant::Bool);
deviceParamsRemote.append(channelParam);
channelParam = ParamType("channel4", QVariant::Bool);
channelParam = ParamType("channel 4", QVariant::Bool);
deviceParamsRemote.append(channelParam);
channelParam = ParamType("channel5", QVariant::Bool);
channelParam = ParamType("channel 5", QVariant::Bool);
deviceParamsRemote.append(channelParam);
deviceClassElroRemote.setParamTypes(deviceParamsRemote);
@ -155,24 +148,21 @@ QList<DeviceClass> DevicePluginElro::supportedDevices() const
QList<ParamType> deviceParamsMotionDetector;
// =======================================
// Switch
DeviceClass deviceClassElroSwitch(pluginId(), elroVendorId, elroSwitchId);
deviceClassElroSwitch.setName("Elro Power Switch");
QList<ParamType> deviceParamsSwitch;
ParamType paramSwitch = ParamType("channel1", QVariant::Bool);
ParamType paramSwitch = ParamType("channel 1", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
paramSwitch = ParamType("channel2", QVariant::Bool);
paramSwitch = ParamType("channel 2", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
paramSwitch = ParamType("channel3", QVariant::Bool);
paramSwitch = ParamType("channel 3", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
paramSwitch = ParamType("channel4", QVariant::Bool);
paramSwitch = ParamType("channel 4", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
paramSwitch = ParamType("channel5", QVariant::Bool);
paramSwitch = ParamType("channel 5", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
paramSwitch = ParamType("A", QVariant::Bool);
deviceParamsSwitch.append(paramSwitch);
@ -192,6 +182,7 @@ QList<DeviceClass> DevicePluginElro::supportedDevices() const
ParamType actionParamSwitch("power", QVariant::Bool);
actionParamsSwitch.append(actionParamSwitch);
QList<ActionType> switchActions;
ActionType powerAction(ActionTypeId("31c9758e-6567-4f89-85bb-29e1a7c55d44"));
@ -228,27 +219,27 @@ QPair<DeviceManager::DeviceError, QString> DevicePluginElro::executeAction(Devic
// =======================================
// create the bincode
// channels
if(device->paramValue("channel1").toBool()){
if(device->paramValue("channel 1").toBool()){
binCode.append("00");
}else{
binCode.append("01");
}
if(device->paramValue("channel2").toBool()){
if(device->paramValue("channel 2").toBool()){
binCode.append("00");
}else{
binCode.append("01");
}
if(device->paramValue("channel3").toBool()){
if(device->paramValue("channel 3").toBool()){
binCode.append("00");
}else{
binCode.append("01");
}
if(device->paramValue("channel4").toBool()){
if(device->paramValue("channel 4").toBool()){
binCode.append("00");
}else{
binCode.append("01");
}
if(device->paramValue("channel5").toBool()){
if(device->paramValue("channel 5").toBool()){
binCode.append("00");
}else{
binCode.append("01");
@ -293,29 +284,32 @@ QPair<DeviceManager::DeviceError, QString> DevicePluginElro::executeAction(Devic
int delay = 350;
// sync signal
rawData.append(delay);
rawData.append(delay*31);
rawData.append(1);
rawData.append(31);
// add the code
foreach (QChar c, binCode) {
if(c == '0'){
rawData.append(delay);
rawData.append(delay*3);
rawData.append(1);
rawData.append(3);
}else{
rawData.append(delay*3);
rawData.append(delay);
rawData.append(3);
rawData.append(1);
}
}
// =======================================
// send data to driver
//qDebug() << "rawData" << rawData;
qDebug() << "transmit" << pluginName() << action.param("power").value().toBool();
transmitData(rawData);
return report();
// send data to hardware resource
if(transmitData(delay, rawData)){
qDebug() << "transmitted" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report();
}else{
qDebug() << "could not transmitt" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report(DeviceManager::DeviceErrorHardwareNotAvailable,QString("Radio 433 MHz transmitter not available."));
}
}
void DevicePluginElro::radioData(QList<int> rawData)
void DevicePluginElro::radioData(const QList<int> &rawData)
{
// filter right here a wrong signal length
if(rawData.length() != 49){
@ -363,7 +357,7 @@ void DevicePluginElro::radioData(QList<int> rawData)
}else{
return;
}
qDebug() << "ELRO understands this protocol: " << binCode;
//qDebug() << "ELRO understands this protocol: " << binCode;
if(binCode.left(20) == "00000100000000000001"){
if(binCode.right(4) == "0100"){
@ -416,11 +410,11 @@ void DevicePluginElro::radioData(QList<int> rawData)
Device *device = 0;
QList<Device*> deviceList = deviceManager()->findConfiguredDevices(elroRemoteId);
foreach (Device *dev, deviceList) {
if (dev->hasParam("channel1") && dev->paramValue("channel1").toBool() == group.at(0) &&
dev->hasParam("channel2") && dev->paramValue("channel2").toBool() == group.at(1) &&
dev->hasParam("channel3") && dev->paramValue("channel3").toBool() == group.at(2) &&
dev->hasParam("channel4") && dev->paramValue("channel4").toBool() == group.at(3) &&
dev->hasParam("channel5") && dev->paramValue("channel5").toBool() == group.at(4)
if (dev->hasParam("channel 1") && dev->paramValue("channel 1").toBool() == group.at(0) &&
dev->hasParam("channel 2") && dev->paramValue("channel 2").toBool() == group.at(1) &&
dev->hasParam("channel 3") && dev->paramValue("channel 3").toBool() == group.at(2) &&
dev->hasParam("channel 4") && dev->paramValue("channel 4").toBool() == group.at(3) &&
dev->hasParam("channel 5") && dev->paramValue("channel 5").toBool() == group.at(4)
) {
// Yippie! We found the device.
device = dev;
@ -439,7 +433,7 @@ void DevicePluginElro::radioData(QList<int> rawData)
DeviceClass deviceClass = supportedDevices().first();
foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.name() == button) {
//qDebug() << "emit event " << pluginName() << group << eventType.name() << power;
qDebug() << "got event: " << pluginName() << group << "power = " << power;
Event event = Event(eventType.id(), device->id(), params);
emit emitEvent(event);
return;

View File

@ -38,7 +38,7 @@ public:
QString pluginName() const override;
PluginId pluginId() const override;
void radioData(QList<int> rawData) override;
void radioData(const QList<int> &rawData) override;
public slots:
QPair<DeviceManager::DeviceError, QString> executeAction(Device *device, const Action &action) override;

View File

@ -159,7 +159,6 @@
#include "plugin/device.h"
#include "devicemanager.h"
#include "hardware/radio433.h"
#include <QDebug>
#include <QStringList>
@ -443,35 +442,38 @@ QPair<DeviceManager::DeviceError, QString> DevicePluginIntertechno::executeActio
binCode.append("0100");
}
//qDebug() << "bin code:" << binCode;
// =======================================
//create rawData timings list
int delay = 350;
// sync signal
rawData.append(delay);
rawData.append(delay*31);
rawData.append(1);
rawData.append(31);
// add the code
foreach (QChar c, binCode) {
if(c == '0'){
rawData.append(delay);
rawData.append(delay*3);
rawData.append(1);
rawData.append(3);
}else{
rawData.append(delay*3);
rawData.append(delay);
rawData.append(3);
rawData.append(1);
}
}
// =======================================
// send data to driver
qDebug() << "transmit" << pluginName() << familyCode << buttonCode << action.param("power").value().toBool();
transmitData(rawData);
return report();
// send data to hardware resource
if(transmitData(delay, rawData)){
qDebug() << "transmitted" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report();
}else{
qWarning() << "ERROR: could not transmitt" << pluginName() << device->name() << "power: " << action.param("power").value().toBool();
return report(DeviceManager::DeviceErrorHardwareNotAvailable, QString("Radio 433 MHz transmitter not available."));
}
}
void DevicePluginIntertechno::radioData(QList<int> rawData)
void DevicePluginIntertechno::radioData(const QList<int> &rawData)
{

View File

@ -38,7 +38,7 @@ public:
QString pluginName() const override;
PluginId pluginId() const override;
void radioData(QList<int> rawData) override;
void radioData(const QList<int> &rawData) override;
public slots:
QPair<DeviceManager::DeviceError, QString> executeAction(Device *device, const Action &action) override;