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

Infinitime Simple Weather Service #319

Merged
merged 25 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b4266e0
adjust weather structures for simple service
jmlich Nov 2, 2023
6fced94
prepare bytes
jmlich Nov 3, 2023
ce67a20
show weather icon
jmlich Nov 3, 2023
f79b083
send timestamp as time_t (seconds since epoch)
jmlich Nov 5, 2023
0015d9a
expose icon for forecast
jmlich Nov 13, 2023
aaf131d
updated format of ble messages
jmlich Nov 13, 2023
c96c599
remove copy paste
jmlich Nov 15, 2023
b22e69c
don't round double before -273.15
jmlich Nov 15, 2023
712f11c
Merge branch 'master' into weather
jmlich Nov 16, 2023
9f1c7d3
fix forecast output
jmlich Nov 16, 2023
9655aa5
avoid premature rounding of temperature
jmlich Nov 18, 2023
f575960
city name to ascii, incorrect conversion K->˚C
jmlich Nov 19, 2023
836bcc8
SimpleWeatherService : update the service according to the new specif…
JF002 Dec 9, 2023
1e0700b
We aren't using night icons anyway
jmlich Dec 10, 2023
43ce5af
Merge remote-tracking branch 'upstream/master' into weather
jmlich Dec 10, 2023
2c29d19
QDateTime::fromSecsSinceEpoch is not compatible with old qt (SailfishOS)
jmlich Dec 10, 2023
82f9bec
append(qsizetype count, char ch) is not in SailfishOS
jmlich Dec 10, 2023
dee7e3b
round temperature, assign numbers to icon enum
jmlich Dec 11, 2023
54695e0
don't replace current weather from forecast
jmlich Dec 12, 2023
b8e0801
Allow old weather service
jmlich Dec 12, 2023
690b366
Merge branch 'master' into weather
jmlich Dec 22, 2023
91814aa
SimpleWeatherService : Update protocol (InfiniTime now uses int16_t i…
JF002 Dec 23, 2023
f969c2c
[bangle.js] missing items were added
jmlich Dec 24, 2023
9ffd6c0
[mibandservice] fix weather precision
jmlich Dec 24, 2023
7eb0d6b
rename SimpleWeatherService to PineTimeSimpleWeatherService
jmlich Dec 24, 2023
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
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