This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
window.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
// URL of your API
|
||||||
|
const apiUrl = '/sensor_data';
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
// Fetching data from the API
|
||||||
|
fetch(apiUrl)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('voltage').textContent = roundToTwo(data.voltage)+ ' V' || 'N/A';
|
||||||
|
document.getElementById('current').textContent = roundToTwo(data.current)+ ' mA' || 'N/A';
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("There was an error fetching data from the API", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData(); // fetch immediately on page load
|
||||||
|
setInterval(fetchData, 5000); // fetch every 5 seconds
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
const apiUrl = '/network_info';
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
fetch(apiUrl)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('wifi_ip').textContent = data.wifi.ip || 'N/A';
|
||||||
|
document.getElementById('wifi_rssi').textContent = data.wifi.rssi || 'N/A';
|
||||||
|
document.getElementById('wifi_link').textContent = data.wifi.link || 'N/A';
|
||||||
|
document.getElementById('wifi_ssid').textContent = data.wifi.ssid || 'N/A';
|
||||||
|
document.getElementById('eth_link').textContent = data.ethernet.link || 'N/A';
|
||||||
|
document.getElementById('eth_ip').textContent = data.ethernet.ip || 'N/A';
|
||||||
|
document.getElementById('eth_speed').textContent = data.ethernet.rssi || 'N/A';
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("There was an error fetching data from the API", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchData(); // fetch immediately on page load
|
||||||
|
setInterval(fetchData, 5000); // fetch every 5 seconds
|
||||||
|
});
|
||||||
|
|
||||||
|
function roundToTwo(num) {
|
||||||
|
return Math.round(num*100)/100;
|
||||||
|
}
|
||||||
@@ -1,14 +1,7 @@
|
|||||||
<!DOCTYPE html>”
|
<!DOCTYPE html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="/chota.css">
|
<link rel="stylesheet" href="/chota.css">
|
||||||
|
|
||||||
<script>
|
|
||||||
if (window.matchMedia &&
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
||||||
document.body.classList.add('dark');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -55,6 +48,11 @@
|
|||||||
<form action="/update_wifi_credentials" method="post">
|
<form action="/update_wifi_credentials" method="post">
|
||||||
<fieldset id="form-settings">
|
<fieldset id="form-settings">
|
||||||
<legend>WiFi Settings</legend>
|
<legend>WiFi Settings</legend>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" id="enable" name="enable" value="true">
|
||||||
|
<label for="enable"> Enable WiFi</label><br>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<label for="ssid">SSID</label>
|
<label for="ssid">SSID</label>
|
||||||
<input id="ssid" name="ssid" type="text">
|
<input id="ssid" name="ssid" type="text">
|
||||||
|
|||||||
102
data/status.html
102
data/status.html
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="/chota.css">
|
<link rel="stylesheet" href="/chota.css">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
|
<script src="/logic.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -34,15 +33,32 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Voltage: </td>
|
<td>Voltage: </td>
|
||||||
<td>12.12V</td>
|
<td id="voltage">WAITING</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current: </td>
|
<td>Current: </td>
|
||||||
<td>10 mA</td>
|
<td id="current">WAITING</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-12 col-6-lg">
|
||||||
|
|
||||||
|
<div class="outer-wrapper">
|
||||||
|
<div class="column-wrapper">
|
||||||
|
<div class="column"></div>
|
||||||
|
</div>
|
||||||
|
<div class="percentage">25%</div>
|
||||||
|
<div class="value">2500 / 10000</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-12 col-3-lg">
|
||||||
<!--ESP Infor card-->
|
<!--ESP Infor card-->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<header>
|
<header>
|
||||||
@@ -69,49 +85,57 @@
|
|||||||
<!--WIFI card-->
|
<!--WIFI card-->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<header>
|
<header>
|
||||||
<h4>Connection Info</h4>
|
<h4>WiFi</h4>
|
||||||
</header>
|
</header>
|
||||||
<table class="tg">
|
<table class="tg">
|
||||||
<thead></thead>
|
<thead></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Type: </td>
|
<td>Link: </td>
|
||||||
<td>WiFi</td>
|
<td id="wifi_link">XX</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>IP: </td>
|
<td>SSID: </td>
|
||||||
<td>127.0.0.1</td>
|
<td id="wifi_ssid">XX</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>RSSI: </td>
|
<td>RSSI: </td>
|
||||||
<td>good</td>
|
<td id="wifi_rssi">XX</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IP: </td>
|
||||||
|
<td id="wifi_ip">127.0.0.1</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--Ethernet card-->
|
||||||
|
<div class="card">
|
||||||
|
<header>
|
||||||
|
<h4>Ethernet</h4>
|
||||||
|
</header>
|
||||||
|
<table class="tg">
|
||||||
|
<thead></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Link: </td>
|
||||||
|
<td id="eth_link">XX</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Speed: </td>
|
||||||
|
<td id="eth_speed">XX</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IP: </td>
|
||||||
|
<td id="eth_ip">xxx</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-7-lg">
|
|
||||||
|
|
||||||
<canvas id="myChart" style="width:100%;max-width:700px"></canvas>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-2-lg">
|
|
||||||
|
|
||||||
<div class="outer-wrapper">
|
|
||||||
<div class="column-wrapper">
|
|
||||||
<div class="column"></div>
|
|
||||||
</div>
|
|
||||||
<div class="percentage">25%</div>
|
|
||||||
<div class="value">2500 / 10000</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -156,23 +180,3 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
|
||||||
var xValues = [1,60,70,80,90,100,110,120,130,140,150];
|
|
||||||
var yValues = [7,8,8,9,9,9,10,11,14,14,15];
|
|
||||||
|
|
||||||
new Chart("myChart", {
|
|
||||||
type: "line",
|
|
||||||
data: {
|
|
||||||
labels: xValues,
|
|
||||||
datasets: [{
|
|
||||||
backgroundColor: "rgba(0,0,0,1.0)",
|
|
||||||
borderColor: "rgba(0,0,0,0.1)",
|
|
||||||
data: yValues
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options:{}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
11
readme.md
Normal file
11
readme.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# TODO
|
||||||
|
|
||||||
|
- Water height calculation
|
||||||
|
- Water height config
|
||||||
|
- Return wather height in API
|
||||||
|
- Return Telementry in API
|
||||||
|
|
||||||
|
|
||||||
|
Config fields:
|
||||||
|
- ssid
|
||||||
|
- wifi_password
|
||||||
380
src/main.cpp
380
src/main.cpp
@@ -27,6 +27,8 @@
|
|||||||
#define ssid_key "ssid"
|
#define ssid_key "ssid"
|
||||||
#define wifi_password_key "wifi_password"
|
#define wifi_password_key "wifi_password"
|
||||||
|
|
||||||
|
extern "C" int rom_phy_get_vdd33();
|
||||||
|
|
||||||
// Calibration variables
|
// Calibration variables
|
||||||
float zero_value = 0.03; // Measured shunt voltage with nothing connected, used to fix measuring offset
|
float zero_value = 0.03; // Measured shunt voltage with nothing connected, used to fix measuring offset
|
||||||
float max_water_level_cm = 200;
|
float max_water_level_cm = 200;
|
||||||
@@ -38,17 +40,27 @@ bool voltage_low = false;
|
|||||||
bool current_high = false;
|
bool current_high = false;
|
||||||
bool current_low = false;
|
bool current_low = false;
|
||||||
|
|
||||||
float rssi;
|
|
||||||
uint32_t ip_address;
|
|
||||||
uint8_t failed_connection_attempts = 0;
|
uint8_t failed_connection_attempts = 0;
|
||||||
|
|
||||||
struct SensorData {
|
struct SensorData
|
||||||
|
{
|
||||||
int percentage;
|
int percentage;
|
||||||
float voltage;
|
float voltage;
|
||||||
float current;
|
float current;
|
||||||
float water_height;
|
float water_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NetworkData
|
||||||
|
{
|
||||||
|
String ip_address;
|
||||||
|
bool link;
|
||||||
|
float rssi;
|
||||||
|
String network_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkData wifi_data;
|
||||||
|
NetworkData ethernet_data;
|
||||||
|
|
||||||
SensorData current_data = SensorData{-1, -1, -1, -1};
|
SensorData current_data = SensorData{-1, -1, -1, -1};
|
||||||
|
|
||||||
int64_t mac_address = ESP.getEfuseMac();
|
int64_t mac_address = ESP.getEfuseMac();
|
||||||
@@ -60,56 +72,74 @@ Preferences prefs;
|
|||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
#define FORMAT_LITTLEFS_IF_FAILED true
|
#define FORMAT_LITTLEFS_IF_FAILED true
|
||||||
|
|
||||||
|
void display_percentage(int percentage)
|
||||||
void display_percentage(int percentage){
|
{
|
||||||
digitalWrite(LED_RED, 0);
|
digitalWrite(LED_RED, 0);
|
||||||
|
|
||||||
if (percentage > 20){
|
if (percentage > 20)
|
||||||
|
{
|
||||||
digitalWrite(LED_1, 1);
|
digitalWrite(LED_1, 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
digitalWrite(LED_1, 0);
|
digitalWrite(LED_1, 0);
|
||||||
}
|
}
|
||||||
if (percentage > 40){
|
if (percentage > 40)
|
||||||
|
{
|
||||||
digitalWrite(LED_2, 1);
|
digitalWrite(LED_2, 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
digitalWrite(LED_2, 0);
|
digitalWrite(LED_2, 0);
|
||||||
}
|
}
|
||||||
if (percentage > 60){
|
if (percentage > 60)
|
||||||
|
{
|
||||||
digitalWrite(LED_3, 1);
|
digitalWrite(LED_3, 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
digitalWrite(LED_3, 0);
|
digitalWrite(LED_3, 0);
|
||||||
}
|
}
|
||||||
if (percentage > 80){
|
if (percentage > 80)
|
||||||
|
{
|
||||||
digitalWrite(LED_4, 1);
|
digitalWrite(LED_4, 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
digitalWrite(LED_4, 0);
|
digitalWrite(LED_4, 0);
|
||||||
}
|
}
|
||||||
if (percentage > 95){
|
if (percentage > 95)
|
||||||
|
{
|
||||||
digitalWrite(LED_5, 1);
|
digitalWrite(LED_5, 1);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
digitalWrite(LED_5, 0);
|
digitalWrite(LED_5, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_error_code(byte err_code) {
|
void display_error_code(byte err_code)
|
||||||
|
{
|
||||||
digitalWrite(LED_RED, 1);
|
digitalWrite(LED_RED, 1);
|
||||||
digitalWrite(LED_1, bitRead(err_code, 0));
|
digitalWrite(LED_1, bitRead(err_code, 0));
|
||||||
digitalWrite(LED_2, bitRead(err_code, 1));
|
digitalWrite(LED_2, bitRead(err_code, 1));
|
||||||
digitalWrite(LED_3, bitRead(err_code, 2));
|
digitalWrite(LED_3, bitRead(err_code, 2));
|
||||||
digitalWrite(LED_4, bitRead(err_code, 3));
|
digitalWrite(LED_4, bitRead(err_code, 3));
|
||||||
digitalWrite(LED_5, bitRead(err_code, 4));
|
digitalWrite(LED_5, bitRead(err_code, 4));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_error(){
|
bool is_error()
|
||||||
|
{
|
||||||
return voltage_high || voltage_low || current_high || current_low;
|
return voltage_high || voltage_low || current_high || current_low;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSuffix(Print* _logOutput, int logLevel) {
|
void printSuffix(Print *_logOutput, int logLevel)
|
||||||
|
{
|
||||||
_logOutput->print(CR);
|
_logOutput->print(CR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_prefix(Print* _logOutput, int logLevel) {
|
void print_prefix(Print *_logOutput, int logLevel)
|
||||||
|
{
|
||||||
_logOutput->print("WATERMETER - C");
|
_logOutput->print("WATERMETER - C");
|
||||||
_logOutput->print(xPortGetCoreID());
|
_logOutput->print(xPortGetCoreID());
|
||||||
_logOutput->print(" - ");
|
_logOutput->print(" - ");
|
||||||
@@ -117,22 +147,34 @@ void print_prefix(Print* _logOutput, int logLevel) {
|
|||||||
_logOutput->print(" - ");
|
_logOutput->print(" - ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_task(void * parameter ){
|
void display_task(void *parameter)
|
||||||
while (true) {
|
{
|
||||||
if (!is_error()){
|
while (true)
|
||||||
|
{
|
||||||
|
if (!is_error())
|
||||||
|
{
|
||||||
// We have no error, refresh status display and wait half a second
|
// We have no error, refresh status display and wait half a second
|
||||||
display_percentage(current_data.percentage);
|
display_percentage(current_data.percentage);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Log.verbose("Error detected");
|
Log.verbose("Error detected");
|
||||||
// We have an error, display error code for 3 seconds and then water level for 3 seconds
|
// We have an error, display error code for 3 seconds and then water level for 3 seconds
|
||||||
if (voltage_low) {
|
if (voltage_low)
|
||||||
|
{
|
||||||
display_error_code(1);
|
display_error_code(1);
|
||||||
} else if (voltage_high){
|
}
|
||||||
|
else if (voltage_high)
|
||||||
|
{
|
||||||
display_error_code(2);
|
display_error_code(2);
|
||||||
} else if (current_low) {
|
}
|
||||||
|
else if (current_low)
|
||||||
|
{
|
||||||
display_error_code(3);
|
display_error_code(3);
|
||||||
} else if (current_high){
|
}
|
||||||
|
else if (current_high)
|
||||||
|
{
|
||||||
display_error_code(4);
|
display_error_code(4);
|
||||||
}
|
}
|
||||||
delay(3000);
|
delay(3000);
|
||||||
@@ -140,43 +182,53 @@ void display_task(void * parameter ){
|
|||||||
delay(3000);
|
delay(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_task(void * parameter ){
|
void wifi_task(void *parameter)
|
||||||
|
{
|
||||||
Log.verbose("Starting WiFi Task");
|
Log.verbose("Starting WiFi Task");
|
||||||
while (true) {
|
while (true)
|
||||||
if (prefs.getString(ssid_key, "") == "" || failed_connection_attempts > 5 ) {
|
{
|
||||||
if (failed_connection_attempts > 5) {
|
if (prefs.getString(ssid_key, "") == "" || failed_connection_attempts > 5)
|
||||||
|
{
|
||||||
|
wifi_data.link = false;
|
||||||
|
if (failed_connection_attempts > 5)
|
||||||
|
{
|
||||||
Log.verbose("Failed to connecto to currently saved SSID, starting SoftAP");
|
Log.verbose("Failed to connecto to currently saved SSID, starting SoftAP");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Log.verbose("No SSID saved, starting SoftAP");
|
Log.verbose("No SSID saved, starting SoftAP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String ap_ssid = "Watermeter-" + String(mac_address);
|
String ap_ssid = "Watermeter-" + String(mac_address);
|
||||||
WiFi.softAP(ap_ssid, "");
|
WiFi.softAP(ap_ssid, "");
|
||||||
|
|
||||||
Log.verbose("[WIFI_TASK] Waiting for SSID now...");
|
Log.verbose("[WIFI_TASK] Waiting for SSID now...");
|
||||||
|
|
||||||
String old_ssid = prefs.getString(ssid_key, "xxx");
|
String old_ssid = prefs.getString(ssid_key, "xxx");
|
||||||
while(prefs.getString(ssid_key, "") == "" || prefs.getString(ssid_key, "") == old_ssid) {
|
while (prefs.getString(ssid_key, "") == "" || prefs.getString(ssid_key, "") == old_ssid)
|
||||||
|
{
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
failed_connection_attempts = 0;
|
failed_connection_attempts = 0;
|
||||||
} else {
|
}
|
||||||
if (WiFi.isConnected() && WiFi.SSID() == prefs.getString(ssid_key, "")) {
|
else
|
||||||
|
{
|
||||||
|
if (WiFi.isConnected() && WiFi.SSID() == prefs.getString(ssid_key, ""))
|
||||||
|
{
|
||||||
failed_connection_attempts = 0;
|
failed_connection_attempts = 0;
|
||||||
rssi = WiFi.RSSI();
|
wifi_data.rssi = WiFi.RSSI();
|
||||||
ip_address = WiFi.localIP();
|
wifi_data.link = true;
|
||||||
|
wifi_data.network_name = WiFi.SSID();
|
||||||
|
wifi_data.ip_address = WiFi.localIP().toString();
|
||||||
|
|
||||||
|
Log.verbose("RSSI: %F, IP Address, %p, SSID: %s", float(WiFi.RSSI()), WiFi.localIP(), prefs.getString(ssid_key, "NOSSID"));
|
||||||
|
|
||||||
Log.verbose("RSSI: %F, IP Address, %p, SSID: %s", rssi, WiFi.localIP(), prefs.getString(ssid_key, "NOSSID"));
|
|
||||||
delay(5000);
|
delay(5000);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Log.verbose("Connecting to %s using password %s", prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
Log.verbose("Connecting to %s using password %s", prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
WiFi.begin(prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||||
@@ -185,17 +237,75 @@ void wifi_task(void * parameter ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ethernet_task(void * parameter ){
|
void ethernet_task(void *parameter)
|
||||||
while (true) {
|
{
|
||||||
|
Log.verbose("Connecting Ethernet");
|
||||||
|
ETH.begin(0, 17, 23, 18);
|
||||||
|
ETH.setHostname("watermeter");
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ethernet_data.link = ETH.linkUp();
|
||||||
|
ethernet_data.rssi = ETH.linkSpeed();
|
||||||
|
ethernet_data.ip_address = ETH.localIP().toString();
|
||||||
|
delay(60 * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collect_internal_telemetry_task(void *parameter)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
float heap_usage = (float(ESP.getFreeHeap()) / float(ESP.getHeapSize())) * 100;
|
||||||
|
uint64_t uptime_seconds = millis() / 1000;
|
||||||
|
|
||||||
|
Log.verbose("Current heap usage: %F", heap_usage);
|
||||||
|
Log.verbose("Current uptime: %d", uptime_seconds);
|
||||||
|
|
||||||
|
delay(60000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void read_sensor_task(void *parameter)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
float bus_voltage = ina_sensor.getBusVoltage();
|
||||||
|
float shunt_voltage = ina_sensor.getShuntVoltage_mV() - zero_value;
|
||||||
|
float shunt_current = shunt_voltage / 4;
|
||||||
|
|
||||||
|
float mA_per_cm = (20 - 4) / (sensor_range * 100);
|
||||||
|
|
||||||
|
float min_water_level_mA_over_zero = (min_water_level_cm * mA_per_cm);
|
||||||
|
float max_water_level_mA_over_zero = (max_water_level_cm * mA_per_cm);
|
||||||
|
|
||||||
|
float min_water_level_mA = 4 + min_water_level_mA_over_zero;
|
||||||
|
float max_water_level_mA = 4 + max_water_level_mA_over_zero;
|
||||||
|
|
||||||
|
// Over Zero always revers to zero water level
|
||||||
|
float shunt_current_over_zero = shunt_current - min_water_level_mA;
|
||||||
|
|
||||||
|
int percentage = round((shunt_current_over_zero / max_water_level_mA_over_zero) * 100);
|
||||||
|
|
||||||
|
current_low = shunt_current < 3.8;
|
||||||
|
current_high = shunt_current > 20.2;
|
||||||
|
voltage_low = bus_voltage < 23;
|
||||||
|
voltage_high = bus_voltage > 25;
|
||||||
|
Log.verbose("Bus current: %F", bus_voltage);
|
||||||
|
Log.verbose("Shunt current: %F", shunt_current);
|
||||||
|
Log.verbose("Shunt voltage: %F", shunt_voltage);
|
||||||
|
Log.verbose("Value percentage: %F", percentage);
|
||||||
|
|
||||||
|
current_data = SensorData{percentage, bus_voltage, shunt_current, shunt_current_over_zero};
|
||||||
|
|
||||||
|
delay(20000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
prefs.begin("waterlevel", false);
|
prefs.begin("waterlevel", false);
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
@@ -203,9 +313,6 @@ void setup() {
|
|||||||
Log.setSuffix(printSuffix);
|
Log.setSuffix(printSuffix);
|
||||||
Log.setPrefix(print_prefix);
|
Log.setPrefix(print_prefix);
|
||||||
|
|
||||||
Log.verbose("Starting WiFi Task now (external)");
|
|
||||||
xTaskCreate(wifi_task, "WiFiTask", 10000, NULL, 1, NULL);
|
|
||||||
|
|
||||||
Log.verbose("Init LEDs");
|
Log.verbose("Init LEDs");
|
||||||
pinMode(LED_1, OUTPUT);
|
pinMode(LED_1, OUTPUT);
|
||||||
pinMode(LED_2, OUTPUT);
|
pinMode(LED_2, OUTPUT);
|
||||||
@@ -229,45 +336,49 @@ void setup() {
|
|||||||
ina_sensor.setAverage(4);
|
ina_sensor.setAverage(4);
|
||||||
display_error_code(21);
|
display_error_code(21);
|
||||||
|
|
||||||
Log.verbose("Connecting Ethernet");
|
|
||||||
ETH.begin(0, 17, 23, 18);
|
|
||||||
Log.verbose(ETH.getHostname());
|
|
||||||
display_error_code(22);
|
display_error_code(22);
|
||||||
|
|
||||||
/////////////////////////////// ROUTES ///////////////////////////////
|
/////////////////////////////// ROUTES ///////////////////////////////
|
||||||
Log.verbose("Route Setup");
|
Log.verbose("Route Setup");
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
request->send(SPIFFS, "/status.html", "text/html", false);
|
{ request->send(SPIFFS, "/status.html", "text/html", false); });
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
request->send(SPIFFS, "/settings.html", "text/html", false);
|
{ request->send(SPIFFS, "/settings.html", "text/html", false); });
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/export", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/export", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
request->send(SPIFFS, "/data_export.html", "text/html", false);
|
{ request->send(SPIFFS, "/data_export.html", "text/html", false); });
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/update_wifi_credentials", HTTP_POST, [](AsyncWebServerRequest *request){
|
server.on("/logic.js", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
|
{ request->send(SPIFFS, "/logic.js", "application/javascript", false); });
|
||||||
|
|
||||||
|
server.on("/update_wifi_credentials", HTTP_POST, [](AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
int params = request->params();
|
int params = request->params();
|
||||||
|
|
||||||
// Log.verbose(request->hasParam(ssid_key));
|
if (request->hasParam(ssid_key, true) && request->hasParam(wifi_password_key, true))
|
||||||
// Log.verbose(request->hasParam(wifi_password_key));
|
{
|
||||||
|
|
||||||
if (request->hasParam(ssid_key, true) && request->hasParam(wifi_password_key, true)){
|
|
||||||
Log.verbose("Updating SSID config");
|
Log.verbose("Updating SSID config");
|
||||||
AsyncWebParameter *ssid_param = request->getParam(ssid_key, true);
|
AsyncWebParameter *ssid_param = request->getParam(ssid_key, true);
|
||||||
AsyncWebParameter *password_param = request->getParam(wifi_password_key, true);
|
AsyncWebParameter *password_param = request->getParam(wifi_password_key, true);
|
||||||
prefs.putString(ssid_key, ssid_param->value().c_str());
|
prefs.putString(ssid_key, ssid_param->value().c_str());
|
||||||
prefs.putString(wifi_password_key, password_param->value().c_str());
|
prefs.putString(wifi_password_key, password_param->value().c_str());
|
||||||
} else {
|
}
|
||||||
for(int i=0;i<params;i++){
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < params; i++)
|
||||||
|
{
|
||||||
AsyncWebParameter *p = request->getParam(i);
|
AsyncWebParameter *p = request->getParam(i);
|
||||||
if(p->isFile()){ //p->isPost() is also true
|
if (p->isFile())
|
||||||
|
{ // p->isPost() is also true
|
||||||
Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
} else if(p->isPost()){
|
}
|
||||||
|
else if (p->isPost())
|
||||||
|
{
|
||||||
Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Log.verbose("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
Log.verbose("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +387,8 @@ void setup() {
|
|||||||
request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating
|
request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/sensor_data", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/sensor_data", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
StaticJsonDocument<128> doc;
|
StaticJsonDocument<128> doc;
|
||||||
doc["percentage"] = current_data.percentage;
|
doc["percentage"] = current_data.percentage;
|
||||||
doc["voltage"] = current_data.voltage;
|
doc["voltage"] = current_data.voltage;
|
||||||
@@ -285,22 +397,36 @@ void setup() {
|
|||||||
|
|
||||||
String output;
|
String output;
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
request->send(200, "application/json", output);
|
request->send(200, "application/json", output); });
|
||||||
});
|
|
||||||
|
|
||||||
server.on("/chota.css", HTTP_GET, [](AsyncWebServerRequest *request){
|
server.on("/network_info", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
request->send(SPIFFS, "/chota.css", "text/css", false);
|
{
|
||||||
});
|
StaticJsonDocument<256> doc;
|
||||||
|
doc["wifi"]["ip"] = wifi_data.ip_address;
|
||||||
|
doc["wifi"]["rssi"] = wifi_data.rssi;
|
||||||
|
doc["wifi"]["link"] = wifi_data.link;
|
||||||
|
doc["wifi"]["ssid"] = wifi_data.network_name;
|
||||||
|
|
||||||
|
doc["ethernet"]["ip"] = ethernet_data.ip_address;
|
||||||
|
doc["ethernet"]["rssi"] = ethernet_data.rssi;
|
||||||
|
doc["ethernet"]["link"] = ethernet_data.link;
|
||||||
|
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(doc, output);
|
||||||
|
request->send(200, "application/json", output); });
|
||||||
|
|
||||||
|
server.on("/chota.css", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
|
{ request->send(SPIFFS, "/chota.css", "text/css", false); });
|
||||||
|
|
||||||
display_error_code(23);
|
display_error_code(23);
|
||||||
|
|
||||||
Log.verbose("Starting webserver");
|
|
||||||
server.begin();
|
|
||||||
display_error_code(24);
|
display_error_code(24);
|
||||||
|
|
||||||
Log.verbose("OTA Setup");
|
Log.verbose("OTA Setup");
|
||||||
ArduinoOTA
|
ArduinoOTA
|
||||||
.onStart([]() {
|
.onStart([]()
|
||||||
|
{
|
||||||
String type;
|
String type;
|
||||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||||
type = "sketch";
|
type = "sketch";
|
||||||
@@ -308,81 +434,37 @@ void setup() {
|
|||||||
type = "filesystem";
|
type = "filesystem";
|
||||||
|
|
||||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||||
Log.verbose("Start updating %s", type);
|
Log.verbose("Start updating %s", type); })
|
||||||
})
|
.onEnd([]()
|
||||||
.onEnd([]() {
|
{ Log.verbose("\nEnd"); })
|
||||||
Log.verbose("\nEnd");
|
.onProgress([](unsigned int progress, unsigned int total)
|
||||||
})
|
{ Serial.printf("Progress: %u%%\r", (progress / (total / 100))); })
|
||||||
.onProgress([](unsigned int progress, unsigned int total) {
|
.onError([](ota_error_t error)
|
||||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
{
|
||||||
})
|
|
||||||
.onError([](ota_error_t error) {
|
|
||||||
Serial.printf("Error[%u]: ", error);
|
Serial.printf("Error[%u]: ", error);
|
||||||
if (error == OTA_AUTH_ERROR) Log.verbose("Auth Failed");
|
if (error == OTA_AUTH_ERROR) Log.verbose("Auth Failed");
|
||||||
else if (error == OTA_BEGIN_ERROR) Log.verbose("Begin Failed");
|
else if (error == OTA_BEGIN_ERROR) Log.verbose("Begin Failed");
|
||||||
else if (error == OTA_CONNECT_ERROR) Log.verbose("Connect Failed");
|
else if (error == OTA_CONNECT_ERROR) Log.verbose("Connect Failed");
|
||||||
else if (error == OTA_RECEIVE_ERROR) Log.verbose("Receive Failed");
|
else if (error == OTA_RECEIVE_ERROR) Log.verbose("Receive Failed");
|
||||||
else if (error == OTA_END_ERROR) Log.verbose("End Failed");
|
else if (error == OTA_END_ERROR) Log.verbose("End Failed"); });
|
||||||
});
|
|
||||||
display_error_code(25);
|
|
||||||
ArduinoOTA.begin();
|
|
||||||
display_error_code(26);
|
display_error_code(26);
|
||||||
digitalWrite(LED_RED, 0);
|
digitalWrite(LED_RED, 0);
|
||||||
Log.verbose(ETH.localIP());
|
|
||||||
|
|
||||||
xTaskCreate(display_task, "DisplayTask", 10000, NULL, 1, NULL);
|
xTaskCreate(display_task, "DisplayTask", 10000, NULL, 1, NULL);
|
||||||
|
xTaskCreate(read_sensor_task, "ReadSensorTask", 2048, NULL, 1, NULL);
|
||||||
|
xTaskCreate(collect_internal_telemetry_task, "InternalTelemetryTask", 2048, NULL, 1, NULL);
|
||||||
|
xTaskCreate(ethernet_task, "EthernetTask", 4096, NULL, 1, NULL);
|
||||||
|
xTaskCreate(wifi_task, "WiFiTask", 10000, NULL, 1, NULL);
|
||||||
|
delay(1000);
|
||||||
|
Log.verbose("Starting webserver");
|
||||||
|
server.begin();
|
||||||
|
display_error_code(25);
|
||||||
|
ArduinoOTA.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
/**
|
{
|
||||||
* Updates the global variables from the current ina sensor data
|
|
||||||
* All other parts just read these variables to prevent incositencies
|
|
||||||
*/
|
|
||||||
void update_sensor_data(){
|
|
||||||
float bus_voltage = ina_sensor.getBusVoltage();
|
|
||||||
float shunt_voltage = ina_sensor.getShuntVoltage_mV() - zero_value;
|
|
||||||
float shunt_current = shunt_voltage / 4 ;
|
|
||||||
|
|
||||||
|
|
||||||
float mA_per_cm = (20 - 4)/ (sensor_range*100);
|
|
||||||
|
|
||||||
|
|
||||||
float min_water_level_mA_over_zero = (min_water_level_cm * mA_per_cm);
|
|
||||||
float max_water_level_mA_over_zero = (max_water_level_cm * mA_per_cm);
|
|
||||||
|
|
||||||
float min_water_level_mA = 4 + min_water_level_mA_over_zero;
|
|
||||||
float max_water_level_mA = 4 + max_water_level_mA_over_zero;
|
|
||||||
|
|
||||||
// Over Zero always revers to zero water level
|
|
||||||
float shunt_current_over_zero = shunt_current - min_water_level_mA;
|
|
||||||
|
|
||||||
int percentage = round(( shunt_current_over_zero / max_water_level_mA_over_zero) * 100);
|
|
||||||
|
|
||||||
|
|
||||||
current_low = shunt_current < 3.8;
|
|
||||||
current_high = shunt_current > 20.2;
|
|
||||||
voltage_low = bus_voltage < 23;
|
|
||||||
voltage_high = bus_voltage > 25;
|
|
||||||
Log.verbose("==========");
|
|
||||||
Log.verbose("Shunt current: %F", shunt_current);
|
|
||||||
Log.verbose("Shunt voltage: %F", shunt_voltage);
|
|
||||||
Log.verbose("Value percentage: %F", percentage);
|
|
||||||
|
|
||||||
|
|
||||||
current_data = SensorData{percentage, bus_voltage, shunt_current, shunt_current_over_zero};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
ArduinoOTA.handle();
|
ArduinoOTA.handle();
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
update_sensor_data();
|
|
||||||
// Log.verbose(WiFi.softAPIP());
|
|
||||||
// Log.verbose(ETH.localIP());
|
|
||||||
delay(5000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user