RTC表示
This commit is contained in:
parent
68a5f0dcce
commit
5e052dba93
|
|
@ -12,11 +12,17 @@ namespace {
|
|||
constexpr char kNusServiceUuid[] = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
|
||||
constexpr char kNusRxUuid[] = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
|
||||
constexpr char kNusTxUuid[] = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
|
||||
constexpr int64_t kInitialYear = 1700;
|
||||
constexpr int64_t kSecondsPerDay = 86400;
|
||||
|
||||
Adafruit_AHTX0 aht20;
|
||||
BH1750 bh1750;
|
||||
bool aht20Ready = false;
|
||||
bool bh1750Ready = false;
|
||||
|
||||
bool isLeapYear(int year) {
|
||||
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
|
||||
}
|
||||
}
|
||||
|
||||
class SensorLoggerCallbacks : public BLECharacteristicCallbacks {
|
||||
|
|
@ -96,6 +102,47 @@ bool SensorLogger::hasReading() const {
|
|||
return logCount_ != 0;
|
||||
}
|
||||
|
||||
size_t SensorLogger::logCount() const {
|
||||
return logCount_;
|
||||
}
|
||||
|
||||
bool SensorLogger::getCurrentTime(char* buffer, size_t bufferSize) const {
|
||||
if (bufferSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t timestamp = currentTimestamp();
|
||||
if (timeSynchronized_) {
|
||||
time_t unixTimestamp = static_cast<time_t>(timestamp);
|
||||
struct tm date;
|
||||
localtime_r(&unixTimestamp, &date);
|
||||
strftime(buffer, bufferSize, "%Y/%m/%d %H:%M:%S", &date);
|
||||
return true;
|
||||
}
|
||||
|
||||
int year = static_cast<int>(kInitialYear);
|
||||
int month = 1;
|
||||
int day = 1;
|
||||
int64_t days = timestamp / kSecondsPerDay;
|
||||
int seconds = static_cast<int>(timestamp % kSecondsPerDay);
|
||||
while (days >= (isLeapYear(year) ? 366 : 365)) {
|
||||
days -= isLeapYear(year) ? 366 : 365;
|
||||
++year;
|
||||
}
|
||||
const int daysInMonth[] = {
|
||||
31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30,
|
||||
31, 31, 30, 31, 30, 31
|
||||
};
|
||||
while (days >= daysInMonth[month - 1]) {
|
||||
days -= daysInMonth[month - 1];
|
||||
++month;
|
||||
}
|
||||
day += static_cast<int>(days);
|
||||
snprintf(buffer, bufferSize, "%04d/%02d/%02d %02d:%02d:%02d",
|
||||
year, month, day, seconds / 3600, (seconds / 60) % 60, seconds % 60);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SensorLogger::readAndStore() {
|
||||
sensors_event_t humidityEvent;
|
||||
sensors_event_t temperatureEvent;
|
||||
|
|
@ -193,7 +240,7 @@ void SensorLogger::sendLog() {
|
|||
size_t logIndex = (logStart_ + index) % kMaxLogEntries;
|
||||
const SensorReading& reading = log_[logIndex];
|
||||
char line[128];
|
||||
snprintf(line, sizeof(line), "%lu,%.2f,%.2f,%.2f,%u,%s\n",
|
||||
snprintf(line, sizeof(line), "%lld,%.2f,%.2f,%.2f,%u,%s\n",
|
||||
reading.timestamp,
|
||||
reading.temperature,
|
||||
reading.humidity,
|
||||
|
|
@ -224,7 +271,7 @@ void SensorLogger::clearLog() {
|
|||
logCount_ = 0;
|
||||
}
|
||||
|
||||
unsigned long SensorLogger::currentTimestamp() const {
|
||||
unsigned long elapsedSeconds = millis() / 1000UL;
|
||||
int64_t SensorLogger::currentTimestamp() const {
|
||||
int64_t elapsedSeconds = millis() / 1000UL;
|
||||
return timeSynchronized_ ? epochOffset_ + elapsedSeconds : elapsedSeconds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class BLECharacteristic;
|
|||
class BLEServer;
|
||||
|
||||
struct SensorReading {
|
||||
unsigned long timestamp;
|
||||
int64_t timestamp;
|
||||
float temperature;
|
||||
float humidity;
|
||||
float illuminance;
|
||||
|
|
@ -21,6 +21,8 @@ public:
|
|||
bool update();
|
||||
const SensorReading& latest() const;
|
||||
bool hasReading() const;
|
||||
size_t logCount() const;
|
||||
bool getCurrentTime(char* buffer, size_t bufferSize) const;
|
||||
|
||||
private:
|
||||
static constexpr unsigned long kMeasureIntervalMs = 3600000UL;
|
||||
|
|
@ -32,7 +34,7 @@ private:
|
|||
void sendNotification(const char* data);
|
||||
void sendLog();
|
||||
void clearLog();
|
||||
unsigned long currentTimestamp() const;
|
||||
int64_t currentTimestamp() const;
|
||||
|
||||
BLEServer* server_ = nullptr;
|
||||
BLECharacteristic* txCharacteristic_ = nullptr;
|
||||
|
|
@ -42,7 +44,7 @@ private:
|
|||
size_t logCount_ = 0;
|
||||
uint8_t soilPin_ = 0;
|
||||
unsigned long lastMeasure_ = 0;
|
||||
unsigned long epochOffset_ = 0;
|
||||
int64_t epochOffset_ = 0;
|
||||
bool timeSynchronized_ = false;
|
||||
String bluetoothName_;
|
||||
String commandBuffer_;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "NeoPixelController.h"
|
||||
#include "SensorLogger.h"
|
||||
|
||||
const char kBluetoothName[] = "BT_Speaker5.32";
|
||||
const char kBluetoothName[] = "BT_Speaker5.4";
|
||||
|
||||
// I2C接続のOLED設定 (SSD1306 128x64)
|
||||
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
|
||||
|
|
@ -18,25 +18,37 @@ String currentTitle = "未接続";
|
|||
String currentArtist = "";
|
||||
int currentVolumePercent = 0; // 音量 (0 ~ 100%)
|
||||
bool bluetoothConnected = false;
|
||||
bool musicPlaying = false;
|
||||
unsigned long lastDisplayUpdate = 0;
|
||||
|
||||
// 画面全体を再描画する関数
|
||||
void updateDisplay() {
|
||||
u8g2.clearBuffer();
|
||||
|
||||
if (!bluetoothConnected) {
|
||||
if (!bluetoothConnected || !musicPlaying) {
|
||||
u8g2.setFont(u8g2_font_6x10_tf);
|
||||
const SensorReading& reading = sensorLogger.latest();
|
||||
|
||||
char sensorLine[32];
|
||||
char timeLine[24];
|
||||
if (sensorLogger.getCurrentTime(timeLine, sizeof(timeLine))) {
|
||||
u8g2.drawStr(0, 9, timeLine);
|
||||
} else {
|
||||
u8g2.drawStr(0, 9, "RTC: --/--/-- --:--:--");
|
||||
}
|
||||
|
||||
snprintf(sensorLine, sizeof(sensorLine), "Log: %u", static_cast<unsigned int>(sensorLogger.logCount()));
|
||||
u8g2.drawStr(0, 20, sensorLine);
|
||||
|
||||
snprintf(sensorLine, sizeof(sensorLine), "T:%5.1fC H:%5.1f%%",
|
||||
reading.temperature, reading.humidity);
|
||||
u8g2.drawStr(0, 12, sensorLine);
|
||||
u8g2.drawStr(0, 32, sensorLine);
|
||||
|
||||
snprintf(sensorLine, sizeof(sensorLine), "Light: %6.1f lx", reading.illuminance);
|
||||
u8g2.drawStr(0, 30, sensorLine);
|
||||
u8g2.drawStr(0, 44, sensorLine);
|
||||
|
||||
snprintf(sensorLine, sizeof(sensorLine), "Soil: %4u", reading.soilMoisture);
|
||||
u8g2.drawStr(0, 48, sensorLine);
|
||||
u8g2.drawStr(0, 56, sensorLine);
|
||||
u8g2.sendBuffer();
|
||||
return;
|
||||
}
|
||||
|
|
@ -88,7 +100,7 @@ void avrc_metadata_callback(uint8_t id, const uint8_t *text) {
|
|||
updated = true;
|
||||
}
|
||||
|
||||
if (updated && bluetoothConnected) {
|
||||
if (updated && bluetoothConnected && musicPlaying) {
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
|
|
@ -96,17 +108,22 @@ void avrc_metadata_callback(uint8_t id, const uint8_t *text) {
|
|||
// 音量変更時のコールバック関数
|
||||
void volume_changed_callback(int volume) {
|
||||
currentVolumePercent = map(volume, 0, 127, 0, 100);
|
||||
if (bluetoothConnected) {
|
||||
if (bluetoothConnected && musicPlaying) {
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void audio_state_changed_callback(esp_a2d_audio_state_t state, void *) {
|
||||
neoPixelController.setPlaying(state == ESP_A2D_AUDIO_STATE_STARTED);
|
||||
musicPlaying = state == ESP_A2D_AUDIO_STATE_STARTED;
|
||||
neoPixelController.setPlaying(musicPlaying);
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void connection_state_changed_callback(esp_a2d_connection_state_t state, void *) {
|
||||
bluetoothConnected = state == ESP_A2D_CONNECTION_STATE_CONNECTED;
|
||||
if (!bluetoothConnected) {
|
||||
musicPlaying = false;
|
||||
}
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +142,7 @@ void setup() {
|
|||
|
||||
sensorLogger.begin(32);
|
||||
updateDisplay();
|
||||
lastDisplayUpdate = millis();
|
||||
|
||||
// I2S ピン設定 (BCK: 27, WS: 25, DOUT: 26)
|
||||
i2s_pin_config_t my_pin_config = {
|
||||
|
|
@ -148,7 +166,11 @@ void setup() {
|
|||
|
||||
void loop() {
|
||||
neoPixelController.update();
|
||||
if (sensorLogger.update() && !bluetoothConnected) {
|
||||
bool newReading = sensorLogger.update();
|
||||
unsigned long now = millis();
|
||||
if ((!bluetoothConnected || !musicPlaying)
|
||||
&& (newReading || now - lastDisplayUpdate >= 1000UL)) {
|
||||
lastDisplayUpdate = now;
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue