Implemented cmdline interface
This commit is contained in:
18
autocomplete.sh
Normal file
18
autocomplete.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function _r3ctl_autocomplete()
|
||||||
|
{
|
||||||
|
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
|
||||||
|
if [[ "$COMP_CWORD" -eq 1 ]]
|
||||||
|
then
|
||||||
|
COMPREPLY=( $(compgen -W "log script sendYmhButton" "$cur") )
|
||||||
|
elif [[ "$COMP_CWORD" -eq 2 ]]
|
||||||
|
then
|
||||||
|
if [[ "${COMP_WORDS[1]}" = "sendYmhButton" ]]
|
||||||
|
then
|
||||||
|
COMPREPLY=( $(compgen -W "ymhpower ymhcd ymhtuner ymhtape ymhwdtv ymhsattv ymhvcr ymh7 ymhaux ymhextdec ymhtest ymhtunabcde ymheffect ymhtvlolup ymhtvvoldown ymhvoldown ymhvolup ymhmute ymhsleep ymhp5 ymhtunminus ymhtunplus ymhprgup ymhprgdown ymhminus ymhplus ymhtimelevel ymhmenu" "$cur") )
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
complete -F _r3ctl_autocomplete r3ctl
|
125
main.cpp
125
main.cpp
@ -1,53 +1,102 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QWebSocket>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonValue>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
#include "r3client.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication a(argc, argv);
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
QWebSocket webSocket;
|
const auto arguments = [&](){
|
||||||
QObject::connect(&webSocket, &QWebSocket::connected, [&](){ qDebug() << "connected()"; });
|
auto arguments = a.arguments();
|
||||||
QObject::connect(&webSocket, &QWebSocket::disconnected, [&](){ qDebug() << "disconnected()"; });
|
arguments.removeFirst();
|
||||||
// QObject::connect(&webSocket, &QWebSocket::textFrameReceived, [&](const QString &frame, bool isLastFrame){
|
return arguments;
|
||||||
// qDebug() << "textFrameReceived()";
|
}();
|
||||||
// });
|
|
||||||
// QObject::connect(&webSocket, &QWebSocket::binaryFrameReceived, [&](const QByteArray &frame, bool isLastFrame){
|
|
||||||
// qDebug() << "binaryFrameReceived()";
|
|
||||||
// });
|
|
||||||
QObject::connect(&webSocket, &QWebSocket::textMessageReceived, [&](const QString &message){
|
|
||||||
qDebug() << "textMessageReceived()" << message;
|
|
||||||
});
|
|
||||||
QObject::connect(&webSocket, &QWebSocket::binaryMessageReceived, [&](const QByteArray &message){
|
|
||||||
qDebug() << "binaryMessageReceived()" << message;
|
|
||||||
});
|
|
||||||
QObject::connect(&webSocket, qOverload<QAbstractSocket::SocketError>(&QWebSocket::error), [&](QAbstractSocket::SocketError error){
|
|
||||||
qDebug() << "error()" << error;
|
|
||||||
});
|
|
||||||
webSocket.open(QUrl{"ws://licht.realraum.at/sock"});
|
|
||||||
|
|
||||||
const auto sendMQTT = [&](const QString &ctx, const QJsonValue &data){
|
if (arguments.isEmpty())
|
||||||
const QJsonObject m{{"ctx", ctx}, {"data", data}};
|
{
|
||||||
const auto text = QJsonDocument{m}.toJson();
|
puts("No cmd given!");
|
||||||
qDebug() << "sendTextMessage()" << text;
|
return -1;
|
||||||
webSocket.sendTextMessage(text);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const auto mqtttopic_golightctrl = [](const QString &lightname){
|
R3Client client;
|
||||||
return QString{"action/GoLightCtrl/%0"}.arg(lightname);
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto sendYmhButton = [&](const QString &btn){
|
QObject::connect(&client, &R3Client::disconnected, [](){ qDebug() << "disconnected()"; });
|
||||||
sendMQTT(mqtttopic_golightctrl(btn), QJsonObject{{"Action", "send"}});
|
QObject::connect(&client, &R3Client::error, [](QAbstractSocket::SocketError error){ qDebug() << "error()" << error; });
|
||||||
};
|
|
||||||
|
|
||||||
QTimer::singleShot(1000, [&](){
|
if (arguments.first() == "log")
|
||||||
sendYmhButton("ymhvolup");
|
{
|
||||||
});
|
QObject::connect(&client, &R3Client::connected, [](){ qDebug() << "connected()"; });
|
||||||
|
QObject::connect(&client, &R3Client::statusReceived, [](const QString &ctx, const QJsonValue &jsonValue){ qDebug() << "statusReceived()" << ctx << jsonValue; });
|
||||||
|
}
|
||||||
|
else if (arguments.first() == "script")
|
||||||
|
{
|
||||||
|
QObject::connect(&client, &R3Client::connected, [&](){
|
||||||
|
client.sendMQTT("action/ceilingscripts/activatescript", QJsonObject{
|
||||||
|
{"colourlist", QJsonArray{
|
||||||
|
QJsonObject{{"b", 0}, {"cw", 0}, {"g", 0}, {"r", 1000}, {"ww", 0}},
|
||||||
|
QJsonObject{{"b", 100}, {"cw", 0}, {"g", 0}, {"r", 800}, {"ww", 0}},
|
||||||
|
QJsonObject{{"b", 300}, {"cw", 0}, {"g", 0}, {"r", 0}, {"ww", 0}},
|
||||||
|
QJsonObject{{"b", 100}, {"cw", 0}, {"g", 500}, {"r", 0}, {"ww", 0}},
|
||||||
|
QJsonObject{{"b", 0}, {"cw", 0}, {"g", 800}, {"r", 0}, {"ww", 0}},
|
||||||
|
QJsonObject{{"b", 0}, {"cw", 0}, {"g", 200}, {"r", 800}, {"ww", 0}}
|
||||||
|
}},
|
||||||
|
{"fadeduration", 500},
|
||||||
|
{"script", "wave"}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (arguments.first() == "sendYmhButton")
|
||||||
|
{
|
||||||
|
if (arguments.size() < 2)
|
||||||
|
{
|
||||||
|
puts("No button given for sendYmhButton");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto btn = arguments.at(1);
|
||||||
|
|
||||||
|
QObject::connect(&client, &R3Client::connected, [&client,btn](){
|
||||||
|
client.sendYmhButton(btn);
|
||||||
|
});
|
||||||
|
QObject::connect(&client, &R3Client::statusReceived, [btn](const QString &ctx, const QJsonValue &jsonValue){
|
||||||
|
if (ctx != "action/yamahastereo/ircmd")
|
||||||
|
return;
|
||||||
|
if (!jsonValue.isObject())
|
||||||
|
{
|
||||||
|
qWarning() << "json data is not an object";
|
||||||
|
qWarning() << jsonValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto object = jsonValue.toObject();
|
||||||
|
if (!object.contains("Cmd"))
|
||||||
|
{
|
||||||
|
qWarning() << "json data does not contain Cmd";
|
||||||
|
qWarning() << object;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto cmdValue = object.value("Cmd");
|
||||||
|
if (!cmdValue.isString())
|
||||||
|
{
|
||||||
|
qWarning() << "json data Cmd is not a string";
|
||||||
|
qWarning() << object;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto cmd = cmdValue.toString();
|
||||||
|
if (cmd == btn)
|
||||||
|
QCoreApplication::quit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
puts("Invalid cmd. Valid are log, script, sendYmhButton");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.open();
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
101
r3client.cpp
Normal file
101
r3client.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include "r3client.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
R3Client::R3Client(QObject *parent) :
|
||||||
|
QObject{parent}
|
||||||
|
{
|
||||||
|
connect(&m_webSocket, &QWebSocket::connected, this, &R3Client::connected);
|
||||||
|
connect(&m_webSocket, &QWebSocket::disconnected, this, &R3Client::disconnected);
|
||||||
|
connect(&m_webSocket, qOverload<QAbstractSocket::SocketError>(&QWebSocket::error), this, &R3Client::error);
|
||||||
|
connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &R3Client::textMessageReceived);
|
||||||
|
connect(&m_webSocket, &QWebSocket::binaryMessageReceived, this, &R3Client::binaryMessageReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::open()
|
||||||
|
{
|
||||||
|
m_webSocket.open(QUrl{"ws://licht.realraum.at/sock"});
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::close(QWebSocketProtocol::CloseCode closeCode, const QString &reason)
|
||||||
|
{
|
||||||
|
m_webSocket.close(closeCode, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::sendMQTT(const QString &ctx, const QJsonValue &data)
|
||||||
|
{
|
||||||
|
const QJsonObject m{{"ctx", ctx}, {"data", data}};
|
||||||
|
//qDebug() << m;
|
||||||
|
const auto text = QJsonDocument{m}.toJson(QJsonDocument::Compact);
|
||||||
|
//qDebug() << "sendTextMessage()" << text;
|
||||||
|
m_webSocket.sendTextMessage(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::sendYmhButton(const QString &btn)
|
||||||
|
{
|
||||||
|
sendMQTT(mqtttopic_golightctrl(btn), QJsonObject{{"Action", "send"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString R3Client::mqtttopic_golightctrl(const QString &lightname)
|
||||||
|
{
|
||||||
|
return QString{"action/GoLightCtrl/%0"}.arg(lightname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::textMessageReceived(const QString &message)
|
||||||
|
{
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(message.toUtf8(), &error);
|
||||||
|
if (error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
qWarning() << "could not parse JSON" << error.errorString();
|
||||||
|
qDebug() << "textMessageReceived()" << message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!document.isObject())
|
||||||
|
{
|
||||||
|
qWarning() << "json is not an object";
|
||||||
|
qDebug() << "textMessageReceived()" << message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto obj = document.object();
|
||||||
|
|
||||||
|
if (!obj.contains("ctx"))
|
||||||
|
{
|
||||||
|
qWarning() << "json does not contain ctx";
|
||||||
|
qDebug() << "textMessageReceived()" << message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ctx;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto ctxValue = obj.value("ctx");
|
||||||
|
if (!ctxValue.isString())
|
||||||
|
{
|
||||||
|
qWarning() << "ctx is not a string!";
|
||||||
|
qDebug() << "textMessageReceived()" << message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = ctxValue.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj.contains("data"))
|
||||||
|
{
|
||||||
|
qWarning() << "json does not contain data";
|
||||||
|
qDebug() << "textMessageReceived()" << message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto data = obj.value("data");
|
||||||
|
|
||||||
|
emit statusReceived(ctx, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3Client::binaryMessageReceived(const QByteArray &message)
|
||||||
|
{
|
||||||
|
qWarning() << "binaryMessageReceived()" << message;
|
||||||
|
}
|
32
r3client.h
Normal file
32
r3client.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWebSocket>
|
||||||
|
|
||||||
|
class R3Client : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
R3Client(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void open();
|
||||||
|
void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CloseCodeNormal, const QString &reason = QString{});
|
||||||
|
|
||||||
|
void sendMQTT(const QString &ctx, const QJsonValue &data);
|
||||||
|
void sendYmhButton(const QString &btn);
|
||||||
|
static QString mqtttopic_golightctrl(const QString &lightname);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connected();
|
||||||
|
void disconnected();
|
||||||
|
void error(QAbstractSocket::SocketError error);
|
||||||
|
void statusReceived(const QString &ctx, const QJsonValue &jsonValue);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void textMessageReceived(const QString &message);
|
||||||
|
void binaryMessageReceived(const QByteArray &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWebSocket m_webSocket;
|
||||||
|
};
|
Reference in New Issue
Block a user