Simplified data storage without eeprom, include timestamps
This commit is contained in:
parent
6bcc22c045
commit
7c2162a5bf
@ -4,9 +4,6 @@
|
||||
|
||||
void bluetoothConfigure();
|
||||
|
||||
bool bluetoothIsConnected();
|
||||
void bluetoothStop();
|
||||
|
||||
// In main.cpp
|
||||
uint32_t secondsUntilNextTemperatureMeasurement();
|
||||
|
||||
uint8_t getWakeupCause();
|
||||
bool bluetoothIsConnected();
|
90
include/eepromInterface.h
Normal file
90
include/eepromInterface.h
Normal file
@ -0,0 +1,90 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct DeviceInfo {
|
||||
|
||||
// The index where the measurement data starts in the eeprom storage
|
||||
uint16_t startIndex;
|
||||
|
||||
// The time when the device was powered on (seconds since 1970)
|
||||
uint32_t deviceStartTime;
|
||||
};
|
||||
|
||||
struct Measurement {
|
||||
|
||||
uint16_t measurementIntervalsSinceDeviceStart;
|
||||
|
||||
uint8_t temperature0;
|
||||
|
||||
uint8_t temperature1;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
constexpr size_t eepromTotalSize = 13350;
|
||||
constexpr uint16_t maxiumDeviceInfoCount = 10;
|
||||
constexpr uint16_t dataStorageStartIndex = sizeof(DeviceInfo) * maxiumDeviceInfoCount;
|
||||
constexpr uint16_t sizeOfMeasurement = sizeof(Measurement);
|
||||
|
||||
class EEPROMInterface {
|
||||
|
||||
public:
|
||||
|
||||
bool isInitialized;
|
||||
|
||||
/**
|
||||
* @brief Initialize the storage
|
||||
*
|
||||
*/
|
||||
EEPROMInterface();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
uint8_t startNewDeviceSession();
|
||||
|
||||
/**
|
||||
* @brief Remove all stored data
|
||||
*
|
||||
* @return true The data was deleted
|
||||
* @return false There was an error deleting the data
|
||||
*/
|
||||
bool clearAllData();
|
||||
|
||||
bool writeData(uint8_t* data, uint16_t count);
|
||||
|
||||
/**
|
||||
* @brief Free space in the buffer
|
||||
*
|
||||
* @param buffer
|
||||
* @param count
|
||||
* @return uint16_t The number
|
||||
*/
|
||||
uint16_t readData(uint8_t* buffer, uint16_t count);
|
||||
|
||||
uint16_t getStoredByteCount();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief The index into the buffer where the next byte should be written
|
||||
*
|
||||
*/
|
||||
uint16_t writeIndex;
|
||||
|
||||
/**
|
||||
* @brief The index into the buffer where the first byte is stored
|
||||
*
|
||||
*/
|
||||
uint16_t readIndex;
|
||||
|
||||
/**
|
||||
* @brief Find the write index, the first zero byte after a non-zero byte
|
||||
*
|
||||
* @return uint16_t The write index
|
||||
*/
|
||||
uint16_t findEndIndex();
|
||||
|
||||
uint16_t findStartIndex();
|
||||
};
|
7
include/main.h
Normal file
7
include/main.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t secondsUntilNextTemperatureMeasurement();
|
||||
uint8_t getWakeupCause();
|
||||
uint32_t getUniqueID();
|
@ -6,33 +6,17 @@
|
||||
|
||||
constexpr uint8_t temperatureSensorCount = 2;
|
||||
|
||||
constexpr size_t storageSize = 80000;
|
||||
constexpr uint16_t storageIntervalInSeconds = 15;
|
||||
constexpr size_t maximumStorageDurationInHours = (storageSize / TEMPERATURE_SENSOR_MAX_COUNT) * storageIntervalInSeconds / 3600;
|
||||
|
||||
// Max size: 7664
|
||||
constexpr size_t maxRtcStorageSize = 7664;
|
||||
constexpr size_t rtcStorageSize = 7550;
|
||||
constexpr size_t rtcStorageSize = 7580;
|
||||
|
||||
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;
|
||||
constexpr long maximumTemperature = temperatureShiftForStorage + 255 * 500;
|
||||
|
||||
constexpr uint8_t temperatureMaximumValue = 255;
|
||||
|
||||
enum class StorageFlags: uint8_t {
|
||||
HasInitializedEEPROM = 1,
|
||||
FailedToInitEEPROM = 2,
|
||||
FailedToWriteEEPROM = 4,
|
||||
RTCStorageOverflow = 5,
|
||||
};
|
||||
|
||||
void storageConfigure(bool isFirstRun);
|
||||
|
||||
/**
|
||||
@ -51,12 +35,14 @@ uint16_t getNumberOfMeasurements();
|
||||
|
||||
uint32_t getTotalNumberOfMeasurements();
|
||||
|
||||
uint32_t getStartTimeOfCurrentRecording();
|
||||
|
||||
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();
|
||||
uint16_t getDataChecksum();
|
||||
|
||||
uint8_t getStorageErrorFlags();
|
||||
void discardAllRecordedBytes();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <string.h>
|
||||
#include <Esp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
@ -10,6 +11,7 @@
|
||||
#include "storage.h"
|
||||
#include "config.h"
|
||||
#include "temperature.h"
|
||||
#include "main.h"
|
||||
|
||||
constexpr size_t bluetoothMaxDataSize = 200;
|
||||
|
||||
@ -29,8 +31,6 @@ uint8_t* bluetoothDataBuffer;
|
||||
uint8_t* bluetoothResponse;
|
||||
size_t bluetoothDataCount = 0;
|
||||
|
||||
RTC_DATA_ATTR uint32_t deviceStartTime = 0;
|
||||
|
||||
void bluetoothStartAdvertising();
|
||||
void bluetoothDidReceiveData(uint8_t* buffer, uint16_t count);
|
||||
|
||||
@ -87,7 +87,6 @@ void bluetoothConfigure() {
|
||||
BLEDevice::init(deviceName);
|
||||
server = BLEDevice::createServer();
|
||||
server->setCallbacks(&bluetooth);
|
||||
|
||||
// Register message service that can receive messages and reply with a static message.
|
||||
BLEService *service = server->createService(serviceUUID);
|
||||
uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE;
|
||||
@ -114,6 +113,11 @@ void bluetoothConfigure() {
|
||||
bluetoothStartAdvertising();
|
||||
}
|
||||
|
||||
void bluetoothStop() {
|
||||
BLEDevice::deinit();
|
||||
esp_bt_controller_disable();
|
||||
}
|
||||
|
||||
void bluetoothStartAdvertising() {
|
||||
// Advertise services
|
||||
BLEAdvertising *advertisement = server->getAdvertising();
|
||||
@ -171,17 +175,6 @@ enum class BluetoothRequest: uint8_t {
|
||||
* This may happen when a new temperature recording is performed in between calls
|
||||
*/
|
||||
clearRecordingBuffer = 2,
|
||||
|
||||
/**
|
||||
* @brief Set the absolute start time of the device
|
||||
*
|
||||
* Request:
|
||||
* - Bytes 1-4: Number of seconds since 1970 (uint32_t)
|
||||
*
|
||||
* Response:
|
||||
* - BluetoothResponse::success
|
||||
*/
|
||||
setDeviceStartTime = 3,
|
||||
};
|
||||
|
||||
enum class BluetoothResponse: uint8_t {
|
||||
@ -237,6 +230,11 @@ void fillInfo() {
|
||||
uint16_t value;
|
||||
uint32_t value32;
|
||||
|
||||
// The unique ID generated on power-on
|
||||
value32 = getUniqueID();
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value32, sizeof(uint32_t));
|
||||
bluetoothDataCount += sizeof(uint32_t);
|
||||
|
||||
// the number of bytes as a uint16_t (2 bytes)
|
||||
value = getTotalNumberOfStoredBytes();
|
||||
memcpy(bluetoothDataBuffer, &value, sizeof(uint16_t));
|
||||
@ -268,7 +266,7 @@ void fillInfo() {
|
||||
bluetoothDataCount += sizeof(uint16_t);
|
||||
|
||||
// Total storage size of device
|
||||
value = totalStorageSize;
|
||||
value = rtcStorageSize;
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
|
||||
bluetoothDataCount += sizeof(uint16_t);
|
||||
|
||||
@ -277,10 +275,20 @@ void fillInfo() {
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value32, sizeof(uint32_t));
|
||||
bluetoothDataCount += sizeof(uint32_t);
|
||||
|
||||
// Configured device start time
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &deviceStartTime, sizeof(uint32_t));
|
||||
// Start time of current recording
|
||||
value32 = getStartTimeOfCurrentRecording();
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value32, sizeof(uint32_t));
|
||||
bluetoothDataCount += sizeof(uint32_t);
|
||||
|
||||
// Checksum for all data
|
||||
value = getDataChecksum();
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
|
||||
bluetoothDataCount += sizeof(uint16_t);
|
||||
|
||||
// The wakeup cause for the current run
|
||||
bluetoothDataBuffer[bluetoothDataCount] = getWakeupCause();
|
||||
bluetoothDataCount += sizeof(uint8_t);
|
||||
|
||||
// Sensor 0
|
||||
|
||||
// Temperature sensor addresses
|
||||
@ -309,9 +317,6 @@ void fillInfo() {
|
||||
memcpy(bluetoothDataBuffer + bluetoothDataCount, &value, sizeof(uint16_t));
|
||||
bluetoothDataCount += sizeof(uint16_t);
|
||||
|
||||
bluetoothDataBuffer[bluetoothDataCount] = getWakeupCause();
|
||||
bluetoothDataCount += sizeof(uint8_t);
|
||||
|
||||
setResponse(BluetoothResponse::success);
|
||||
}
|
||||
|
||||
@ -350,17 +355,6 @@ void clearRecordingBuffer(uint8_t* buffer, uint16_t count) {
|
||||
setResponseWithoutData(BluetoothResponse::success);
|
||||
}
|
||||
|
||||
void setDeviceStartTime(uint8_t* buffer, uint16_t count) {
|
||||
if (count != sizeof(uint32_t)) {
|
||||
setResponseWithoutData(BluetoothResponse::invalidCommand);
|
||||
return;
|
||||
}
|
||||
memcpy(&deviceStartTime, buffer, sizeof(uint32_t));
|
||||
Serial.print("Device start time: ");
|
||||
Serial.println(deviceStartTime);
|
||||
setResponseWithoutData(BluetoothResponse::success);
|
||||
}
|
||||
|
||||
void bluetoothDidReceiveData(uint8_t* buffer, uint16_t count) {
|
||||
if (count < 1) {
|
||||
setResponseWithoutData(BluetoothResponse::invalidCommand);
|
||||
@ -384,10 +378,6 @@ void bluetoothDidReceiveData(uint8_t* buffer, uint16_t count) {
|
||||
getRecordingData(payload, payloadSize);
|
||||
break;
|
||||
|
||||
case BluetoothRequest::setDeviceStartTime:
|
||||
setDeviceStartTime(payload, payloadSize);
|
||||
break;
|
||||
|
||||
default:
|
||||
setResponseWithoutData(BluetoothResponse::unknownCommand);
|
||||
break;
|
||||
|
6
src/eepromInterface.cpp
Normal file
6
src/eepromInterface.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "eepromInterface.h"
|
||||
#include <EEPROM.h>
|
||||
|
||||
EEPROMInterface::EEPROMInterface() {
|
||||
isInitialized = EEPROM.begin(eepromTotalSize);
|
||||
}
|
19
src/main.cpp
19
src/main.cpp
@ -2,6 +2,7 @@
|
||||
#include <esp_wifi.h>
|
||||
#include <driver/rtc_io.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "bluetooth.h"
|
||||
#include "storage.h"
|
||||
@ -16,6 +17,9 @@ RTC_DATA_ATTR uint32_t nextTimeToMeasureTemperatureSeconds = 0;
|
||||
|
||||
RTC_DATA_ATTR bool isFirstStart = true;
|
||||
|
||||
// The unique ID generated whenever the device is powered on
|
||||
RTC_DATA_ATTR uint32_t uniqueID;
|
||||
|
||||
// Indicate the time until the device should stay awake
|
||||
// Updated when button is pressed
|
||||
uint32_t sleepStartAfterButtonPressOrConnection = 0;
|
||||
@ -26,6 +30,10 @@ uint8_t getWakeupCause() {
|
||||
return wakeupCauseByte;
|
||||
}
|
||||
|
||||
uint32_t getUniqueID() {
|
||||
return uniqueID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if enough time has passed for the next temperature measurement
|
||||
*
|
||||
@ -54,7 +62,8 @@ uint32_t secondsUntilNextTemperatureMeasurement() {
|
||||
if (currentTime >= nextTimeToMeasureTemperatureSeconds) {
|
||||
return 0;
|
||||
}
|
||||
return nextTimeToMeasureTemperatureSeconds - currentTime;
|
||||
uint32_t seconds = nextTimeToMeasureTemperatureSeconds - currentTime;
|
||||
return min(seconds, temperatureMeasurementIntervalSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,6 +83,7 @@ void deepSleepUntilNextTemperatureMeasurement() {
|
||||
Serial.print("Sleeping for ");
|
||||
Serial.print(seconds);
|
||||
Serial.println(" seconds");
|
||||
bluetoothStop();
|
||||
esp_deep_sleep(seconds * 1000000);
|
||||
}
|
||||
|
||||
@ -125,7 +135,12 @@ void enableLED() {
|
||||
|
||||
void setup() {
|
||||
// No need for serial output in production
|
||||
Serial.begin(serialBaudRate);
|
||||
Serial.begin(serialBaudRate);
|
||||
|
||||
if (isFirstStart) {
|
||||
// Generate unique ID on device start
|
||||
uniqueID = random();
|
||||
}
|
||||
|
||||
// LED useless inside case
|
||||
// enableLED();
|
||||
|
221
src/storage.cpp
221
src/storage.cpp
@ -3,63 +3,21 @@
|
||||
#include <EEPROM.h>
|
||||
#include <esp_attr.h>
|
||||
|
||||
constexpr uint8_t absoluteTemperatureIndicator = 0xFF;
|
||||
|
||||
RTC_DATA_ATTR uint8_t storageFlags = 0;
|
||||
|
||||
// Storage for temperature measurements in RTC memory that survives deep sleep
|
||||
RTC_DATA_ATTR uint8_t data[rtcStorageSize];
|
||||
RTC_DATA_ATTR uint16_t dataIndex = 0;
|
||||
RTC_DATA_ATTR uint16_t numberOfMeasurements = 0;
|
||||
RTC_DATA_ATTR uint32_t numberOfDiscardedMeasurements = 0;
|
||||
RTC_DATA_ATTR uint16_t dataIndex = 0; // Index of next byte / total byte count
|
||||
RTC_DATA_ATTR uint16_t rtcDataSum = 0; // Checksum for the data storage
|
||||
RTC_DATA_ATTR uint16_t numberOfMeasurements = 0; // Current number of measurements (dataIndex / 4)
|
||||
RTC_DATA_ATTR uint32_t numberOfDiscardedMeasurements = 0; // Previous measurements already deleted
|
||||
|
||||
// The index into EEPROM storage where the next data should be written
|
||||
RTC_DATA_ATTR uint32_t eepromIndex = 0;
|
||||
RTC_DATA_ATTR bool isFirstRunAfterPowerOn = true;
|
||||
|
||||
constexpr uint16_t eepromOffset = sizeof(uint16_t);
|
||||
constexpr uint16_t eepromDataSize = eepromSize - eepromOffset;
|
||||
// The time (in seconds since device start) when the current recording started
|
||||
RTC_DATA_ATTR uint32_t startTimeOfCurrentRecording = 0;
|
||||
|
||||
// Keeps the last valid temperatures for each sensor
|
||||
RTC_DATA_ATTR Temperature lastTemperatures[temperatureSensorCount];
|
||||
RTC_DATA_ATTR uint32_t lastValidTemperatureTime[temperatureSensorCount];
|
||||
RTC_DATA_ATTR uint8_t lastMeasurements[temperatureSensorCount] = {0, 0};
|
||||
|
||||
void setStorageFlag(StorageFlags flag) {
|
||||
storageFlags |= static_cast<uint8_t>(flag);
|
||||
}
|
||||
|
||||
void clearStorageFlag(StorageFlags flag) {
|
||||
storageFlags &= ~static_cast<uint8_t>(flag);
|
||||
}
|
||||
|
||||
bool hasStorageFlag(StorageFlags flag) {
|
||||
return storageFlags & static_cast<uint8_t>(flag);
|
||||
}
|
||||
|
||||
bool hasInitializedEEPROM() {
|
||||
return hasStorageFlag(StorageFlags::HasInitializedEEPROM);
|
||||
}
|
||||
|
||||
void didInitializeEEPROM() {
|
||||
setStorageFlag(StorageFlags::HasInitializedEEPROM);
|
||||
}
|
||||
|
||||
void setupEEPROMIfNeeded() {
|
||||
if (hasInitializedEEPROM()) {
|
||||
return;
|
||||
}
|
||||
bool success = EEPROM.begin(eepromSize);
|
||||
if (!success) {
|
||||
Serial.println("Failed to set up EEPROM");
|
||||
setStorageFlag(StorageFlags::FailedToInitEEPROM);
|
||||
}
|
||||
Serial.print("EEPROM size: ");
|
||||
Serial.println(eepromSize);
|
||||
clearStorageFlag(StorageFlags::FailedToInitEEPROM);
|
||||
setStorageFlag(StorageFlags::HasInitializedEEPROM);
|
||||
}
|
||||
|
||||
void resetLastMeasurements() {
|
||||
for (uint8_t index = 0; index < temperatureSensorCount; index += 1) {
|
||||
lastTemperatures[index].status == TemperatureStatus::sensorNotFound;
|
||||
@ -74,41 +32,6 @@ void storageConfigure(bool isFirstRun) {
|
||||
// Ensure that first values are stored
|
||||
resetLastMeasurements();
|
||||
}
|
||||
// Initialize EEPROM on every wake
|
||||
// setupEEPROMIfNeeded();
|
||||
//setStorageFlag(StorageFlags::HasInitializedEEPROM);
|
||||
}
|
||||
|
||||
void moveDataToEEPROMIfNeeded() {
|
||||
if (dataIndex < rtcStorageSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
setupEEPROMIfNeeded();
|
||||
if (!hasInitializedEEPROM()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write until EEPROM is full
|
||||
uint16_t bytesRemaining = eepromDataSize - eepromIndex;
|
||||
uint16_t bytesToWrite = min(dataIndex, bytesRemaining);
|
||||
EEPROM.writeBytes(eepromIndex, data, bytesToWrite); // TODO: Check that result == bytesToWrite
|
||||
EEPROM.commit();
|
||||
|
||||
// Move remaining data to front of array (if any)
|
||||
uint16_t bytesToKeep = dataIndex - bytesToWrite;
|
||||
memmove(data, data + bytesToWrite, bytesToKeep);
|
||||
dataIndex -= bytesToWrite;
|
||||
}
|
||||
|
||||
void saveByteAtCurrentIndex(uint8_t byte) {
|
||||
if (dataIndex >= rtcStorageSize) {
|
||||
setStorageFlag(StorageFlags::RTCStorageOverflow);
|
||||
return;
|
||||
}
|
||||
data[dataIndex] = byte;
|
||||
dataIndex += 1;
|
||||
//moveDataToEEPROMIfNeeded();
|
||||
}
|
||||
|
||||
uint8_t byteForAbsoluteTemperature(Temperature* temp) {
|
||||
@ -139,79 +62,40 @@ uint8_t byteForAbsoluteTemperature(Temperature* temp) {
|
||||
return converted;
|
||||
}
|
||||
|
||||
bool needsAbsoluteTemperatureRecording(Temperature* temperatures) {
|
||||
if (numberOfMeasurements == 0) {
|
||||
return true;
|
||||
}
|
||||
for (uint8_t index = 0; index < temperatureSensorCount; index += 1) {
|
||||
if (temperatures[index].status != TemperatureStatus::temperatureIsValid) {
|
||||
// Error value can be encoded as differential (0x00)
|
||||
continue;
|
||||
}
|
||||
// Note: If previously only errors, then last value is 0. This also work for differential temperatures
|
||||
long diff = (lastTemperatures[index].value - temperatures[index].value) / 500 + 8;
|
||||
if (diff < 1 || diff > 15) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void saveTemperatures(Temperature* temperatures) {
|
||||
if (needsAbsoluteTemperatureRecording(temperatures)) {
|
||||
// Write absolute temperatures
|
||||
saveByteAtCurrentIndex(absoluteTemperatureIndicator);
|
||||
for (uint8_t sensorIndex = 0; sensorIndex < temperatureSensorCount; sensorIndex += 1) {
|
||||
Temperature* temp = &temperatures[sensorIndex];
|
||||
uint8_t byte = byteForAbsoluteTemperature(temp);
|
||||
saveByteAtCurrentIndex(byte);
|
||||
lastMeasurements[sensorIndex] = byte;
|
||||
if (temp->status == TemperatureStatus::temperatureIsValid) {
|
||||
// Only update if temperature is valid
|
||||
lastTemperatures[sensorIndex] = *temp;
|
||||
lastValidTemperatureTime[sensorIndex] = time(NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Calculate temperature differences
|
||||
uint8_t valueToStore = 0;
|
||||
for (uint8_t index = 0; index < temperatureSensorCount; index += 1) {
|
||||
Temperature* temp = &temperatures[index];
|
||||
uint8_t diff = 0; // Indicate sensor error
|
||||
if (temp->status == TemperatureStatus::temperatureIsValid) {
|
||||
diff = (lastTemperatures[index].value - temp->value) / 500 + 8;
|
||||
}
|
||||
if (index % 2) {
|
||||
// Store second bits
|
||||
valueToStore |= diff; // Valid range already ensured
|
||||
saveByteAtCurrentIndex(valueToStore);
|
||||
valueToStore = 0;
|
||||
} else {
|
||||
// Store in first four bits
|
||||
valueToStore = (diff << 4);
|
||||
}
|
||||
lastMeasurements[index] = byteForAbsoluteTemperature(temp);
|
||||
if (numberOfMeasurements == 0) {
|
||||
// Adjust start time if new measurement is begun
|
||||
startTimeOfCurrentRecording = time(NULL);
|
||||
}
|
||||
if (dataIndex + 4 >= rtcStorageSize) {
|
||||
// Don't add any more measurements if storage is full
|
||||
return;
|
||||
}
|
||||
// First: Write timestamp
|
||||
// Timestamp is number of measurement intervals since start of recording
|
||||
uint16_t timestamp = (time(NULL) - startTimeOfCurrentRecording) / 60;
|
||||
memcpy(data + dataIndex, ×tamp, sizeof(uint16_t));
|
||||
rtcDataSum += data[dataIndex] + data[dataIndex+1]; // Update checksum
|
||||
dataIndex += sizeof(uint16_t);
|
||||
|
||||
if (temp->status == TemperatureStatus::temperatureIsValid) {
|
||||
// Only update if temperature is valid
|
||||
lastTemperatures[index].status = TemperatureStatus::temperatureIsValid;
|
||||
lastTemperatures[index].value = temp->value;
|
||||
lastValidTemperatureTime[index] = time(NULL);
|
||||
} else if (lastTemperatures[index].status != TemperatureStatus::temperatureIsValid) {
|
||||
lastTemperatures[index].value = 0;
|
||||
lastValidTemperatureTime[index] = 0;
|
||||
}
|
||||
}
|
||||
// Ensure storage with uneven number of sensors
|
||||
if (temperatureSensorCount % 2) {
|
||||
saveByteAtCurrentIndex(valueToStore);
|
||||
for (uint8_t sensorIndex = 0; sensorIndex < temperatureSensorCount; sensorIndex += 1) {
|
||||
Temperature* temp = &temperatures[sensorIndex];
|
||||
uint8_t byte = byteForAbsoluteTemperature(temp);
|
||||
data[dataIndex] = byte;
|
||||
dataIndex += 1;
|
||||
rtcDataSum += byte; // Update checksum
|
||||
lastMeasurements[sensorIndex] = byte;
|
||||
if (temp->status == TemperatureStatus::temperatureIsValid) {
|
||||
// Only update if temperature is valid
|
||||
lastTemperatures[sensorIndex] = *temp;
|
||||
lastValidTemperatureTime[sensorIndex] = time(NULL);
|
||||
}
|
||||
}
|
||||
numberOfMeasurements += 1;
|
||||
}
|
||||
|
||||
uint16_t getTotalNumberOfStoredBytes() {
|
||||
return dataIndex; // + eepromIndex;
|
||||
return dataIndex;
|
||||
}
|
||||
|
||||
uint16_t getNumberOfMeasurements() {
|
||||
@ -222,48 +106,35 @@ uint32_t getTotalNumberOfMeasurements() {
|
||||
return numberOfMeasurements + numberOfDiscardedMeasurements;
|
||||
}
|
||||
|
||||
uint32_t getStartTimeOfCurrentRecording() {
|
||||
return startTimeOfCurrentRecording;
|
||||
}
|
||||
|
||||
uint8_t getLastTemperature(uint8_t sensorIndex) {
|
||||
return lastMeasurements[sensorIndex];
|
||||
}
|
||||
|
||||
uint16_t getTimeSinceValidTemperature(uint8_t sensorIndex) {
|
||||
return time(NULL) - lastValidTemperatureTime[sensorIndex];
|
||||
return min(time(NULL) - lastValidTemperatureTime[sensorIndex], 65535ul);
|
||||
}
|
||||
|
||||
uint16_t getRecordedBytesAtOffset(uint8_t* buffer, uint16_t offset, uint16_t count) {
|
||||
// Copy remaining bytes from RTC memory
|
||||
if (offset >= dataIndex) {
|
||||
return 0;
|
||||
}
|
||||
uint16_t remainingBytes = dataIndex - offset;
|
||||
uint16_t bytesToCopy = min(count, remainingBytes);
|
||||
memcpy(buffer, data + offset, count);
|
||||
memcpy(buffer, data + offset, bytesToCopy);
|
||||
return bytesToCopy;
|
||||
/*
|
||||
// TODO: Check limits
|
||||
uint16_t eepromByteCount = eepromIndex;
|
||||
uint16_t endIndex = offset + count;
|
||||
uint16_t eepromStart = min(offset, eepromByteCount);
|
||||
uint16_t eepromEnd = min(endIndex, eepromByteCount);
|
||||
uint16_t bytesToCopyFromEEPROM = eepromEnd - eepromStart;
|
||||
if (bytesToCopyFromEEPROM > 0) {
|
||||
EEPROM.readBytes(eepromStart, buffer, bytesToCopyFromEEPROM); // TODO: Check bytes read
|
||||
// Reduce offset and count to point to RTC memory
|
||||
offset -= bytesToCopyFromEEPROM;
|
||||
count -= bytesToCopyFromEEPROM;
|
||||
}
|
||||
offset -= eepromByteCount;
|
||||
// Copy remaining bytes from RTC memory
|
||||
uint16_t bytesToCopyFromRTC = min(count, dataIndex);
|
||||
memcpy(buffer + bytesToCopyFromEEPROM, data + offset, bytesToCopyFromRTC);
|
||||
return bytesToCopyFromEEPROM + bytesToCopyFromRTC;
|
||||
*/
|
||||
}
|
||||
|
||||
uint16_t getDataChecksum() {
|
||||
return rtcDataSum;
|
||||
}
|
||||
|
||||
void discardAllRecordedBytes() {
|
||||
eepromIndex = 0;
|
||||
dataIndex = 0;
|
||||
rtcDataSum = 0;
|
||||
numberOfDiscardedMeasurements += numberOfMeasurements;
|
||||
numberOfMeasurements = 0;
|
||||
}
|
||||
|
||||
uint8_t getStorageErrorFlags() {
|
||||
return storageFlags;
|
||||
}
|
Loading…
Reference in New Issue
Block a user