232 lines
5.4 KiB
C++
232 lines
5.4 KiB
C++
#include <Arduino.h>
|
|
#include <OneWire.h>
|
|
#include <DallasTemperature.h>
|
|
|
|
#include "config.h"
|
|
#include "sensors.h"
|
|
#include "app_config.h"
|
|
|
|
SensorData sensors;
|
|
|
|
OneWire oneWire(ONEWIRE_PIN);
|
|
DallasTemperature ds18b20(&oneWire);
|
|
|
|
DeviceAddress sensorAddresses[MAX_TEMP_SENSORS];
|
|
String sensorAddressStrings[MAX_TEMP_SENSORS];
|
|
int sensorCount = 0;
|
|
|
|
float cToF(float c) {
|
|
return (c * 9.0 / 5.0) + 32.0;
|
|
}
|
|
|
|
bool validTempC(float tempC) {
|
|
return tempC != DEVICE_DISCONNECTED_C && tempC > -55 && tempC < 125;
|
|
}
|
|
|
|
String addressToString(DeviceAddress address) {
|
|
String output = "";
|
|
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if (address[i] < 16) output += "0";
|
|
output += String(address[i], HEX);
|
|
if (i < 7) output += ":";
|
|
}
|
|
|
|
output.toUpperCase();
|
|
return output;
|
|
}
|
|
|
|
void printAddress(DeviceAddress address) {
|
|
Serial.print(addressToString(address));
|
|
}
|
|
|
|
bool addressMatches(DeviceAddress address, const String& expected) {
|
|
if (expected.length() == 0) {
|
|
return false;
|
|
}
|
|
|
|
String actual = addressToString(address);
|
|
String normalizedExpected = expected;
|
|
normalizedExpected.toUpperCase();
|
|
|
|
return actual == normalizedExpected;
|
|
}
|
|
|
|
bool isTempAddressAssigned(const String& address) {
|
|
if (address.length() == 0) {
|
|
return false;
|
|
}
|
|
|
|
String normalizedAddress = address;
|
|
normalizedAddress.toUpperCase();
|
|
|
|
for (int i = 0; i < MAX_TEMP_SENSORS; i++) {
|
|
String assigned = appConfig.tempSensors[i].address;
|
|
assigned.toUpperCase();
|
|
|
|
if (assigned == normalizedAddress) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void clearSensorRuntimeData() {
|
|
for (int i = 0; i < MAX_TEMP_SENSORS; i++) {
|
|
sensors.tempsF[i] = -127.0;
|
|
sensors.online[i] = false;
|
|
}
|
|
}
|
|
|
|
int scanTempSensors() {
|
|
ds18b20.begin();
|
|
|
|
sensorCount = ds18b20.getDeviceCount();
|
|
|
|
if (sensorCount > MAX_TEMP_SENSORS) {
|
|
sensorCount = MAX_TEMP_SENSORS;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_TEMP_SENSORS; i++) {
|
|
sensorAddressStrings[i] = "";
|
|
}
|
|
|
|
int availableCount = 0;
|
|
|
|
for (int i = 0; i < sensorCount; i++) {
|
|
DeviceAddress address;
|
|
|
|
if (!ds18b20.getAddress(address, i)) {
|
|
continue;
|
|
}
|
|
|
|
String addressString = addressToString(address);
|
|
|
|
if (isTempAddressAssigned(addressString)) {
|
|
continue;
|
|
}
|
|
|
|
memcpy(sensorAddresses[availableCount], address, 8);
|
|
sensorAddressStrings[availableCount] = addressString;
|
|
availableCount++;
|
|
}
|
|
|
|
sensorCount = availableCount;
|
|
|
|
return sensorCount;
|
|
}
|
|
|
|
int getTempScanResultCount() {
|
|
return sensorCount;
|
|
}
|
|
|
|
String getTempScanResultAddress(int index) {
|
|
if (index < 0 || index >= sensorCount) {
|
|
return "";
|
|
}
|
|
|
|
return sensorAddressStrings[index];
|
|
}
|
|
|
|
void printSensorAddresses() {
|
|
Serial.println("DS18B20 Sensors Found:");
|
|
|
|
for (int i = 0; i < sensorCount; i++) {
|
|
Serial.print(i + 1);
|
|
Serial.print(") ");
|
|
Serial.println(sensorAddressStrings[i]);
|
|
}
|
|
|
|
if (sensorCount == 0) {
|
|
Serial.println("No DS18B20 sensors found.");
|
|
} else {
|
|
Serial.println("Use: assign temp <slot> <number>");
|
|
}
|
|
}
|
|
|
|
void initSensors() {
|
|
clearSensorRuntimeData();
|
|
scanTempSensors();
|
|
printSensorAddresses();
|
|
}
|
|
|
|
void updateSensors() {
|
|
clearSensorRuntimeData();
|
|
|
|
ds18b20.requestTemperatures();
|
|
|
|
for (int configIndex = 0; configIndex < MAX_TEMP_SENSORS; configIndex++) {
|
|
if (!appConfig.tempSensors[configIndex].enabled) {
|
|
continue;
|
|
}
|
|
|
|
String configuredAddress = appConfig.tempSensors[configIndex].address;
|
|
|
|
if (configuredAddress.length() == 0) {
|
|
sensors.tempsF[configIndex] = -127.0;
|
|
sensors.online[configIndex] = false;
|
|
continue;
|
|
}
|
|
|
|
for (int physicalIndex = 0; physicalIndex < sensorCount; physicalIndex++) {
|
|
if (!addressMatches(sensorAddresses[physicalIndex], configuredAddress)) {
|
|
continue;
|
|
}
|
|
|
|
float tempC = ds18b20.getTempC(sensorAddresses[physicalIndex]);
|
|
|
|
if (validTempC(tempC)) {
|
|
sensors.tempsF[configIndex] = cToF(tempC);
|
|
sensors.online[configIndex] = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool assignTempSensorByIndex(int configIndex, int scanIndex) {
|
|
if (configIndex < 0 || configIndex >= MAX_TEMP_SENSORS) {
|
|
return false;
|
|
}
|
|
|
|
if (scanIndex < 0 || scanIndex >= sensorCount) {
|
|
return false;
|
|
}
|
|
|
|
String selectedAddress = sensorAddressStrings[scanIndex];
|
|
|
|
for (int i = 0; i < MAX_TEMP_SENSORS; i++) {
|
|
if (i == configIndex) {
|
|
continue;
|
|
}
|
|
|
|
if (appConfig.tempSensors[i].address == selectedAddress) {
|
|
appConfig.tempSensors[i].address = "";
|
|
appConfig.tempSensors[i].enabled = false;
|
|
sensors.tempsF[i] = -127.0;
|
|
sensors.online[i] = false;
|
|
}
|
|
}
|
|
|
|
appConfig.tempSensors[configIndex].address = selectedAddress;
|
|
appConfig.tempSensors[configIndex].enabled = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool clearTempSensor(int configIndex) {
|
|
if (configIndex < 0 || configIndex >= MAX_TEMP_SENSORS) {
|
|
return false;
|
|
}
|
|
|
|
appConfig.tempSensors[configIndex].address = "";
|
|
appConfig.tempSensors[configIndex].enabled = false;
|
|
appConfig.tempSensors[configIndex].weather = false;
|
|
sensors.tempsF[configIndex] = -127.0;
|
|
sensors.online[configIndex] = false;
|
|
|
|
return true;
|
|
}
|