Skip to content

Commit

Permalink
Merge pull request #319 from jmlich/weather
Browse files Browse the repository at this point in the history
Infinitime Simple Weather Service
  • Loading branch information
piggz authored Dec 27, 2023
2 parents 636a1f0 + 7eb0d6b commit 094fd08
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 47 deletions.
2 changes: 2 additions & 0 deletions daemon/daemon.pro
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ SOURCES += \
src/services/infinitimemotionservice.cpp \
src/services/infinitimenavservice.cpp \
src/services/infinitimeweatherservice.cpp \
src/services/pinetimesimpleweatherservice.cpp \
src/services/pinetimemusicservice.cpp \
src/services/uartservice.cpp \
src/typeconversion.cpp \
Expand Down Expand Up @@ -205,6 +206,7 @@ HEADERS += \
src/services/infinitimemotionservice.h \
src/services/infinitimenavservice.h \
src/services/infinitimeweatherservice.h \
src/services/pinetimesimpleweatherservice.h \
src/services/pinetimemusicservice.h \
src/services/uartservice.h \
src/services/immediatealertservice.h \
Expand Down
6 changes: 3 additions & 3 deletions daemon/src/devices/banglejsdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ void BangleJSDevice::sendWeather(CurrentWeather *weather)
QJsonObject o;
o.insert("t", "weather");
o.insert("temp", weather->temperature());
o.insert("hum", 0); //TODO we dont have this
o.insert("hum", weather->humidity());
o.insert("txt", weather->description());
o.insert("wind", 0); //TODO we dont have this
o.insert("wdir", ""); // TODO we dont have this
o.insert("wind", weather->windSpeed());
o.insert("wdir", weather->windDeg());
o.insert("loc", weather->city()->name());

