Transmit last temperature time

This commit is contained in:
Christoph Hagen 2023-06-03 08:14:30 +02:00
parent 3727fdb694
commit c4d8116cfd
4 changed files with 118 additions and 70 deletions

View File

@ -17,6 +17,8 @@ constexpr size_t rtcStorageSize = 7600;
constexpr size_t maxEepromSize = 13350;
constexpr size_t eepromSize = 13350;
constexpr size_t totalStorageSize = rtcStorageSize + eepromSize;
// The minimum temperature to store, in millidegrees celcius
// True minimum will be higher by 1°, since two values are reserved
constexpr long temperatureShiftForStorage = -40000;
@ -44,6 +46,8 @@ uint16_t getNumberOfMeasurements();
uint8_t getLastTemperature(uint8_t sensorIndex);
uint16_t getTimeSinceValidTemperature(uint8_t sensorIndex);
uint16_t getRecordedBytesAtOffset(uint8_t* buffer, uint16_t offset, uint16_t count);
void discardAllRecordedBytes();

View File

@ -30,7 +30,7 @@ uint8_t* bluetoothResponse;
size_t bluetoothDataCount = 0;
void bluetoothStartAdvertising();
void bluetoothDidReceiveData(uint8_t* buffer, size_t count);
void bluetoothDidReceiveData(uint8_t* buffer, uint16_t count);
class BluetoothConnection: public BLEServerCallbacks {
@ -215,86 +215,121 @@ uint16_t readNumberFromReceivedBuffer(uint8_t* buffer) {
return *((uint16_t*) buffer + 1);
}
void bluetoothDidReceiveData(uint8_t* buffer, size_t count) {
void fillInfo() {
uint16_t value;
// BluetoothResponse::success
setResponse(BluetoothResponse::success);
// the number of bytes as a uint16_t (2 bytes)
value = getTotalNumberOfStoredBytes();
memcpy(bluetoothDataBuffer, &value, sizeof(uint16_t));
bluetoothDataCount = sizeof(uint16_t);
// the number of seconds until the next measurement as a uint16_t (2 bytes)
value = secondsUntilNextTemperatureMeasurement();
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of seconds between measurements as a uint16_t (2 bytes)
value = temperatureMeasurementIntervalSeconds;
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of measurements as a uint16_t (2 bytes)
value = getNumberOfMeasurements();
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the maximum number of bytes that can be copied
value = bluetoothMaxDataSize;
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of seconds since power on as a uint32_t (4 bytes)
uint32_t currentTime = time(NULL);
memcpy(bluetoothDataBuffer + bluetoothDataCount, &currentTime, sizeof(uint32_t));
bluetoothDataCount += sizeof(uint32_t);
// The last temperatures
bluetoothDataBuffer[bluetoothDataCount] = getLastTemperature(0);
bluetoothDataCount += sizeof(uint8_t);
bluetoothDataBuffer[bluetoothDataCount] = getLastTemperature(1);
bluetoothDataCount += sizeof(uint8_t);
// Temperature sensor addresses
copySensorAddress(0, bluetoothDataBuffer + bluetoothDataCount);
bluetoothDataCount += TEMPERATURE_SENSOR_ADDRESS_SIZE;
copySensorAddress(1, bluetoothDataBuffer + bluetoothDataCount);
bluetoothDataCount += TEMPERATURE_SENSOR_ADDRESS_SIZE;
// Time since measurement of sensor 0
value = getTimeSinceValidTemperature(0);
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// Time since measurement of sensor 1
value = getTimeSinceValidTemperature(1);
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
value = totalStorageSize;
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
}
void getRecordingData(uint8_t* buffer, uint16_t count) {
if (count != 2 * sizeof(uint16_t)) {
setResponseWithoutData(BluetoothResponse::invalidCommand);
return;
}
uint16_t byteCount;
memcpy(&byteCount, buffer, sizeof(uint16_t));
if (byteCount > bluetoothMaxDataSize) {
setResponseWithoutData(BluetoothResponse::responseTooLarge);
return;
}
uint16_t byteOffset;
memcpy(&byteOffset, buffer + sizeof(uint16_t), sizeof(uint16_t));
bluetoothDataCount = getRecordedBytesAtOffset(bluetoothDataBuffer, byteOffset, byteCount);
}
void clearRecordingBuffer(uint8_t* buffer, uint16_t count) {
if (count != sizeof(uint16_t)) {
setResponseWithoutData(BluetoothResponse::invalidCommand);
return;
}
uint16_t byteCount;
memcpy(&byteCount, buffer, sizeof(uint16_t));
if (byteCount != getTotalNumberOfStoredBytes()) {
setResponseWithoutData(BluetoothResponse::invalidNumberOfBytesToDelete);
return;
}
discardAllRecordedBytes();
setResponseWithoutData(BluetoothResponse::success);
}
void bluetoothDidReceiveData(uint8_t* buffer, uint16_t count) {
if (count < 1) {
setResponseWithoutData(BluetoothResponse::invalidCommand);
return;
}
uint32_t currentTime;
uint16_t value;
BluetoothRequest request = static_cast<BluetoothRequest>(buffer[0]);
switch (request) {
case BluetoothRequest::getInfo:
// BluetoothResponse::success
setResponse(BluetoothResponse::success);
// the number of bytes as a uint16_t (2 bytes)
value = getTotalNumberOfStoredBytes();
memcpy(bluetoothDataBuffer, &value, sizeof(uint16_t));
bluetoothDataCount = sizeof(uint16_t);
// the number of seconds until the next measurement as a uint16_t (2 bytes)
value = secondsUntilNextTemperatureMeasurement();
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of seconds between measurements as a uint16_t (2 bytes)
value = temperatureMeasurementIntervalSeconds;
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of measurements as a uint16_t (2 bytes)
value = getNumberOfMeasurements();
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the maximum number of bytes that can be copied
value = bluetoothMaxDataSize;
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
bluetoothDataCount += sizeof(uint16_t);
// the number of seconds since power on as a uint32_t (4 bytes)
currentTime = time(NULL);
memcpy(bluetoothDataBuffer + bluetoothDataCount, &currentTime, sizeof(uint32_t));
bluetoothDataCount += sizeof(uint32_t);
// The last temperatures
bluetoothDataBuffer[bluetoothDataCount] = getLastTemperature(0);
bluetoothDataCount += sizeof(uint8_t);
bluetoothDataBuffer[bluetoothDataCount] = getLastTemperature(1);
bluetoothDataCount += sizeof(uint8_t);
// Temperature sensor addresses
copySensorAddress(0, bluetoothDataBuffer + bluetoothDataCount);
bluetoothDataCount += TEMPERATURE_SENSOR_ADDRESS_SIZE;
copySensorAddress(1, bluetoothDataBuffer + bluetoothDataCount);
bluetoothDataCount += TEMPERATURE_SENSOR_ADDRESS_SIZE;
fillInfo();
break;
case BluetoothRequest::clearRecordingBuffer:
memcpy(&count, buffer + 1, sizeof(uint16_t));
if (count != getTotalNumberOfStoredBytes()) {
setResponseWithoutData(BluetoothResponse::invalidNumberOfBytesToDelete);
} else {
discardAllRecordedBytes();
setResponseWithoutData(BluetoothResponse::success);
}
clearRecordingBuffer(buffer + sizeof(uint8_t), count - sizeof(uint8_t));
break;
case BluetoothRequest::getRecordingData:
if (count != sizeof(uint16_t) + sizeof(uint8_t)) {
setResponseWithoutData(BluetoothResponse::invalidCommand);
break;
}
memcpy(&value, buffer + sizeof(uint8_t) , sizeof(uint16_t));
memcpy(&count, buffer + sizeof(uint8_t) + sizeof(uint16_t), sizeof(uint16_t));
if (count > bluetoothMaxDataSize) {
setResponseWithoutData(BluetoothResponse::responseTooLarge);
break;
}
count = getRecordedBytesAtOffset(bluetoothDataBuffer, value, count);
bluetoothDataCount = count;
getRecordingData(buffer + sizeof(uint8_t), count - sizeof(uint8_t));
break;
default:

View File

@ -134,7 +134,7 @@ void loop() {
setNextTemperatureMeasurementInterval();
}
if (wakeupButtonIsPressed()) {
if (wakeupButtonIsPressed() || bluetoothIsConnected()) {
bluetoothConfigure(); // Only done once internally
updateStayAwakeTime();
}
@ -146,5 +146,7 @@ void loop() {
// May return, if less then one second to wait
// Otherwise control flow starts with setup() again
deepSleepUntilNextTemperatureMeasurement();
} else {
delay(100);
}
}

View File

@ -19,13 +19,14 @@ RTC_DATA_ATTR bool isFirstRunAfterPowerOn = true;
// Keeps the last valid temperatures for each sensor
RTC_DATA_ATTR Temperature lastTemperatures[temperatureSensorCount];
RTC_DATA_ATTR uint32_t lastValidTemperatureTime[temperatureSensorCount];
bool didSetupEEPROM = false;
// On first boot, this is set to true; Afterwards it's remembered to be false
RTC_DATA_ATTR bool eepromIsConsideredEmpty = true;
constexpr uint16_t eepromOffset = 2; // Size of uint16
constexpr uint16_t eepromOffset = sizeof(uint16_t);
constexpr uint16_t eepromDataSize = eepromSize - eepromOffset;
void setupEEPROMIfNeeded() {
@ -46,6 +47,7 @@ void resetLastMeasurements() {
for (uint8_t index = 0; index < temperatureSensorCount; index += 1) {
lastTemperatures[index].status == TemperatureStatus::sensorNotFound;
lastTemperatures[index].value = 0;
lastValidTemperatureTime[index] = 0;
}
}
@ -146,6 +148,7 @@ void saveTemperatures(Temperature* temperatures) {
if (temperatures[sensorIndex].status == TemperatureStatus::temperatureIsValid) {
// Only update if temperature is valid
lastTemperatures[sensorIndex] = temperatures[sensorIndex];
lastValidTemperatureTime[sensorIndex] = time(NULL);
}
}
} else {
@ -169,6 +172,7 @@ void saveTemperatures(Temperature* temperatures) {
if (temperatures[index].status == TemperatureStatus::temperatureIsValid) {
// Only update if temperature is valid
lastTemperatures[index] = temperatures[index];
lastValidTemperatureTime[index] = time(NULL);
}
}
// Ensure storage with uneven number of sensors
@ -196,6 +200,10 @@ uint8_t getLastTemperature(uint8_t sensorIndex) {
return byteForAbsoluteTemperature(lastTemperatures[sensorIndex].value);
}
uint16_t getTimeSinceValidTemperature(uint8_t sensorIndex) {
return time(NULL) - lastValidTemperatureTime[sensorIndex];
}
uint16_t getRecordedBytesAtOffset(uint8_t* buffer, uint16_t offset, uint16_t count) {
// TODO: Check limits
uint16_t eepromByteCount = getNumberOfBytesStoredInEEPROM();
@ -221,5 +229,4 @@ void discardAllRecordedBytes() {
dataIndex = 0;
numberOfMeasurements = 0;
resetLastMeasurements();
}