This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-core/libguh/hardware/radio433receiver.cpp
Simon Stürz 3a8908c982 added eQ-3 plugin
pluginstatus: can be discovered, still not refreshing
auto generate devices from cube missing
some errors in message parsing
2019-04-01 20:48:17 +02:00

246 lines
7.8 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 <QFile>
#include <QFileSystemWatcher>
#include <QDebug>
#include <sys/time.h>
#include "radio433receiver.h"
Radio433Receiver::Radio433Receiver(QObject *parent, int gpio) :
QThread(parent),m_gpioPin(gpio)
{
m_gpio = new Gpio(this,m_gpioPin);
stopReceiver();
connect(this,SIGNAL(timingReady(int)),this,SLOT(handleTiming(int)),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;
}
bool Radio433Receiver::stopReceiver()
{
m_mutex.lock();
m_enabled = false;
m_mutex.unlock();
return true;
}
void Radio433Receiver::run()
{
struct pollfd fdset[2];
int gpio_fd = m_gpio->openGpio();
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
while(enabled){
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
int rc = poll(fdset, 2, 3000);
if (rc < 0) {
qDebug() << "ERROR: poll failed";
return;
}
if(rc == 0){
//timeout
}
if (fdset[1].revents & POLLPRI){
read(fdset[1].fd, buf, 1);
int currentTime = micros();
int duration = currentTime - lastTime;
lastTime = currentTime;
emit timingReady(duration);
}
m_mutex.lock();
enabled = m_enabled;
m_mutex.unlock();
}
}
int Radio433Receiver::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) ;
}
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){
return true;
}
return false;
}
bool Radio433Receiver::checkValue(int value)
{
if(valueInTolerance(value,m_pulseProtocolOne) || valueInTolerance(value,2*m_pulseProtocolOne) || valueInTolerance(value,3*m_pulseProtocolOne) || valueInTolerance(value,4*m_pulseProtocolOne) || valueInTolerance(value,8*m_pulseProtocolOne)){
return true;
}
if(valueInTolerance(value,m_pulseProtocolTwo) || valueInTolerance(value,2*m_pulseProtocolTwo) || valueInTolerance(value,3*m_pulseProtocolTwo) || valueInTolerance(value,4*m_pulseProtocolTwo) || valueInTolerance(value,8*m_pulseProtocolTwo)){
return true;
}
return false;
}
bool Radio433Receiver::checkValues(Protocol protocol)
{
switch (protocol) {
case Protocol48:
for(int i = 1; i < m_timings.count(); i++){
if(!(valueInTolerance(m_timings.at(i),m_pulseProtocolOne) || valueInTolerance(m_timings.at(i),2*m_pulseProtocolOne) || valueInTolerance(m_timings.at(i),3*m_pulseProtocolOne) || valueInTolerance(m_timings.at(i),4*m_pulseProtocolOne) || valueInTolerance(m_timings.at(i),8*m_pulseProtocolOne))){
break;
}
}
return true;
case Protocol64:
for(int i = 1; i < m_timings.count(); i++){
if(!(valueInTolerance(m_timings.at(i),m_pulseProtocolTwo) || valueInTolerance(m_timings.at(i),2*m_pulseProtocolTwo) || valueInTolerance(m_timings.at(i),3*m_pulseProtocolTwo) || valueInTolerance(m_timings.at(i),4*m_pulseProtocolTwo) || valueInTolerance(m_timings.at(i),8*m_pulseProtocolTwo))){
break;
}
}
return true;
default:
break;
}
return false;
}
void Radio433Receiver::changeReading(bool reading)
{
if(reading != m_reading){
m_reading = reading;
emit readingChanged(reading);
}
}
void Radio433Receiver::handleTiming(int duration)
{
// to short...
if(duration < 50){
changeReading(false);
m_timings.clear();
return;
}
// could by a sync signal...
bool sync = false;
if(duration > 2400 && duration < 14000){
changeReading(false);
sync = true;
}
// got sync signal and list is not empty...
if(!m_timings.isEmpty() && sync){
// 1 sync bit + 48 data bit
if(m_timings.count() == 49 && checkValues(Protocol48)){
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--------------------------";
changeReading(false);
emit dataReceived(m_timings);
}
m_timings.clear();
m_pulseProtocolOne = 0;
m_pulseProtocolTwo = 0;
changeReading(false);
}
// got sync signal and list is empty...
if(m_timings.isEmpty() && sync){
m_timings.append(duration);
m_pulseProtocolOne = (int)((double)m_timings.first()/31);
m_pulseProtocolTwo = (int)((double)m_timings.first()/10);
changeReading(false);
return;
}
// list not empty and this is a possible value
if(!m_timings.isEmpty() && checkValue(duration)){
m_timings.append(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))){
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--------------------------";
emit dataReceived(m_timings);
}
// 1 sync bit + 64 data bit
if(m_timings.count() == 65 && checkValues(Protocol64)){
qDebug() << "64 bit -> " << m_timings << "\n--------------------------";
changeReading(false);
emit dataReceived(m_timings);
}
}
}