Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsteroidOS support #320

Merged
merged 15 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions daemon/daemon.pro
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ include(libwatchfish/libwatchfish.pri)
include(../qble/qble.pri)

SOURCES += \
src/devices/asteroidosdevice.cpp \
src/devices/banglejsdevice.cpp \
src/devices/bipdevice.cpp \
src/devices/bipsdevice.cpp \
Expand All @@ -126,6 +127,10 @@ SOURCES += \
src/operations/huamiupdatefirmwareoperation2020.cpp \
src/qaesencryption.cpp \
src/services/adafruitblefsservice.cpp \
src/services/asteroidtimeservice.cpp \
src/services/asteroidweatherservice.cpp \
src/services/asteroidnotificationservice.cpp \
src/services/asteroidmediaservice.cpp \
src/services/currenttimeservice.cpp \
src/services/dfuservice.cpp \
src/services/infinitimemotionservice.cpp \
Expand Down Expand Up @@ -175,6 +180,7 @@ SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172

HEADERS += \
src/codec.h \
src/devices/asteroidosdevice.h \
src/devices/banglejsdevice.h \
src/devices/bipdevice.h \
src/devices/bipsdevice.h \
Expand All @@ -201,6 +207,10 @@ HEADERS += \
src/operations/huamiupdatefirmwareoperation2020.h \
src/qaesencryption.h \
src/services/adafruitblefsservice.h \
src/services/asteroidtimeservice.h \
src/services/asteroidweatherservice.h \
src/services/asteroidnotificationservice.h \
src/services/asteroidmediaservice.h \
src/services/currenttimeservice.h \
src/services/dfuservice.h \
src/services/infinitimemotionservice.h \
Expand Down
16 changes: 16 additions & 0 deletions daemon/src/devicefactory.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "devicefactory.h"
#include "asteroidosdevice.h"
#include "huamidevice.h"
#include "gtsdevice.h"
#include "biplitedevice.h"
Expand Down Expand Up @@ -56,6 +57,21 @@ AbstractDevice* DeviceFactory::createDevice(const QString &deviceName)
return new BangleJSDevice(deviceName);
}

QList<QString> asteroidDevices = {
"AsteroidOS",
"bass", "sturgeon", "narwhal", "sparrow", "dory",
"lenok", "catfish", "carp", "smelt", "anthias",
"pike", "sawfish", "ray", "firefish", "beluga", "skipjack",
"koi", "mooneye", "swift", "nemo", "hoki",
"minnow", "tetra", "sprat", "kingyo", "medaka"
};

for (auto iterator = asteroidDevices.begin(); iterator != asteroidDevices.end(); ++iterator) {
if (deviceName == *iterator) {
return new AsteroidOSDevice(deviceName);
}
}

qDebug() << "DeviceFactory::createDevice: no suitable devices found, creating a Bip device as default";
return new BipDevice(deviceName);

Expand Down
1 change: 1 addition & 0 deletions daemon/src/devices/abstractdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void AbstractDevice::pair()
QBLEDevice::pair();
}