uart->txJson(o);
Expand Down
9 changes: 9 additions & 0 deletions daemon/src/devices/pinetimejfdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "hrmservice.h"
#include "infinitimemotionservice.h"
#include "infinitimeweatherservice.h"
#include "pinetimesimpleweatherservice.h"
#include "adafruitblefsservice.h"
#include "batteryservice.h"
#include "amazfishconfig.h"
Expand Down Expand Up @@ -154,6 +155,8 @@ void PinetimeJFDevice::parseServices()
addService(HRMService::UUID_SERVICE_HRM, new HRMService(path, this));
} else if (uuid == InfiniTimeMotionService::UUID_SERVICE_MOTION && !service(InfiniTimeMotionService::UUID_SERVICE_MOTION)) {
addService(InfiniTimeMotionService::UUID_SERVICE_MOTION, new InfiniTimeMotionService(path, this));
} else if (uuid == PineTimeSimpleWeatherService::UUID_SERVICE_SIMPLE_WEATHER && !service(PineTimeSimpleWeatherService::UUID_SERVICE_SIMPLE_WEATHER)) {
addService(PineTimeSimpleWeatherService::UUID_SERVICE_SIMPLE_WEATHER, new PineTimeSimpleWeatherService(path, this));
} else if (uuid == InfiniTimeWeatherService::UUID_SERVICE_WEATHER && !service(InfiniTimeWeatherService::UUID_SERVICE_WEATHER)) {
addService(InfiniTimeWeatherService::UUID_SERVICE_WEATHER, new InfiniTimeWeatherService(path, this));
} else if (uuid == AdafruitBleFsService::UUID_SERVICE_FS && !service(AdafruitBleFsService::UUID_SERVICE_FS)) {
Expand Down Expand Up @@ -496,4 +499,10 @@ void PinetimeJFDevice::sendWeather(CurrentWeather *weather)
if (w){
w->sendWeather(weather);
}

PineTimeSimpleWeatherService *sw = qobject_cast<PineTimeSimpleWeatherService*>(service(PineTimeSimpleWeatherService::UUID_SERVICE_SIMPLE_WEATHER));

if (sw){
sw->sendWeather(weather);
}
}
10 changes: 5 additions & 5 deletions daemon/src/services/mibandservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ void MiBandService::sendWeather(const CurrentWeather *weather, bool supportsCond
QBuffer buffer(&buf);
buffer.open(QIODevice::WriteOnly);

char temp = weather->temperature() - 273;
char temp = weather->temperature() - 273.15;
qint32 dt = qToLittleEndian(weather->dateTime());

qDebug() << dt << temp << condition;
Expand Down Expand Up @@ -830,8 +830,8 @@ void MiBandService::sendWeather(const CurrentWeather *weather, bool supportsCond
buffer.putChar(NR_DAYS);
buffer.putChar(condition);
buffer.putChar(condition);
buffer.putChar((char) (weather->maxTemperature() - 273));
buffer.putChar((char) (weather->minTemperature() - 273));
buffer.putChar((char) (weather->maxTemperature() - 273.15));
buffer.putChar((char) (weather->minTemperature() - 273.15));
if (supportsConditionString) {
buffer.write(weather->description().toLatin1());
buffer.putChar((char)0x00);
Expand All @@ -845,8 +845,8 @@ void MiBandService::sendWeather(const CurrentWeather *weather, bool supportsCond

buffer.putChar(condition);
buffer.putChar(condition);
buffer.putChar((char) (fc.maxTemperature() - 273));
buffer.putChar((char) (fc.minTemperature() - 273));
buffer.putChar((char) (fc.maxTemperature() - 273.15));
buffer.putChar((char) (fc.minTemperature() - 273.15));

if (supportsConditionString) {
buffer.write(fc.description().toLatin1());
Expand Down
141 changes: 141 additions & 0 deletions daemon/src/services/pinetimesimpleweatherservice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include "pinetimesimpleweatherservice.h"
#include "typeconversion.h"
#include "codec.h"

#include <QDateTime>
#include <QDebug>
#include <math.h>

const char* PineTimeSimpleWeatherService::UUID_SERVICE_SIMPLE_WEATHER = "00050000-78fc-48fe-8e23-433b3a1942d0";
const char* PineTimeSimpleWeatherService::UUID_CHARACTERISTIC_SIMPLE_WEATHER_DATA = "00050001-78fc-48fe-8e23-433b3a1942d0";

PineTimeSimpleWeatherService::PineTimeSimpleWeatherService(const QString &path, QObject *parent) : QBLEService(UUID_SERVICE_SIMPLE_WEATHER, path, parent)
{
qDebug() << Q_FUNC_INFO;
}


void PineTimeSimpleWeatherService::sendWeather(CurrentWeather *weather)
{

qDebug() << "Current weather data"
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
<< QDateTime::fromSecsSinceEpoch(weather->dateTime())
#else
<< QDateTime::fromTime_t(weather->dateTime())
#endif
<< weather->dateTime()
<< weather->temperature() - 273.15
<< weather->minTemperature() - 273.15
<< weather->maxTemperature() - 273.15
<< weather->city()->name()
<< weather->weatherIcon()
<< QMetaEnum::fromType<PineTimeSimpleWeatherService::WeatherIcons>().valueToKey(
(int)iconToEnum(weather->weatherIcon())
)
<< (int)iconToEnum(weather->weatherIcon())
// << weather->clouds()
// << weather->humidity()
// << weather->windDeg()
// << weather->windSpeed()
// << weather->windGusts()
;

QByteArray cityNameBytes = weather->city()->name().toLocal8Bit().left(32);
if(cityNameBytes.size() < 32) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
cityNameBytes.append(32-cityNameBytes.size(), 0x00);
#else
for (int i = 0; i < (32 - cityNameBytes.size()); i++) {
cityNameBytes.append( '\0' );
}
#endif
}

QByteArray weatherBytes;

weatherBytes += TypeConversion::fromInt8(0); // message type
weatherBytes += TypeConversion::fromInt8(0); // version information
weatherBytes += TypeConversion::fromInt64(weather->dateTime());
weatherBytes += TypeConversion::fromInt16( round((weather->temperature() - 273.15) * 100) );
weatherBytes += TypeConversion::fromInt16( round((weather->minTemperature() - 273.15) * 100) );
weatherBytes += TypeConversion::fromInt16( round((weather->maxTemperature() - 273.15) * 100) );
weatherBytes += cityNameBytes;
weatherBytes += TypeConversion::fromInt8( (int)iconToEnum(weather->weatherIcon()) );

// weatherBytes += TypeConversion::fromInt8( weather->clouds() );
// weatherBytes += TypeConversion::fromInt8( weather->humidity() );

// weatherBytes += TypeConversion::fromInt16( (int)(100 * weather->windDeg()));
// weatherBytes += TypeConversion::fromInt16((int)(100 * weather->windSpeed()));
// weatherBytes += TypeConversion::fromInt16((int)(100 * weather->windGusts()));

qDebug() << "Weather bytes" << weatherBytes.toHex();

writeValue(UUID_CHARACTERISTIC_SIMPLE_WEATHER_DATA, weatherBytes);


int fcDays = std::min(weather->forecastCount(), 5);

QByteArray forecastBytes;
forecastBytes += TypeConversion::fromInt8(1); // message type
forecastBytes += TypeConversion::fromInt8(0); // version information
forecastBytes += TypeConversion::fromInt64(weather->dateTime());
forecastBytes += TypeConversion::fromInt8(fcDays);



for (int f = 0; (f < fcDays); f++) {
CurrentWeather::Forecast fc = weather->forecast(f);
// qDebug() << "Forecast:" << f << fc.dateTime()<< fc.weatherCode() << (fc.maxTemperature() - 273) << (fc.minTemperature() - 273) << fc.humidity() << fc.pressure() << fc.windMaxSpeed() << fc.clouds();


qDebug() << "Forecast Day" << f
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
<< QDateTime::fromSecsSinceEpoch(fc.dateTime())
#else
<< QDateTime::fromTime_t(fc.dateTime())
#endif
<< fc.dateTime()
<< fc.minTemperature() - 273.15
<< fc.maxTemperature() - 273.15
<< fc.weatherIcon()
<< QMetaEnum::fromType<PineTimeSimpleWeatherService::WeatherIcons>().valueToKey(
(int)iconToEnum(fc.weatherIcon())
)
<< (int)iconToEnum(fc.weatherIcon())
;

forecastBytes += TypeConversion::fromInt16( round((fc.minTemperature() - 273.15) * 100) );
forecastBytes += TypeConversion::fromInt16( round((fc.maxTemperature() - 273.15) * 100) );
forecastBytes += TypeConversion::fromInt8( (int)iconToEnum(fc.weatherIcon()) );

}

qDebug() << "Forecast bytes" << forecastBytes.toHex();

writeValue(UUID_CHARACTERISTIC_SIMPLE_WEATHER_DATA, forecastBytes);

}

PineTimeSimpleWeatherService::WeatherIcons PineTimeSimpleWeatherService::iconToEnum(const QString& iconName) {
if (iconName == "01d") return WeatherIcons::ClearSky;
if (iconName == "01n") return WeatherIcons::ClearSky;
if (iconName == "02d") return WeatherIcons::FewClouds;
if (iconName == "02n") return WeatherIcons::FewClouds;
if (iconName == "03d") return WeatherIcons::ScatteredClouds;
if (iconName == "03n") return WeatherIcons::ScatteredClouds;
if (iconName == "04d") return WeatherIcons::BrokenClouds;
if (iconName == "04n") return WeatherIcons::BrokenClouds;
if (iconName == "09d") return WeatherIcons::ShowerRain;
if (iconName == "09n") return WeatherIcons::ShowerRain;
if (iconName == "10d") return WeatherIcons::Rain;
if (iconName == "10n") return WeatherIcons::Rain;
if (iconName == "11d") return WeatherIcons::Thunderstorm;
if (iconName == "11n") return WeatherIcons::Thunderstorm;
if (iconName == "13d") return WeatherIcons::Snow;
if (iconName == "13n") return WeatherIcons::Snow;
if (iconName == "50d") return WeatherIcons::Mist;
if (iconName == "50n") return WeatherIcons::Mist;
return WeatherIcons::Unknown;
}
39 changes: 39 additions & 0 deletions daemon/src/services/pinetimesimpleweatherservice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef PINETIMESIMPLEWEATHERSERVICE_H
#define PINETIMESIMPLEWEATHERSERVICE_H

#include <QObject>
#include "qble/qbleservice.h"
#include "devices/abstractdevice.h"

class PineTimeSimpleWeatherService : public QBLEService
{
Q_OBJECT
public:
static const char *UUID_SERVICE_SIMPLE_WEATHER;
static const char *UUID_CHARACTERISTIC_SIMPLE_WEATHER_DATA;

explicit PineTimeSimpleWeatherService(const QString &path, QObject *parent);


void sendWeather(CurrentWeather *weather);

enum class WeatherIcons {
ClearSky = 0,
FewClouds = 1,
ScatteredClouds = 2,
BrokenClouds = 3,
ShowerRain = 4,
Rain = 5,
Thunderstorm = 6,
Snow = 7,
Mist = 8,
Unknown = 255 // for any icon not listed above
};

Q_ENUM(WeatherIcons)

WeatherIcons iconToEnum(const QString& iconName);

};

#endif // #define PINETIMESIMPLEWEATHERSERVICE_H
18 changes: 17 additions & 1 deletion daemon/src/typeconversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ QByteArray fromInt32(int val)
return QByteArray(1, val & 0xff) + QByteArray(1, ((val >> 8) & 0xff)) + QByteArray(1, ((val >> 16) & 0xff)) + QByteArray(1, ((val >> 24) & 0xff));
}

QByteArray fromInt64(long long int val)
{
QByteArray ret = QByteArray(1, val & 0xff)
+ QByteArray(1, ((val >> 8) & 0xff))
+ QByteArray(1, ((val >> 16) & 0xff))
+ QByteArray(1, ((val >> 24) & 0xff))
+ QByteArray(1, ((val >> 32) & 0xff))
+ QByteArray(1, ((val >> 40) & 0xff))
+ QByteArray(1, ((val >> 48) & 0xff))
+ QByteArray(1, ((val >> 56) & 0xff));

qDebug() << "Converting int64 to char" << val << " " << ret.toHex();

return ret;
}


QByteArray dateTimeToBytes(const QDateTime &dt, int format, bool adjustForTZ)
{
QByteArray ret;
Expand Down Expand Up @@ -129,7 +146,6 @@ int toUint16(char val1, char val2) {
return (val1 & 0xff) | ((val2 & 0xff) << 8);
}


int toUint32(char val1, char val2, char val3, char val4) {
return (val1 & 0xff) | ((val2 & 0xff) << 8) | ((val3 & 0xff) << 16) | ((val4 & 0xff) << 24);
}
Expand Down
1 change: 1 addition & 0 deletions daemon/src/typeconversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ QByteArray fromInt8(int val);
QByteArray fromInt16(int val);
QByteArray fromInt24(int val);
QByteArray fromInt32(int val);
QByteArray fromInt64(long long int val);
QDateTime rawBytesToDateTime(const QByteArray &value, bool honorDeviceTimeOffset);
QByteArray dateTimeToBytes(const QDateTime &dt, int format, bool adjustForTZ = true);
int toUint16(char val1, char val2);
Expand Down
Loading

0 comments on commit 094fd08

Please sign in to comment.