FIRST FLASHED VERSION
This commit is contained in:
parent
72a020127f
commit
a4598ed63e
|
@ -403,6 +403,7 @@ list(APPEND SOURCE_FILES
|
|||
displayapp/screens/Error.cpp
|
||||
displayapp/screens/Alarm.cpp
|
||||
displayapp/screens/Styles.cpp
|
||||
displayapp/screens/Agenda.cpp
|
||||
displayapp/Colors.cpp
|
||||
displayapp/widgets/Counter.cpp
|
||||
|
||||
|
@ -457,6 +458,7 @@ list(APPEND SOURCE_FILES
|
|||
components/ble/MusicService.cpp
|
||||
components/ble/weather/WeatherService.cpp
|
||||
components/ble/NavigationService.cpp
|
||||
components/ble/AgendaService.cpp
|
||||
components/ble/BatteryInformationService.cpp
|
||||
components/ble/FSService.cpp
|
||||
components/ble/ImmediateAlertService.cpp
|
||||
|
@ -528,6 +530,7 @@ list(APPEND RECOVERY_SOURCE_FILES
|
|||
components/ble/ImmediateAlertService.cpp
|
||||
components/ble/ServiceDiscovery.cpp
|
||||
components/ble/NavigationService.cpp
|
||||
components/ble/AgendaService.cpp
|
||||
components/ble/HeartRateService.cpp
|
||||
components/ble/MotionService.cpp
|
||||
components/firmwarevalidator/FirmwareValidator.cpp
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* Copyright (C) 2021 Adam Pigg
|
||||
|
||||
This file is part of InfiniTime.
|
||||
|
||||
InfiniTime is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
InfiniTime is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "components/ble/AgendaService.h"
|
||||
|
||||
#include "systemtask/SystemTask.h"
|
||||
|
||||
namespace {
|
||||
// 3fdaYYXX-e246-472e-b7e0-d2b0f3d9c17a
|
||||
constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) {
|
||||
return ble_uuid128_t {.u = {.type = BLE_UUID_TYPE_128},
|
||||
.value = {0x7a, 0xc1, 0xd9, 0xf3, 0xb0, 0xd2, 0xe0, 0xb7, 0x2e, 0x47, 0x46, 0xe2, x, y, 0xda, 0x3f}};
|
||||
}
|
||||
|
||||
// 00010000-78fc-48fe-8e23-433b3a1942d0
|
||||
constexpr ble_uuid128_t BaseUuid() {
|
||||
return CharUuid(0x00, 0x00);
|
||||
}
|
||||
|
||||
constexpr ble_uuid128_t agendaUuid {BaseUuid()};
|
||||
|
||||
constexpr ble_uuid128_t agendaItemCharUuid {CharUuid(0x01, 0x00)};
|
||||
/*constexpr ble_uuid128_t navNarrativeCharUuid {CharUuid(0x02, 0x00)};
|
||||
constexpr ble_uuid128_t navManDistCharUuid {CharUuid(0x03, 0x00)};
|
||||
constexpr ble_uuid128_t navProgressCharUuid {CharUuid(0x04, 0x00)};*/
|
||||
|
||||
int AgendaCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
|
||||
auto agendaService = static_cast<Pinetime::Controllers::AgendaService*>(arg);
|
||||
return agendaService->OnCommand(conn_handle, attr_handle, ctxt);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Pinetime::Controllers::AgendaService::AgendaService(Pinetime::System::SystemTask& system) : m_system(system) {
|
||||
characteristicDefinition[0] = {.uuid = &agendaItemCharUuid.u,
|
||||
.access_cb = AgendaCallback,
|
||||
.arg = this,
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
|
||||
|
||||
characteristicDefinition[1] = {0};
|
||||
|
||||
serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &agendaUuid.u, .characteristics = characteristicDefinition};
|
||||
serviceDefinition[1] = {0};
|
||||
}
|
||||
|
||||
void Pinetime::Controllers::AgendaService::Init() {
|
||||
int res = 0;
|
||||
res = ble_gatts_count_cfg(serviceDefinition);
|
||||
ASSERT(res == 0);
|
||||
|
||||
res = ble_gatts_add_svcs(serviceDefinition);
|
||||
ASSERT(res == 0);
|
||||
|
||||
m_agenda_times[0] = 1655327841;
|
||||
m_agenda_pieces[0] = "Write AgendaService";
|
||||
}
|
||||
|
||||
int Pinetime::Controllers::AgendaService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
|
||||
|
||||
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
|
||||
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
|
||||
uint8_t data[notifSize + 1];
|
||||
data[notifSize] = '\0';
|
||||
os_mbuf_copydata(ctxt->om, 0, notifSize, data);
|
||||
if (ble_uuid_cmp(ctxt->chr->uuid, &agendaItemCharUuid.u) == 0) {
|
||||
if (notifSize >= 5) {
|
||||
uint8_t itemIndex = (uint8_t) data[0];
|
||||
uint32_t itemTime = ((uint32_t) data[1]) << 24 | ((uint32_t) data[2]) << 16 | ((uint32_t) data[3]) << 8 | ((uint32_t) data[4]);
|
||||
char* sAgendaItem = (char*) &data[5];
|
||||
if (itemIndex <= 15) { // don't allow a buffer overflow
|
||||
m_agenda_times[itemIndex] = itemTime;
|
||||
// implicit std::string copy/conversion here:
|
||||
m_agenda_pieces[itemIndex] = sAgendaItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Pinetime::Controllers::AgendaService::getAgendaTime(uint8_t index) {
|
||||
if (index <= 15) {
|
||||
return m_agenda_times[index];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Pinetime::Controllers::AgendaService::getAgendaPiece(uint8_t index) {
|
||||
if (index <= 15) {
|
||||
return m_agenda_pieces[index];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (C) 2021 Adam Pigg
|
||||
|
||||
This file is part of InfiniTime.
|
||||
|
||||
InfiniTime is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
InfiniTime is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#define min // workaround: nimble's min/max macros conflict with libstdc++
|
||||
#define max
|
||||
#include <host/ble_gap.h>
|
||||
#include <host/ble_uuid.h>
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
namespace Pinetime {
|
||||
namespace System {
|
||||
class SystemTask;
|
||||
}
|
||||
namespace Controllers {
|
||||
|
||||
class AgendaService {
|
||||
public:
|
||||
explicit AgendaService(Pinetime::System::SystemTask& system);
|
||||
|
||||
void Init();
|
||||
|
||||
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
|
||||
|
||||
uint32_t getAgendaTime(uint8_t index);
|
||||
|
||||
std::string getAgendaPiece(uint8_t index);
|
||||
|
||||
private:
|
||||
struct ble_gatt_chr_def characteristicDefinition[2];
|
||||
struct ble_gatt_svc_def serviceDefinition[2];
|
||||
|
||||
uint32_t m_agenda_times[16];
|
||||
std::string m_agenda_pieces[16];
|
||||
|
||||
Pinetime::System::SystemTask& m_system;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -51,6 +51,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
|
|||
heartRateService {systemTask, heartRateController},
|
||||
motionService {systemTask, motionController},
|
||||
fsService {systemTask, fs},
|
||||
agendaService {systemTask},
|
||||
serviceDiscovery({¤tTimeClient, &alertNotificationClient}) {
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "components/ble/NavigationService.h"
|
||||
#include "components/ble/ServiceDiscovery.h"
|
||||
#include "components/ble/MotionService.h"
|
||||
#include "components/ble/AgendaService.h"
|
||||
#include "components/ble/weather/WeatherService.h"
|
||||
#include "components/fs/FS.h"
|
||||
|
||||
|
@ -61,6 +62,9 @@ namespace Pinetime {
|
|||
Pinetime::Controllers::NavigationService& navigation() {
|
||||
return navService;
|
||||
};
|
||||
Pinetime::Controllers::AgendaService& agenda() {
|
||||
return agendaService;
|
||||
};
|
||||
Pinetime::Controllers::AlertNotificationService& alertService() {
|
||||
return anService;
|
||||
};
|
||||
|
@ -103,6 +107,7 @@ namespace Pinetime {
|
|||
HeartRateService heartRateService;
|
||||
MotionService motionService;
|
||||
FSService fsService;
|
||||
AgendaService agendaService;
|
||||
ServiceDiscovery serviceDiscovery;
|
||||
|
||||
uint8_t addrType;
|
||||
|
|
|
@ -478,7 +478,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
|||
break;
|
||||
|
||||
case Apps::Agenda:
|
||||
currentScreen = std::make_unique<Screens::Agenda>(this);
|
||||
currentScreen = std::make_unique<Screens::Agenda>(this, systemTask->nimble().agenda());
|
||||
break;
|
||||
}
|
||||
currentApp = app;
|
||||
|
|
|
@ -1,15 +1,84 @@
|
|||
#include "displayapp/screens/Agenda.h"
|
||||
#include "displayapp/DisplayApp.h"
|
||||
#include "components/ble/AgendaService.h"
|
||||
#include <date/date.h>
|
||||
#include <nrf_log.h>
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
Agenda::Agenda(DisplayApp* app) : Screen(app) {
|
||||
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(title, "My test application");
|
||||
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
Agenda::Agenda(DisplayApp* app, AgendaService& agenda) : Screen(app), agendaSvc(agenda) {
|
||||
lv_obj_t* alignNextTo = lv_scr_act();
|
||||
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
lv_obj_t* agendaItem = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(agendaItem, ".\n.");
|
||||
//lv_label_set_align(agendaItem, LV_LABEL_ALIGN_CENTER);
|
||||
if (i != 0) {
|
||||
lv_obj_align(agendaItem, alignNextTo, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
||||
}
|
||||
|
||||
agendaItems[i] = agendaItem;
|
||||
alignNextTo = agendaItem;
|
||||
}
|
||||
|
||||
pagingOffset = 0;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
Agenda::~Agenda() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void Agenda::Refresh() {
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
auto todayDate = floor<date::days>(now);
|
||||
auto nowTimePart = make_time(now - todayDate);
|
||||
|
||||
//NRF_LOG_INFO("date %s", todayDate);
|
||||
|
||||
//std::cout << todayDate << ' ' << nowTimePart << '\n';
|
||||
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
uint8_t itemIdx = i + pagingOffset;
|
||||
uint32_t time = agendaSvc.getAgendaTime(itemIdx);
|
||||
|
||||
lv_obj_t* agendaItem = agendaItems[i];
|
||||
|
||||
if (time == 0) {
|
||||
lv_label_set_text_static(agendaItem, "--h--\n .....");
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x332222));
|
||||
} else {
|
||||
auto timestamp = std::chrono::system_clock::time_point{time * 1s};
|
||||
auto agendaDate = floor<days>(timestamp);
|
||||
auto agendaTimePart = make_time(timestamp - agendaDate);
|
||||
//std::cout << agendaDate << ' ' << agendaTimePart << '\n';
|
||||
|
||||
/*std::time_t result = std::time(nullptr);
|
||||
std::time_t result = std::time(nullptr);
|
||||
std::chrono::time_point = */;
|
||||
if (agendaDate == todayDate) {
|
||||
lv_label_set_text_fmt(agendaItem, "%02dh%02d\n %s", agendaTimePart.hours(), agendaTimePart.minutes(), agendaSvc.getAgendaPiece(itemIdx).data());
|
||||
} else {
|
||||
auto ymd = year_month_day(agendaDate);
|
||||
lv_label_set_text_fmt(agendaItem, "%04d-%02d-%02d %02dh%02d\n %s", ymd.year(), ymd.month(), ymd.day(), agendaTimePart.hours(), agendaTimePart.minutes(), agendaSvc.getAgendaPiece(itemIdx).data());
|
||||
}
|
||||
|
||||
if (timestamp + 30min < now) {
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x334433));
|
||||
} else if (timestamp + 5min < now) {
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
|
||||
} else if (timestamp - 5min < now && now < timestamp + 5min) {
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFA500));
|
||||
} else if (now + 5min < timestamp) {
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00));
|
||||
} else if (now + 30min < timestamp) {
|
||||
lv_obj_set_style_local_text_color(agendaItem, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFFFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,23 @@
|
|||
#include <lvgl/lvgl.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class AgendaService;
|
||||
}
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class Agenda : public Screen {
|
||||
public:
|
||||
Agenda(DisplayApp* app);
|
||||
Agenda(DisplayApp* app, Pinetime::Controllers::AgendaService& agendaSvc);
|
||||
~Agenda() override;
|
||||
|
||||
void Refresh() override;
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::AgendaService& agendaSvc;
|
||||
|
||||
lv_obj_t* agendaItems[4];
|
||||
uint8_t pagingOffset;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue