Major wip refactor
Allow running without gui Remove serialPortMultiplexer broadcast use Add TcpServer and TcpClient Introduce the concept of an item source
This commit is contained in:
parent
cbeb8d49a7
commit
6d742e60db
38 changed files with 928 additions and 825 deletions
|
|
@ -1,62 +0,0 @@
|
|||
#include "ocupancysensor.h"
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include "../apgetconnected.h"
|
||||
|
||||
|
||||
OcupancySensorSource::OcupancySensorSource(QObject *parent, const QString& device,
|
||||
const QString& deviceMac): QObject (parent), deviceMac_(deviceMac), device_(device)
|
||||
{
|
||||
QTimer::singleShot(timeoutMs, this, &OcupancySensorSource::Timeout);
|
||||
}
|
||||
|
||||
void OcupancySensorSource::sensorEvent(Sensor sensor)
|
||||
{
|
||||
if(sensor.type == Sensor::TYPE_DOOR && sensor.id == 1 && sensor.field != 0.0f)
|
||||
{
|
||||
if(occupied == false) stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, 1, "Occupancy"));
|
||||
QTimer::singleShot(timeoutMs, this, &OcupancySensorSource::Timeout);
|
||||
}
|
||||
}
|
||||
|
||||
void OcupancySensorSource::Timeout()
|
||||
{
|
||||
int error = 0;
|
||||
qDebug()<<"testing for occupancy";
|
||||
std::vector<uint64_t> devices = ap::connectedDevices(device_.toLatin1().toStdString(), error);
|
||||
if(error == 0)
|
||||
{
|
||||
bool found = false;
|
||||
for(size_t i = 0; i < devices.size(); ++i)
|
||||
{
|
||||
std::string mac = ap::macAddrToString(devices[i]);
|
||||
if(mac.find(deviceMac_.toLatin1().toStdString()) != std::string::npos)
|
||||
{
|
||||
found = true;
|
||||
qDebug()<<"occupied";
|
||||
break;
|
||||
}
|
||||
}
|
||||
stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, found, "Occupancy"));
|
||||
occupied = found;
|
||||
}
|
||||
else
|
||||
{
|
||||
stateChanged(Sensor(Sensor::TYPE_OCUPANCY, 0, true, "Occupancy"));
|
||||
qDebug()<<"occupancy sensor error "<<error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OcupancySensorSource::store(QJsonObject &json)
|
||||
{
|
||||
json["Device"] = device_;
|
||||
json["MacAddres"] = deviceMac_;
|
||||
}
|
||||
|
||||
void OcupancySensorSource::load(const QJsonObject &json)
|
||||
{
|
||||
device_ = json["Device"].toString("wlan0");
|
||||
deviceMac_ = json["MacAddres"].toString("60:BE:B5:25:8C:E0");
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonObject>
|
||||
#include "sensor.h"
|
||||
|
||||
class OcupancySensorSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
QString deviceMac_;
|
||||
QString device_;
|
||||
bool occupied = true;
|
||||
static constexpr unsigned timeoutMs = (15 * 60) * 1000;
|
||||
|
||||
public:
|
||||
explicit OcupancySensorSource(QObject *parent = nullptr, const QString& device = "wlan0",
|
||||
const QString& deviceMac = "60:BE:B5:25:8C:E0");
|
||||
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
|
||||
public slots:
|
||||
void sensorEvent(Sensor sensor);
|
||||
|
||||
private slots:
|
||||
|
||||
void Timeout();
|
||||
|
||||
signals:
|
||||
void stateChanged(Sensor sensor);
|
||||
};
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
#include "pipewiresensor.h"
|
||||
#include <QDebug>
|
||||
|
||||
static const struct pw_node_events node_events = {
|
||||
.version = PW_VERSION_NODE_EVENTS,
|
||||
.info = &PipeWireSensorSource::nodeEventHandler,
|
||||
.param = nullptr
|
||||
};
|
||||
|
||||
PipeWireSensorSource::PipeWireSensorSource(PipeWireHandler* handler, const std::string& nodeName, uint8_t id, QObject *parent)
|
||||
: QObject{parent}, handler_(handler), nodeName_(nodeName), id_(id)
|
||||
{
|
||||
connect(handler_, &PipeWireHandler::nodeAdded, this, &PipeWireSensorSource::nodeAdded);
|
||||
connect(&timer, &QTimer::timeout, this, &PipeWireSensorSource::offTimeout);
|
||||
timer.setSingleShot(true);
|
||||
}
|
||||
|
||||
void PipeWireSensorSource::offTimeout()
|
||||
{
|
||||
if(state == false)
|
||||
return;
|
||||
state = false;
|
||||
stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, id_, state));
|
||||
}
|
||||
|
||||
void PipeWireSensorSource::nodeEventHandler(void* data, const struct pw_node_info *info)
|
||||
{
|
||||
PipeWireSensorSource* source = static_cast<PipeWireSensorSource*>(data);
|
||||
|
||||
if(info->state == source->prevState)
|
||||
return;
|
||||
|
||||
source->prevState = info->state;
|
||||
|
||||
switch (info->state)
|
||||
{
|
||||
case PW_NODE_STATE_ERROR:
|
||||
case PW_NODE_STATE_CREATING:
|
||||
source->state = false;
|
||||
source->stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, source->id_, 0));
|
||||
break;
|
||||
case PW_NODE_STATE_SUSPENDED:
|
||||
case PW_NODE_STATE_IDLE:
|
||||
if(source->state == true)
|
||||
source->timer.start(10000);
|
||||
break;
|
||||
case PW_NODE_STATE_RUNNING:
|
||||
if(source->state == false)
|
||||
{
|
||||
source->state = true;
|
||||
source->stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, source->id_, source->state));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PipeWireSensorSource::nodeAdded(PipeWireHandler::PwNode node)
|
||||
{
|
||||
if(node.name == nodeName_)
|
||||
{
|
||||
|
||||
sinkNode = static_cast<struct pw_node*>(pw_registry_bind(handler_->getRegistry(), node.id, PW_TYPE_INTERFACE_Node, PW_VERSION_CLIENT, 0));
|
||||
if(sinkNode)
|
||||
{
|
||||
qDebug()<<"Failed to register to required pipewire node"<<node.name.c_str()<<"as id"<<node.id;
|
||||
return;
|
||||
}
|
||||
pw_node_add_listener(sinkNode, &sinkListener, &node_events, this);
|
||||
qDebug()<<"Found required pipewire node"<<node.name.c_str()<<"as id"<<node.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef PIPEWIRESENSOR_H
|
||||
#define PIPEWIRESENSOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <string>
|
||||
#include <pipewire/core.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
#include <QTimer>
|
||||
|
||||
#include "sensor.h"
|
||||
#include "../pipewire.h"
|
||||
|
||||
class PipeWireSensorSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
PipeWireHandler* handler_;
|
||||
std::string nodeName_;
|
||||
struct pw_node* sinkNode = nullptr;
|
||||
struct spa_hook sinkListener;
|
||||
pw_node_state prevState = PW_NODE_STATE_SUSPENDED;
|
||||
QTimer timer;
|
||||
uint8_t id_;
|
||||
bool state = false;
|
||||
|
||||
private slots:
|
||||
void offTimeout();
|
||||
|
||||
public:
|
||||
explicit PipeWireSensorSource(PipeWireHandler* handler, const std::string& nodeName, uint8_t id, QObject *parent = nullptr);
|
||||
static void nodeEventHandler(void* data, const struct pw_node_info *info);
|
||||
|
||||
signals:
|
||||
void stateChanged(Sensor sensor);
|
||||
|
||||
private slots:
|
||||
void nodeAdded(PipeWireHandler::PwNode node);
|
||||
};
|
||||
|
||||
#endif // PIPEWIRESENSOR_H
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include<QDateTime>
|
||||
#include<QObject>
|
||||
#include<vector>
|
||||
#include<QJsonObject>
|
||||
|
||||
class Sensor
|
||||
{
|
||||
|
|
@ -41,6 +42,15 @@ public:
|
|||
{
|
||||
lastSeen = QDateTime::currentDateTime();
|
||||
}
|
||||
Sensor(const QJsonObject& json)
|
||||
{
|
||||
type = json["SensorType"].toInt(0);
|
||||
id = json["Id"].toInt(0);
|
||||
field = json["Field"].toInt(0);
|
||||
name = json["Name"].toString("Sensor");
|
||||
lastSeen = QDateTime::fromString(json["LastSeen"].toString(""));
|
||||
hidden = json["Hidden"].toBool(false);
|
||||
}
|
||||
inline bool operator==(const Sensor& in) const
|
||||
{
|
||||
return type==in.type && id == in.id;
|
||||
|
|
@ -77,15 +87,32 @@ public:
|
|||
QString::number((type == Sensor::TYPE_HUMIDITY || type == Sensor::TYPE_TEMPERATURE) ? field*10 : field) +
|
||||
" TIME: " + QString::number(lastSeen.toSecsSinceEpoch());
|
||||
}
|
||||
inline void store(QJsonObject& json)
|
||||
{
|
||||
json["Type"] = "Sensor";
|
||||
json["SensorType"] = static_cast<int>(type);
|
||||
json["Id"] = static_cast<int>(id);
|
||||
json["Field"] = field;
|
||||
json["Name"] = name;
|
||||
json["LastSeen"] = lastSeen.toString();
|
||||
json["Hidden"] = hidden;
|
||||
}
|
||||
inline void generateName()
|
||||
{
|
||||
if(type == TYPE_TEMPERATURE) name = "Temperature " + QString::number(id);
|
||||
else if(type == TYPE_DOOR) name = "Door " + QString::number(id);
|
||||
else if(type == TYPE_BUTTON) name = "Button " + QString::number(id);
|
||||
else if(type == TYPE_AUDIO_OUTPUT) name = "Speakers " + QString::number(id);
|
||||
else if(type == TYPE_HUMIDITY) name = "Humidity " + QString::number(id);
|
||||
else if(type == TYPE_SUN_ALTITUDE) name = "Solar Altitude";
|
||||
else if(type == TYPE_SHUTDOWN_IMMINENT) name = "Shutdown Imminent";
|
||||
if(type == TYPE_TEMPERATURE)
|
||||
name = "Temperature " + QString::number(id);
|
||||
else if(type == TYPE_DOOR)
|
||||
name = "Door " + QString::number(id);
|
||||
else if(type == TYPE_BUTTON)
|
||||
name = "Button " + QString::number(id);
|
||||
else if(type == TYPE_AUDIO_OUTPUT)
|
||||
name = "Speakers " + QString::number(id);
|
||||
else if(type == TYPE_HUMIDITY)
|
||||
name = "Humidity " + QString::number(id);
|
||||
else if(type == TYPE_SUN_ALTITUDE)
|
||||
name = "Solar Altitude";
|
||||
else if(type == TYPE_SHUTDOWN_IMMINENT)
|
||||
name = "Shutdown Imminent";
|
||||
else name = "Sensor Type " + QString::number(type) + " Id " + QString::number(id);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
#include "speakersensor.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
SpeakerSensorSource::SpeakerSensorSource(QString name, QObject *parent) : QObject(parent), name_(name)
|
||||
{
|
||||
silenceCount = 0;
|
||||
}
|
||||
|
||||
SpeakerSensorSource::~SpeakerSensorSource()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void SpeakerSensorSource::run()
|
||||
{
|
||||
abort();
|
||||
arecord.start( "arecord", {"--disable-softvol", "-r", "8000", "-D", "front", "-"});
|
||||
|
||||
connect(&timer, SIGNAL(timeout()), this, SLOT(doTick()));
|
||||
timer.setInterval(500);
|
||||
timer.start();
|
||||
|
||||
stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 1, name_));
|
||||
}
|
||||
|
||||
|
||||
void SpeakerSensorSource::abort()
|
||||
{
|
||||
if(arecord.state() == QProcess::Running)arecord.close();
|
||||
if(timer.isActive())timer.stop();
|
||||
}
|
||||
|
||||
void SpeakerSensorSource::doTick()
|
||||
{
|
||||
if(arecord.state() == QProcess::Running)
|
||||
{
|
||||
QByteArray buffer = arecord.readAllStandardOutput();
|
||||
//qDebug()<<(int16_t)buffer[0];
|
||||
for(long i = 0; i < buffer.size(); i++)
|
||||
{
|
||||
if((int16_t)buffer.at(i) != -128)
|
||||
{
|
||||
silenceCount = 0;
|
||||
}
|
||||
}
|
||||
if(silenceCount > 40 && state)
|
||||
{
|
||||
stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 0, name_));
|
||||
state = false;
|
||||
}
|
||||
else if(silenceCount == 0 && !state)
|
||||
{
|
||||
stateChanged(Sensor(Sensor::TYPE_AUDIO_OUTPUT, 0, 1, name_));
|
||||
state = true;
|
||||
}
|
||||
silenceCount++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#ifndef AMPMANAGER_H
|
||||
#define AMPMANAGER_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
#include <QScopedPointer>
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
#include <QProcess>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "sensor.h"
|
||||
|
||||
|
||||
class SpeakerSensorSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QString name_;
|
||||
bool state = true;
|
||||
QTimer timer;
|
||||
|
||||
public:
|
||||
explicit SpeakerSensorSource(QString name = "", QObject *parent = nullptr);
|
||||
~SpeakerSensorSource();
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void abort();
|
||||
|
||||
signals:
|
||||
void stateChanged(Sensor sensor);
|
||||
|
||||
private slots:
|
||||
void doTick();
|
||||
|
||||
private:
|
||||
long silenceCount = 0;
|
||||
|
||||
QProcess arecord;
|
||||
};
|
||||
|
||||
#endif // AMPMANAGER_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue