diff options
Diffstat (limited to 'bluetooth')
-rw-r--r-- | bluetooth/CMakeLists.txt | 2 | ||||
-rw-r--r-- | bluetooth/bluetooth.cpp | 230 | ||||
-rw-r--r-- | bluetooth/bluetooth.h | 94 | ||||
-rw-r--r-- | bluetooth/bluetoothmessage.cpp | 30 | ||||
-rw-r--r-- | bluetooth/bluetoothmessage.h | 44 |
5 files changed, 400 insertions, 0 deletions
diff --git a/bluetooth/CMakeLists.txt b/bluetooth/CMakeLists.txt new file mode 100644 index 0000000..c068a9f --- /dev/null +++ b/bluetooth/CMakeLists.txt @@ -0,0 +1,2 @@ +add_headers(bluetooth.h bluetoothmessage.h) +add_sources(bluetooth.cpp bluetoothmessage.cpp) diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp new file mode 100644 index 0000000..cc5f496 --- /dev/null +++ b/bluetooth/bluetooth.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "message.h" +#include "messageengine.h" +#include "bluetooth.h" +#include "bluetoothmessage.h" +#include "responsemessage.h" + +Bluetooth::Bluetooth (QUrl &url, QObject * parent) : + QObject(parent), + m_mloop(nullptr) +{ + m_mloop = new MessageEngine(url); + QObject::connect(m_mloop, &MessageEngine::connected, this, &Bluetooth::onConnected); + QObject::connect(m_mloop, &MessageEngine::disconnected, this, &Bluetooth::onDisconnected); + QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &Bluetooth::onMessageReceived); + + uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb"); + uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb"); +} + +Bluetooth::~Bluetooth() +{ + delete m_mloop; +} + +void Bluetooth::generic_command(QString verb, QString value) +{ + BluetoothMessage *tmsg = new BluetoothMessage(); + QJsonObject parameter; + + if (!value.isEmpty()) + parameter.insert("value", value); + + tmsg->createRequest(verb, parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Bluetooth::setPower(bool state) +{ + generic_command("power", state ? "true": "false"); + + m_power = state; + + emit powerChanged(m_power); +} + +void Bluetooth::setDiscoverable(bool state) +{ + const QStringList properties { "Pairable", "Discoverable" }; + QStringListIterator propertyIterator(properties); + + while (propertyIterator.hasNext()) { + BluetoothMessage *tmsg = new BluetoothMessage(); + QJsonObject parameter; + + parameter.insert("Property", propertyIterator.next()); + parameter.insert("value", state ? "true" : "false"); + + tmsg->createRequest("set_property", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); + } + + m_discoverable = state; + + emit discoverableChanged(); +} + +void Bluetooth::start_discovery() +{ + generic_command("start_discovery", ""); + generic_command("discovery_result", ""); +} + +void Bluetooth::stop_discovery() +{ + generic_command("stop_discovery", ""); +} + +void Bluetooth::remove_device(QString address) +{ + generic_command("remove_device", address); +} + +void Bluetooth::pair(QString address) +{ + generic_command("pair", address); +} + +void Bluetooth::cancel_pair(QString address) +{ + generic_command("cancel_pair", address); +} + +void Bluetooth::connect(QString address, QString uuid) +{ + BluetoothMessage *tmsg = new BluetoothMessage(); + QJsonObject parameter; + + uuid = process_uuid(uuid); + + parameter.insert("value", address); + parameter.insert("uuid", uuid); + tmsg->createRequest("connect", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Bluetooth::connect(QString address) +{ + generic_command("connect", address); +} + +void Bluetooth::disconnect(QString address, QString uuid) +{ + BluetoothMessage *tmsg = new BluetoothMessage(); + QJsonObject parameter; + + uuid = process_uuid(uuid); + + parameter.insert("value", address); + parameter.insert("uuid", uuid); + tmsg->createRequest("disconnect", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Bluetooth::disconnect(QString address) +{ + generic_command("disconnect", address); +} + +void Bluetooth::send_confirmation() +{ + generic_command("send_confirmation", "yes"); +} + +void Bluetooth::set_avrcp_controls(QString address, QString cmd) +{ + BluetoothMessage *tmsg = new BluetoothMessage(); + QJsonObject parameter; + + parameter.insert("Address", address); + parameter.insert("value", cmd); + tmsg->createRequest("set_avrcp_controls", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Bluetooth::onConnected() +{ + QStringListIterator eventIterator(events); + BluetoothMessage *tmsg; + + while (eventIterator.hasNext()) { + tmsg = new BluetoothMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + tmsg->createRequest("subscribe", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); + } + + // get initial power state + generic_command("power", QString()); + + // send initial list + generic_command("discovery_result", ""); +} + +void Bluetooth::onDisconnected() +{ + QStringListIterator eventIterator(events); + BluetoothMessage *tmsg; + + while (eventIterator.hasNext()) { + tmsg = new BluetoothMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + tmsg->createRequest("unsubscribe", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); + } +} + +void Bluetooth::onMessageReceived(MessageType type, Message *msg) +{ + if (msg->isEvent() && type == BluetoothEventMessage) { + BluetoothMessage *tmsg = qobject_cast<BluetoothMessage*>(msg); + + if (tmsg->isConnectionEvent()) { + emit connectionEvent(tmsg->eventData()); + } else if (tmsg->isRequestConfirmationEvent()) { + emit requestConfirmationEvent(tmsg->eventData()); + } else if (tmsg->isDeviceAddedEvent()) { + emit deviceAddedEvent(tmsg->eventData()); + } else if (tmsg->isDeviceRemovedEvent()) { + emit deviceRemovedEvent(tmsg->eventData()); + } else if (tmsg->isDeviceUpdatedEvent()) { + emit deviceUpdatedEvent(tmsg->eventData()); + } + } else if (msg->isReply() && type == ResponseRequestMessage) { + ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg); + + if (tmsg->requestVerb() == "discovery_result") { + emit deviceListEvent(tmsg->replyData()); + } else if (tmsg->requestVerb() == "power") { + m_power = tmsg->replyData().value("power").toString() == "on"; + emit powerChanged(m_power); + } + } + + msg->deleteLater(); +} diff --git a/bluetooth/bluetooth.h b/bluetooth/bluetooth.h new file mode 100644 index 0000000..24605cf --- /dev/null +++ b/bluetooth/bluetooth.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_H +#define BLUETOOTH_H + +#include <QDebug> +#include <QObject> + +#include "messageengine.h" + +class Bluetooth : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool power READ power WRITE setPower NOTIFY powerChanged) + Q_PROPERTY(bool discoverable READ discoverable WRITE setDiscoverable NOTIFY discoverableChanged) + + public: + explicit Bluetooth(QUrl &url, QObject * parent = Q_NULLPTR); + virtual ~Bluetooth(); + + void setPower(bool); + void setDiscoverable(bool); + + Q_INVOKABLE void start_discovery(void); + Q_INVOKABLE void stop_discovery(void); + + Q_INVOKABLE void remove_device(QString address); + Q_INVOKABLE void pair(QString address); + Q_INVOKABLE void cancel_pair(QString address); + + Q_INVOKABLE void connect(QString address, QString uuid); + Q_INVOKABLE void connect(QString address); + + Q_INVOKABLE void disconnect(QString address, QString uuid); + Q_INVOKABLE void disconnect(QString address); + + Q_INVOKABLE void send_confirmation(void); + Q_INVOKABLE void set_avrcp_controls(QString address, QString cmd); + + bool power() const { return m_power; }; + bool discoverable() const { return m_discoverable; }; + + signals: + void powerChanged(bool state); + void discoverableChanged(); + + void connectionEvent(QJsonObject data); + void requestConfirmationEvent(QJsonObject data); + void deviceAddedEvent(QJsonObject data); + void deviceRemovedEvent(QJsonObject data); + void deviceUpdatedEvent(QJsonObject data); + void deviceListEvent(QJsonObject data); + + private: + MessageEngine *m_mloop; + void generic_command(QString, QString); + + // slots + void onConnected(); + void onDisconnected(); + void onMessageReceived(MessageType, Message*); + + QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); }; + + // values + bool m_power; + bool m_discoverable; + + QMap<QString, QString> uuids; + + const QStringList events { + "connection", + "request_confirmation", + "device_added", + "device_removed", + "device_updated", + }; +}; + +#endif // BLUETOOTH_H diff --git a/bluetooth/bluetoothmessage.cpp b/bluetooth/bluetoothmessage.cpp new file mode 100644 index 0000000..52ecbed --- /dev/null +++ b/bluetooth/bluetoothmessage.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> + +#include "bluetoothmessage.h" + +bool BluetoothMessage::createRequest(QString verb, QJsonObject parameter) +{ + if (!verbs.contains(verb)) + return false; + + return Message::createRequest("Bluetooth-Manager", verb, parameter); +} diff --git a/bluetooth/bluetoothmessage.h b/bluetooth/bluetoothmessage.h new file mode 100644 index 0000000..6ce2f3e --- /dev/null +++ b/bluetooth/bluetoothmessage.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BLUETOOTH_MESSAGE_H +#define BLUETOOTH_MESSAGE_H + +#include "message.h" + +class BluetoothMessage : public Message +{ + Q_OBJECT + public: + bool isConnectionEvent() { return (this->eventName() == "connection"); }; + bool isRequestConfirmationEvent() { return (this->eventName() == "request_confirmation"); }; + bool isDeviceAddedEvent() { return (this->eventName() == "device_added"); }; + bool isDeviceRemovedEvent() { return (this->eventName() == "device_removed"); }; + bool isDeviceUpdatedEvent() { return (this->eventName() == "device_updated"); }; + bool createRequest(QString verb, QJsonObject parameter); + + private: + QStringList verbs { + "start_discovery" , "stop_discovery", "power", + "remove_device", "pair", "cancel_pair", + "connect", "disconnect", "device_priorites", + "set_device_property", "set_property", "discovery_result", + "set_avrcp_controls", "send_confirmation", + "subscribe", "unsubscribe", + }; +}; + +#endif // BLUETOOTH_MESSAGE_H |