void AbstractDevice::connectToDevice()
{
qDebug() << "AbstractDevice::connectToDevice";
Expand Down
281 changes: 281 additions & 0 deletions daemon/src/devices/asteroidosdevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
#include "asteroidosdevice.h"

#include "batteryservice.h"
#include "asteroidtimeservice.h"
#include "asteroidweatherservice.h"
#include "asteroidnotificationservice.h"
#include "asteroidmediaservice.h"

#include <QtXml/QtXml>


AsteroidOSDevice::AsteroidOSDevice(const QString &pairedName, QObject *parent) : AbstractDevice(pairedName, parent)
{
qDebug() << Q_FUNC_INFO << pairedName;
connect(this, &QBLEDevice::propertiesChanged, this, &AsteroidOSDevice::onPropertiesChanged, Qt::UniqueConnection);
}

int AsteroidOSDevice::supportedFeatures() const
{
return FEATURE_WEATHER | FEATURE_WEATHER | FEATURE_ALERT ;
//FEATURE_HRM | FEATURE_STEPS;
}

QString AsteroidOSDevice::deviceType() const
{
return "asteroidos";
}

AbstractFirmwareInfo *AsteroidOSDevice::firmwareInfo(const QByteArray &bytes)
{
qDebug() << Q_FUNC_INFO;
return nullptr;
}

void AsteroidOSDevice::sendAlert(const QString &sender, const QString &subject, const QString &message)
{
qDebug() << Q_FUNC_INFO << sender << subject << message;

AsteroidNotificationService *notification = qobject_cast<AsteroidNotificationService*>(service(AsteroidNotificationService::UUID_SERVICE_NOTIFICATION));
if (notification) {
notification->sendAlert(sender, subject, message);
}

}

void AsteroidOSDevice::incomingCall(const QString &caller)
{
qDebug() << Q_FUNC_INFO << caller;

AsteroidNotificationService *notification = qobject_cast<AsteroidNotificationService*>(service(AsteroidNotificationService::UUID_SERVICE_NOTIFICATION));
if (notification) {
notification->incomingCall(caller);
}

}


void AsteroidOSDevice::pair()
{
qDebug() << Q_FUNC_INFO;

m_needsAuth = true;
m_pairing = true;
m_autoreconnect = true;
//disconnectFromDevice();
setConnectionState("pairing");
emit connectionStateChanged();

QBLEDevice::connectToDevice();
}


/*
//Firmware handling
AbstractFirmwareInfo * AsteroidOSDevice::firmwareInfo(const QByteArray &bytes) = 0; //Caller owns the pointer and should delete it
void AsteroidOSDevice::prepareFirmwareDownload(const AbstractFirmwareInfo* info);
void AsteroidOSDevice::startDownload();

void AsteroidOSDevice::downloadSportsData();
void AsteroidOSDevice::refreshInformation();
QString AsteroidOSDevice::information(Info i) const;
void AsteroidOSDevice::applyDeviceSetting(Settings s);
void AsteroidOSDevice::rebootWatch();
void AsteroidOSDevice::sendEventReminder(int id, const QDateTime &dt, const QString &event);
void AsteroidOSDevice::enableFeature(AbstractDevice::Feature feature);
void AsteroidOSDevice::setMusicStatus(bool playing, const QString &title, const QString &artist, const QString &album, int duration = 0, int position = 0);
void AsteroidOSDevice::navigationRunning(bool running);
void AsteroidOSDevice::navigationNarrative(const QString &flag, const QString &narrative, const QString &manDist, int progress);
QStringList AsteroidOSDevice::supportedDisplayItems() const;
*/


void AsteroidOSDevice::onPropertiesChanged(QString interface, QVariantMap map, QStringList list)
{
qDebug() << Q_FUNC_INFO << interface << map << list;

if (interface == "org.bluez.Device1") {
m_reconnectTimer->start();
if (deviceProperty("ServicesResolved").toBool() ) {
initialise();
}
if (map.contains("Connected")) {
bool value = map["Connected"].toBool();

if (!value) {
qDebug() << "DisConnected!";
setConnectionState("disconnected");
} else {
setConnectionState("connected");
}
}
}

}


void AsteroidOSDevice::parseServices()
{
qDebug() << Q_FUNC_INFO;

QDBusInterface adapterIntro("org.bluez", devicePath(), "org.freedesktop.DBus.Introspectable", QDBusConnection::systemBus(), 0);
QDBusReply<QString> xml = adapterIntro.call("Introspect");

qDebug() << "Resolved services...";

qDebug().noquote() << xml.value();

QDomDocument doc;
doc.setContent(xml.value());

QDomNodeList nodes = doc.elementsByTagName("node");

qDebug() << nodes.count() << "nodes";

for (int x = 0; x < nodes.count(); x++)
{
QDomElement node = nodes.at(x).toElement();
QString nodeName = node.attribute("name");

if (nodeName.startsWith("service")) {
QString path = devicePath() + "/" + nodeName;

QDBusInterface devInterface("org.bluez", path, "org.bluez.GattService1", QDBusConnection::systemBus(), 0);
QString uuid = devInterface.property("UUID").toString();

qDebug() << "Creating service for: " << uuid;

if (uuid == BatteryService::UUID_SERVICE_BATTERY && !service(BatteryService::UUID_SERVICE_BATTERY)) {
addService(BatteryService::UUID_SERVICE_BATTERY, new BatteryService(path, this));
} else if (uuid == AsteroidTimeService::UUID_SERVICE_ASTEROID_TIME && !service(AsteroidTimeService::UUID_SERVICE_ASTEROID_TIME)) {
addService(AsteroidTimeService::UUID_SERVICE_ASTEROID_TIME, new AsteroidTimeService(path, this));
} else if (uuid == AsteroidWeatherService::UUID_SERVICE_WEATHER && !service(AsteroidWeatherService::UUID_SERVICE_WEATHER)) {
addService(AsteroidWeatherService::UUID_SERVICE_WEATHER, new AsteroidWeatherService(path, this));
} else if (uuid == AsteroidNotificationService::UUID_SERVICE_NOTIFICATION && !service(AsteroidNotificationService::UUID_SERVICE_NOTIFICATION)) {
addService(AsteroidNotificationService::UUID_SERVICE_NOTIFICATION, new AsteroidNotificationService(path, this));
} else if (uuid == AsteroidMediaService::UUID_SERVICE_MEDIA && !service(AsteroidMediaService::UUID_SERVICE_MEDIA )) {
addService(AsteroidMediaService::UUID_SERVICE_MEDIA , new AsteroidMediaService(path, this));
} else if ( !service(uuid)) {
addService(uuid, new QBLEService(uuid, path, this));
}
}
}
setConnectionState("authenticated");
}

void AsteroidOSDevice::initialise()
{
qDebug() << Q_FUNC_INFO;
setConnectionState("connected");
parseServices();

AsteroidNotificationService *notification = qobject_cast<AsteroidNotificationService*>(service(AsteroidNotificationService::UUID_SERVICE_NOTIFICATION));
if (notification) {
// notification->enableNotification(AsteroidNotificationService::UUID_CHARACTERISTIC_ALERT_NOTIFICATION_EVENT);
// connect(alert, &AlertNotificationService::serviceEvent, this, &PinetimeJFDevice::serviceEvent, Qt::UniqueConnection);
}


BatteryService *battery = qobject_cast<BatteryService*>(service(BatteryService::UUID_SERVICE_BATTERY));
if (battery) {
connect(battery, &BatteryService::informationChanged, this, &AsteroidOSDevice::informationChanged, Qt::UniqueConnection);
}


AsteroidTimeService *ats = qobject_cast<AsteroidTimeService*>(service(AsteroidTimeService::UUID_SERVICE_ASTEROID_TIME));
if (ats) {
ats->setCurrentTime();
}


AsteroidMediaService *ms = qobject_cast<AsteroidMediaService*>(service(AsteroidMediaService::UUID_SERVICE_MEDIA));
if (ms) {
ms->enableNotification(AsteroidMediaService::UUID_CHARACTERISTIC_MEDIA_COMMAND);
ms->enableNotification(AsteroidMediaService::UUID_CHARACTERISTIC_MEDIA_VOLUME);
connect(ms, &AsteroidMediaService::serviceEvent, this, &AsteroidOSDevice::serviceEvent, Qt::UniqueConnection);
}

}


void AsteroidOSDevice::authenticated(bool ready)
{
qDebug() << Q_FUNC_INFO << ready;

if (ready) {
setConnectionState("authenticated");
} else {
setConnectionState("authfailed");
}
}

void AsteroidOSDevice::refreshInformation()
{

BatteryService *bat = qobject_cast<BatteryService*>(service(BatteryService::UUID_SERVICE_BATTERY));
if (bat) {
bat->refreshInformation();
}

}

void AsteroidOSDevice::sendWeather(CurrentWeather *weather)
{
AsteroidWeatherService *w = qobject_cast<AsteroidWeatherService*>(service(AsteroidWeatherService::UUID_SERVICE_WEATHER));
if (w){
w->sendWeather(weather);
}
}

void AsteroidOSDevice::setMusicStatus(bool playing, const QString &title, const QString &artist, const QString &album, int duration, int position)
{
Q_UNUSED(duration)
Q_UNUSED(position)

AsteroidMediaService *media = qobject_cast<AsteroidMediaService*>(service(AsteroidMediaService::UUID_SERVICE_MEDIA));
if (media) {
media->setStatus(playing);
media->setAlbum(album);
media->setTrack(title);
media->setArtist(artist);
}
}

void AsteroidOSDevice::serviceEvent(const QString &characteristic, uint8_t event, uint8_t data)
{
if (characteristic == AsteroidMediaService::UUID_CHARACTERISTIC_MEDIA_COMMAND) {
switch(event) {
case AsteroidMediaService::EVENT_MEDIA_PREV:
emit deviceEvent(AbstractDevice::EVENT_MUSIC_PREV);
break;
case AsteroidMediaService::EVENT_MEDIA_NEXT:
emit deviceEvent(AbstractDevice::EVENT_MUSIC_NEXT);
break;
case AsteroidMediaService::EVENT_MEDIA_PLAY:
emit deviceEvent(AbstractDevice::EVENT_MUSIC_PLAY);
break;
case AsteroidMediaService::EVENT_MEDIA_PAUSE:
emit deviceEvent(AbstractDevice::EVENT_MUSIC_PAUSE);
break;
case AsteroidMediaService::EVENT_MEDIA_VOL:
qDebug() << Q_FUNC_INFO << "Command volume" << characteristic << event << data;
if (data < m_prevVolume) {
emit deviceEvent(AbstractDevice::EVENT_MUSIC_VOLDOWN);
} else {
emit deviceEvent(AbstractDevice::EVENT_MUSIC_VOLUP);
}
m_prevVolume = data;
AsteroidMediaService *media = qobject_cast<AsteroidMediaService*>(service(AsteroidMediaService::UUID_SERVICE_MEDIA));
if (media) {
media->setVolume(data);
}

break;


}
} else {
qDebug() << Q_FUNC_INFO << characteristic << event << data;
}

}
Loading