2023-05-11 10:49:43 +02:00
/****************************************************************************************************************************
2023-07-26 16:04:27 +02:00
Remote Power / SWR Meter - a solution to remotely measure RF power and VSWR over ethernet
2023-05-11 10:49:43 +02:00
For Ethernet shields using WT32_ETH01 ( ESP32 + LAN8720 )
Uses WebServer_WT32_ETH01 , a library for the Ethernet LAN8720 in WT32_ETH01 to run WebServer
2023-05-30 20:15:53 +02:00
Author : Michael Clemens , DK1MI
Licensed under GPLv3 license ( see LICENSE . md )
2023-05-11 10:49:43 +02:00
2023-05-11 16:19:28 +02:00
VU meter code was taken from https : //github.com/tomnomnom/vumeter, credits go to Tom Hudson (https://github.com/tomnomnom)
2023-05-11 10:49:43 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-05-24 11:13:54 +02:00
# define DEBUG_ETHERNET_WEBSERVER_PORT Serial
2023-05-11 10:49:43 +02:00
// Debug Level from 0 to 4
2023-05-24 11:13:54 +02:00
# define _ETHERNET_WEBSERVER_LOGLEVEL_ 3
2023-05-11 10:49:43 +02:00
# define FORMAT_SPIFFS_IF_FAILED true
# include <WebServer_WT32_ETH01.h>
2023-05-30 16:23:15 +02:00
# include "javascript.h"
# include "dashboard_css.h"
# include "config_css.h"
2023-05-11 10:49:43 +02:00
# include "index.h" // Main Web page header file
# include <Preferences.h>
# include "FS.h"
# include "SPIFFS.h"
2023-09-13 12:41:13 +02:00
# include <OneWire.h>
# include <DallasTemperature.h>
2023-05-11 10:49:43 +02:00
2023-09-13 12:41:13 +02:00
String version = " 1.0.2 " ;
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
Preferences config ;
2023-05-24 14:20:12 +02:00
Preferences global_config ;
2023-09-13 12:41:13 +02:00
String band_config_items [ ] = { " b_show_mV " , " b_show_dBm " , " b_show_watt " , " s_vswr_thresh " , " b_vswr_beep " , " s_ant_name " , " s_max_led_pwr_f " , " s_max_led_pwr_r " , " s_max_led_vswr " , " b_show_led_fwd " , " b_show_led_ref " , " b_show_led_vswr " , " s_cable_loss " , " b_power_avg " , " b_show_temp " , " b_celsius " } ;
String band_config_defaults [ ] = { " true " , " true " , " true " , " 2 " , " true " , " " , " 100 " , " 100 " , " 3 " , " true " , " true " , " true " , " 0 " , " false " , " false " , " true " } ;
String band_config_nice_names [ ] = { " Show voltage in mV (yes/no) " , " Show power level in dBm (yes/no) " , " Show power in Watt (yes/no) " , " VSWR threshold that triggers a warning (e.g. 3) " , " Beep if VSWR threshold is exceeded (yes/no) " , " Name of the antenna " , " Max. FWD power displayed by LED bar graph in W (e.g. 100) " , " Max. REF power displayed by LED bar graph in W (e.g. 100) " , " Max. VSWR displayed by LED bar graph (e.g. 3) " , " Show LED graph for FWD power (yes/no) " , " Show LED graph for REF power (yes/no) " , " Show LED graph for VSWR (yes/no) " , " Cable loss in db (e.g. 3) " , " Display average power instead of PEP? (yes=AVG/no=PEP) " , " Display Temperature? (yes/no) " , " Display Temperature in C or F? (yes=C/no=F) " } ;
2023-05-11 10:49:43 +02:00
2023-05-24 11:13:54 +02:00
double fwd_array [ 3300 ] = { } ;
double ref_array [ 3300 ] = { } ;
2023-05-11 10:49:43 +02:00
2023-05-24 11:13:54 +02:00
int voltage_fwd , voltage_ref ;
double fwd_dbm = 0 , ref_dbm = 0 ;
double fwd_watt = 0 , ref_watt = 0 ;
byte iii = 0 ;
2023-05-11 10:49:43 +02:00
String conf_content ;
String conf_textareas = " " ;
String conf_config_table = " " ;
String band = " " ;
String default_band = " 70cm " ;
String band_fwd = band + " _fwd " ;
String band_ref = band + " _ref " ;
2023-05-24 11:13:54 +02:00
String band_list [ ] = { " 1.25cm " , " 3cm " , " 6cm " , " 9cm " , " 13cm " , " 23cm " , " 70cm " , " 2m " , " HF " } ;
2023-05-11 10:49:43 +02:00
int IO2_FWD = 2 ;
int IO4_REF = 4 ;
2023-09-13 12:41:13 +02:00
const int IO14_TEMP = 14 ;
OneWire oneWire ( IO14_TEMP ) ;
DallasTemperature sensors ( & oneWire ) ;
2023-05-11 10:49:43 +02:00
WebServer server ( 80 ) ;
// Select the IP address according to your local network
2023-05-22 13:34:12 +02:00
IPAddress myIP ( 192 , 168 , 1 , 100 ) ;
IPAddress myGW ( 192 , 168 , 1 , 1 ) ;
IPAddress mySN ( 255 , 255 , 255 , 0 ) ;
IPAddress myDNS ( 192 , 168 , 1 , 1 ) ;
2023-05-11 10:49:43 +02:00
2023-05-24 11:13:54 +02:00
// Reads a file from SPIFF and returns its content as a string
String readFile ( fs : : FS & fs , const char * path ) {
Serial . printf ( " Reading file: %s \r \n " , path ) ;
2023-05-11 10:49:43 +02:00
2023-05-24 11:13:54 +02:00
File file = fs . open ( path ) ;
if ( ! file | | file . isDirectory ( ) ) {
Serial . println ( " failed to open file for reading " ) ;
return " " ;
}
2023-05-11 10:49:43 +02:00
String ret = " " ;
2023-05-24 11:13:54 +02:00
Serial . println ( " read from file: " ) ;
while ( file . available ( ) ) {
ret + = char ( file . read ( ) ) ;
}
file . close ( ) ;
return ret ;
2023-05-11 10:49:43 +02:00
}
2023-05-22 13:34:12 +02:00
// Takes a string and writes it to a file on SPIFF
2023-05-24 11:13:54 +02:00
void writeFile ( fs : : FS & fs , const char * path , const char * message ) {
Serial . printf ( " Writing file: %s \r \n " , path ) ;
File file = fs . open ( path , FILE_WRITE ) ;
if ( ! file ) {
Serial . println ( " failed to open file for writing " ) ;
return ;
}
if ( file . print ( message ) ) {
Serial . println ( " file written " ) ;
} else {
Serial . println ( " file write failed " ) ;
}
file . close ( ) ;
2023-05-11 10:49:43 +02:00
}
// converts dBm to Watt
double dbm_to_watt ( double dbm ) {
2023-05-24 11:13:54 +02:00
return pow ( 10.0 , ( dbm - 30.0 ) / 10.0 ) ;
2023-05-11 10:49:43 +02:00
}
2023-05-19 22:43:59 +02:00
// checks if a given voltage is lower as the smallest value
// in the table or higher than the biggest value
2023-05-24 11:13:54 +02:00
bool is_val_out_of_bounds ( int mv , bool fwd ) {
2023-05-19 22:43:59 +02:00
double stored_val = 0 ;
int key_a = 0 ;
int key_b = 0 ;
2023-05-22 13:34:12 +02:00
// searches for the first key (voltage) that has a value (dBm)
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < 3300 ; i + + ) {
2023-05-19 22:43:59 +02:00
if ( fwd ) {
stored_val = fwd_array [ i ] ;
} else {
stored_val = ref_array [ i ] ;
}
if ( stored_val ! = 0 ) {
key_a = i ;
break ;
2023-05-24 11:13:54 +02:00
}
2023-05-19 22:43:59 +02:00
}
2023-05-22 13:34:12 +02:00
// searches for the last key (voltage) that has a value (dBm)
2023-05-24 11:13:54 +02:00
for ( int i = 3299 ; i > 0 ; i - - ) {
2023-05-19 22:43:59 +02:00
if ( fwd ) {
stored_val = fwd_array [ i ] ;
} else {
stored_val = ref_array [ i ] ;
}
if ( stored_val ! = 0 ) {
key_b = i ;
break ;
2023-05-24 11:13:54 +02:00
}
2023-05-19 22:43:59 +02:00
}
2023-05-24 11:13:54 +02:00
int lowerkey = min ( key_a , key_b ) ; // takes both values found above and assigns the lower key
int higherkey = max ( key_a , key_b ) ; // takes both values found above and assigns the higher key
2023-05-22 13:34:12 +02:00
// returns false if given voltage is between the lowest and highest configured voltages
// returns true if voltage is out of bounds
2023-05-19 22:43:59 +02:00
if ( lowerkey < = mv and mv < = higherkey )
return false ;
else {
return true ;
}
}
2023-05-11 10:49:43 +02:00
// takes a voltage value and translates it
// to dBm based on the corresponding lookup table
2023-05-24 11:13:54 +02:00
double millivolt_to_dbm ( int mv , bool fwd ) {
2023-05-11 10:49:43 +02:00
double lastval = 0 ;
double nextval = 0 ;
int lastkey = 0 ;
int nextkey = 0 ;
double stored_val = 0 ;
2023-05-19 22:43:59 +02:00
bool ascending = true ;
2023-05-11 10:49:43 +02:00
2023-05-19 22:43:59 +02:00
int lowest_key_in_table = 0 ;
int highest_key_in_table = 0 ;
2023-05-11 10:49:43 +02:00
2023-05-19 22:43:59 +02:00
// check if table is ascending or descending
double asc_tmp_val = 0 ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < 3300 ; i + + ) {
2023-05-11 10:49:43 +02:00
if ( fwd ) {
stored_val = fwd_array [ i ] ;
} else {
stored_val = ref_array [ i ] ;
}
if ( stored_val ! = 0 ) {
2023-05-19 22:43:59 +02:00
if ( asc_tmp_val = = 0 ) {
asc_tmp_val = stored_val ;
} else if ( stored_val > asc_tmp_val ) {
ascending = true ;
break ;
} else if ( stored_val < asc_tmp_val ) {
ascending = false ;
break ;
2023-05-11 10:49:27 +02:00
}
2023-05-24 11:13:54 +02:00
}
2023-05-19 22:43:59 +02:00
}
2023-06-02 10:14:56 +02:00
// checks if the voltage values are opposite to the dBm values or
// if both, voltage and dBm values are ascending
2023-05-19 22:43:59 +02:00
if ( ascending ) {
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < 3300 ; i + + ) {
2023-05-19 22:43:59 +02:00
if ( fwd ) {
stored_val = fwd_array [ i ] ;
2023-05-11 10:49:27 +02:00
} else {
2023-05-19 22:43:59 +02:00
stored_val = ref_array [ i ] ;
}
if ( stored_val ! = 0 ) {
2023-05-24 11:13:54 +02:00
if ( lowest_key_in_table = = 0 ) {
lowest_key_in_table = i ; //finds the lowest voltage value stored in the table
2023-05-19 22:43:59 +02:00
}
2023-05-24 11:13:54 +02:00
highest_key_in_table = i ; // we will have the highest voltage value in the table at the end of the loop
if ( i < mv ) {
2023-05-19 22:43:59 +02:00
lastval = stored_val ;
lastkey = i ;
} else {
nextval = stored_val ;
nextkey = i ;
break ;
}
2023-05-04 14:34:11 +02:00
}
2023-05-11 10:49:43 +02:00
}
2023-05-11 16:19:28 +02:00
} else {
2023-05-24 11:13:54 +02:00
for ( int i = 3300 ; i > 0 ; i - - ) {
2023-05-19 22:43:59 +02:00
if ( fwd ) {
stored_val = fwd_array [ i ] ;
} else {
stored_val = ref_array [ i ] ;
}
if ( stored_val ! = 0 ) {
2023-05-24 11:13:54 +02:00
if ( lowest_key_in_table = = 0 ) {
lowest_key_in_table = i ; //finds the lowest voltage value stored in the table
2023-05-19 22:43:59 +02:00
}
2023-05-24 11:13:54 +02:00
highest_key_in_table = i ; // we will have the highest voltage value in the table at the end of the loop
if ( i > mv ) {
2023-05-19 22:43:59 +02:00
lastval = stored_val ;
lastkey = i ;
} else {
nextval = stored_val ;
nextkey = i ;
break ;
}
}
}
}
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
double lowerkey = min ( lastkey , nextkey ) ;
2023-05-19 22:43:59 +02:00
double higherkey = max ( lastkey , nextkey ) ;
2023-05-22 13:34:12 +02:00
2023-05-11 10:49:43 +02:00
double lowerval = min ( lastval , nextval ) ;
2023-05-19 22:43:59 +02:00
double higherval = max ( lastval , nextval ) ;
2023-05-11 10:49:43 +02:00
double diffkey = max ( lastkey , nextkey ) - min ( lastkey , nextkey ) ;
double diffval = max ( lastval , nextval ) - min ( lastval , nextval ) ;
2023-05-22 13:34:12 +02:00
2023-05-19 22:43:59 +02:00
double result = 0 ;
2023-05-22 13:34:12 +02:00
2023-05-19 22:43:59 +02:00
if ( ascending ) {
result = lowerval + ( ( diffval / diffkey ) * ( mv - lowerkey ) ) ;
} else {
result = higherval - ( ( diffval / diffkey ) * ( mv - lowerkey ) ) ;
2023-05-11 10:49:43 +02:00
}
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
return result ;
}
// read voltages from both input pins
2023-05-22 13:34:12 +02:00
// calculates avaerage value of 50 measurements
2023-05-24 11:13:54 +02:00
void read_directional_couplers ( ) {
2023-05-11 10:49:43 +02:00
int voltage_sum_fwd = 0 ;
int voltage_sum_ref = 0 ;
2023-05-22 13:34:12 +02:00
2023-09-13 12:41:13 +02:00
int voltage_fwd_max = 0 ;
int voltage_ref_max = 0 ;
int voltage_fwd_now = 0 ;
int voltage_ref_now = 0 ;
2023-05-22 13:34:12 +02:00
// Takes 50 samples and sums them up
2023-09-13 12:41:13 +02:00
// figure out the highest values
2023-05-24 11:13:54 +02:00
for ( iii = 0 ; iii < 50 ; iii + + ) {
2023-09-13 12:41:13 +02:00
voltage_fwd_now = analogReadMilliVolts ( IO2_FWD ) ;
voltage_ref_now = analogReadMilliVolts ( IO4_REF ) ;
voltage_sum_fwd + = voltage_fwd_now ;
voltage_sum_ref + = voltage_ref_now ;
voltage_fwd_max = max ( voltage_fwd_now , voltage_fwd_max ) ;
voltage_ref_max = max ( voltage_ref_now , voltage_ref_max ) ;
2023-05-11 10:49:43 +02:00
}
2023-09-13 12:41:13 +02:00
if ( config . getString ( String ( " s_power_avg " ) . c_str ( ) ) = = " true " ) {
// calculate the average value by deviding the above sum by 50
voltage_fwd = voltage_sum_fwd / 50 ;
voltage_ref = voltage_sum_ref / 50 ;
} else {
// take the highest value of the 50 samples
voltage_fwd = voltage_fwd_max ;
voltage_ref = voltage_ref_max ;
}
2023-05-11 10:49:43 +02:00
2023-05-22 13:34:12 +02:00
// calculate the dBm value from the voltage based on the calibration table
2023-05-11 10:49:43 +02:00
fwd_dbm = millivolt_to_dbm ( voltage_fwd , true ) ;
ref_dbm = millivolt_to_dbm ( voltage_ref , false ) ;
2023-06-02 10:14:56 +02:00
// add cable loss to FWD dBm, substract cable loss from REF dBm
double cable_loss = 0 ;
cable_loss = config . getString ( String ( " s_cable_loss " ) . c_str ( ) ) . toDouble ( ) ;
//Serial.println("cable loss: " + String(cable_loss));
fwd_dbm = fwd_dbm - cable_loss ;
ref_dbm = ref_dbm + cable_loss ;
2023-05-22 13:34:12 +02:00
// calculate watt from dBm
2023-05-12 13:43:53 +02:00
fwd_watt = dbm_to_watt ( fwd_dbm ) ;
ref_watt = dbm_to_watt ( ref_dbm ) ;
2023-05-11 10:49:43 +02:00
}
// delivers the dashboard page in "index.h"
2023-05-24 11:13:54 +02:00
void handleRoot ( ) {
2023-05-30 16:23:15 +02:00
String html = MAIN_page ;
String css = DB_STYLESHEET ;
2023-06-02 10:14:56 +02:00
String js = JAVASCRIPT ;
2023-05-30 16:23:15 +02:00
server . send ( 200 , " text/html " , css + js + html ) ;
2023-05-11 10:49:43 +02:00
}
// delivers a 404 page if a non-existant resouurce is requested
2023-05-24 11:13:54 +02:00
void handleNotFound ( ) {
2023-05-11 10:49:43 +02:00
String message = F ( " File Not Found \n \n " ) ;
message + = F ( " URI: " ) ;
message + = server . uri ( ) ;
message + = F ( " \n Method: " ) ;
message + = ( server . method ( ) = = HTTP_GET ) ? F ( " GET " ) : F ( " POST " ) ;
message + = F ( " \n Arguments: " ) ;
message + = server . args ( ) ;
message + = F ( " \n " ) ;
2023-05-24 11:13:54 +02:00
for ( uint8_t i = 0 ; i < server . args ( ) ; i + + ) {
2023-05-11 10:49:43 +02:00
message + = " " + server . argName ( i ) + " : " + server . arg ( i ) + " \n " ;
}
server . send ( 404 , F ( " text/plain " ) , message ) ;
}
2023-05-19 22:43:59 +02:00
2023-05-11 10:49:43 +02:00
// executes the function to gather sensor data
// delivers gathered data to dashboard page
// invoked periodically by the dashboard page
void handleDATA ( ) {
read_directional_couplers ( ) ;
2023-05-19 22:43:59 +02:00
2023-05-12 13:43:53 +02:00
double vswr = 0 ;
2023-05-19 22:43:59 +02:00
2023-05-24 11:13:54 +02:00
if ( fwd_watt > ref_watt ) {
vswr = ( 1 + sqrt ( ref_watt / fwd_watt ) ) / ( 1 - sqrt ( ref_watt / fwd_watt ) ) ;
2023-05-12 13:43:53 +02:00
}
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
String vswr_str = " -1 " ;
String fwd_watt_str = " " ;
String ref_watt_str = " " ;
if ( vswr > = 1 ) {
vswr_str = String ( vswr ) ;
}
double rl = fwd_dbm - ref_dbm ;
// get vswr_threshold from general config
2023-05-24 14:01:19 +02:00
String vswr_threshold = config . getString ( String ( " s_vswr_thresh " ) . c_str ( ) ) ;
2023-05-11 10:49:43 +02:00
String voltage_fwd_str = " " ;
String voltage_ref_str = " " ;
2023-05-24 14:01:19 +02:00
if ( config . getString ( String ( " b_show_mV " ) . c_str ( ) ) ! = " false " ) {
2023-05-11 10:49:43 +02:00
voltage_fwd_str = String ( voltage_fwd ) + " mV " ;
voltage_ref_str = String ( voltage_ref ) + " mV " ;
}
String fwd_dbm_str = " " ;
String ref_dbm_str = " " ;
2023-05-24 14:01:19 +02:00
if ( config . getString ( String ( " b_show_dBm " ) . c_str ( ) ) ! = " false " ) {
2023-05-24 11:13:54 +02:00
fwd_dbm_str = String ( fwd_dbm , 2 ) ;
ref_dbm_str = String ( ref_dbm , 2 ) ;
2023-05-11 10:49:43 +02:00
}
2023-05-11 22:26:10 +02:00
2023-05-24 14:01:19 +02:00
if ( config . getString ( String ( " b_show_watt " ) . c_str ( ) ) ! = " false " ) {
2023-05-24 11:13:54 +02:00
fwd_watt_str = String ( fwd_watt , 10 ) ;
2023-05-11 22:26:10 +02:00
}
2023-05-24 14:01:19 +02:00
if ( config . getString ( String ( " b_show_watt " ) . c_str ( ) ) ! = " false " ) {
2023-05-24 11:13:54 +02:00
ref_watt_str = String ( ref_watt , 10 ) ;
2023-05-11 22:26:10 +02:00
}
2023-05-11 22:48:35 +02:00
String rl_str = " -- " ;
if ( rl > 0 ) {
rl_str = ( String ( rl ) ) ;
}
2023-05-11 10:49:43 +02:00
rl_str . replace ( " nan " , " -- " ) ;
2023-05-24 14:01:19 +02:00
String antenna_name = config . getString ( String ( " s_ant_name " ) . c_str ( ) ) ;
String vswr_beep = config . getString ( String ( " b_vswr_beep " ) . c_str ( ) ) ;
2023-05-11 10:49:43 +02:00
2023-05-19 22:43:59 +02:00
bool fwd_oob = is_val_out_of_bounds ( voltage_fwd , true ) ;
bool ref_oob = is_val_out_of_bounds ( voltage_ref , false ) ;
2023-05-22 13:34:12 +02:00
// Generate a semicolon seperated string that will be sent to the frontend
2023-05-24 11:13:54 +02:00
String output = fwd_watt_str + " ; " ; // data[0]: FWD power in Watt
output + = fwd_dbm_str + " ; " ; // data[1]: FWD dBm value
output + = voltage_fwd_str + " ; " ; // data[2]: FWD voltage
output + = ref_watt_str + " ; " ; // data[3]: REF power in Watt
output + = ref_dbm_str + " ; " ; // data[4]: REF dBm value
output + = voltage_ref_str + " ; " ; // data[5]: REF voltage
output + = vswr_str + " ; " ; // data[6]: VSWR value
output + = rl_str + " ; " ; // data[7]: RL value
output + = band + " ; " ; // data[8]: band (e.g. "70cm")
output + = String ( vswr_threshold ) + " ; " ; // data[9]: VSWR threshold (e.g. "3")
2023-05-24 14:01:19 +02:00
output + = antenna_name + " ; " ; // data[10]: Name of antenna (e.g. "X200")
2023-05-24 11:13:54 +02:00
output + = vswr_beep + " ; " ; // data[11]: should it beep if VSWR is too high? (true/false)
2023-05-24 14:01:19 +02:00
output + = config . getString ( String ( " s_max_led_pwr_f " ) . c_str ( ) ) + " ; " ; // data[12]: highest value in Watt for the FWD LED graph (e.g. "100")
output + = config . getString ( String ( " s_max_led_pwr_r " ) . c_str ( ) ) + " ; " ; // data[13]: highest value in Watt for the REF LED graph (e.g. "1")
output + = config . getString ( String ( " s_max_led_vswr " ) . c_str ( ) ) + " ; " ; // data[14]: highest value in Watt for the VSWR LED graph (e.g. "3")
2023-05-24 11:13:54 +02:00
output + = String ( fwd_oob ) + " ; " ; // data[15]: Is the FWD voltage out of bounds? (true/false)
output + = String ( ref_oob ) + " ; " ; // data[16]: Is the REF voltage out of bounds? (true/false)
2023-05-24 14:01:19 +02:00
output + = config . getString ( String ( " b_show_led_fwd " ) . c_str ( ) ) + " ; " ; // data[17]: Show the FWD LED bar graph? (true/false)
output + = config . getString ( String ( " b_show_led_ref " ) . c_str ( ) ) + " ; " ; // data[18]: Show the REF LED bar graph? (true/false)
2023-05-30 23:12:32 +02:00
output + = config . getString ( String ( " b_show_led_vswr " ) . c_str ( ) ) + " ; " ; // data[19]: Show the VSWR LED bar graph? (true/false)
2023-09-13 12:41:13 +02:00
output + = version + " ; " ; // data[20]: program version
output + = getTemp ( ) ; // data[21]: temperature
2023-05-11 10:49:43 +02:00
server . send ( 200 , " text/plane " , output ) ;
}
// main function for displaying the configuration page
// invoked by the "configuration" button on the dashboard page
void handleCONFIG ( ) {
if ( conf_textareas = = " " ) {
build_textareas ( ) ;
}
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
if ( conf_config_table = = " " ) {
build_config_table ( ) ;
}
2023-05-24 11:13:54 +02:00
2023-05-30 16:23:15 +02:00
String css = CFG_STYLESHEET ;
conf_content = css ;
2023-05-30 18:58:50 +02:00
conf_content + = " <div class='grid-container'> " ;
conf_content + = " <div id='title_box' class='titlebox maintitlebox'> " ;
conf_content + = " Configuration</div> " ;
conf_content + = " <div id='title_box' class='bandbox maintitlebox'> " ;
2023-05-11 10:49:43 +02:00
conf_content + = " <form method='POST' action='/selectband'> " ;
2023-06-02 10:14:56 +02:00
conf_content + = " Band: <label for='bands'></label><select class='button' onchange='this.form.submit()'' id='band' name='bands' size='1'> " ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < sizeof band_list / sizeof band_list [ 0 ] ; i + + ) {
2023-05-11 10:49:43 +02:00
String selected = " " ;
if ( band_list [ i ] = = band ) {
selected = " selected " ;
}
conf_content + = " <option value=' " + band_list [ i ] + " ' " + selected + " > " + band_list [ i ] + " </option> " ;
}
conf_content + = " </select></form> " ;
2023-05-30 18:58:50 +02:00
conf_content + = " </div> " ;
2023-06-02 10:14:56 +02:00
conf_content + = " <div class='subtitle1 subtitlebox'>Translation Detector Voltage /mV to RF-Power Level /dBm</div> " ;
2023-05-30 18:58:50 +02:00
conf_content + = " <div class='translationitems contentbox'> " ;
2023-05-24 11:13:54 +02:00
conf_content + = conf_textareas ;
2023-05-30 18:58:50 +02:00
conf_content + = " </div> " ;
conf_content + = " <div class='subtitle2 subtitlebox'>General Configuration Items</div> " ;
conf_content + = " <div class='configitems contentbox'> " ;
2023-05-11 10:49:43 +02:00
conf_content + = conf_config_table ;
2023-05-30 18:58:50 +02:00
conf_content + = " </div> " ;
conf_content + = " <div class='footerbox'> " ;
2023-05-30 23:12:32 +02:00
conf_content + = " <form method='POST' action='/'><button class='linkbutton' value='back' name='back' type='submit'>Back to Dashboard</button> - Version: " + version + " </form> " ;
2023-05-30 18:58:50 +02:00
conf_content + = " </div> " ;
conf_content + = " </div> " ;
2023-05-11 10:49:43 +02:00
conf_content + = " </html> " ;
server . send ( 200 , " text/html " , conf_content ) ;
}
// generates the translation table for either the FWD or
// REF values
void build_textareas ( ) {
String fwd = readFile ( SPIFFS , String ( " / " + band + " fwd.txt " ) . c_str ( ) ) ;
String ref = readFile ( SPIFFS , String ( " / " + band + " ref.txt " ) . c_str ( ) ) ;
clear_fwd_ref_array ( ) ;
save_string_to_array ( fwd , fwd_array ) ;
save_string_to_array ( ref , ref_array ) ;
2023-06-02 10:14:56 +02:00
String tbl = " <form action= \" /modcal \" method= \" POST \" > " ;
2023-05-11 10:49:43 +02:00
tbl + = " <table class='styled-table'> " ;
2023-05-24 11:13:54 +02:00
tbl + = " <thead><tr><td> " + band + " FWD (mV:dBm)</td><td> " + band + " REF (mV:dBm)</td></tr></thead> " ;
2023-05-11 10:49:43 +02:00
tbl + = " <tr><td> " ;
2023-05-30 18:58:50 +02:00
tbl + = " <textarea id='fwd_textarea' name='fwd_textarea' rows='22'> " ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < sizeof fwd_array / sizeof fwd_array [ 0 ] ; i + + ) {
if ( fwd_array [ i ] ! = 0 ) {
tbl + = String ( i ) + " : " + String ( fwd_array [ i ] , 5 ) + " \n " ;
2023-05-11 10:49:43 +02:00
}
}
tbl + = " </textarea> " ;
tbl + = " </td><td> " ;
2023-05-30 18:58:50 +02:00
tbl + = " <textarea id='ref_textarea' name='ref_textarea' rows='22'> " ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < sizeof ref_array / sizeof ref_array [ 0 ] ; i + + ) {
if ( ref_array [ i ] ! = 0 ) {
tbl + = String ( i ) + " : " + String ( ref_array [ i ] , 5 ) + " \n " ;
2023-05-11 10:49:43 +02:00
}
}
tbl + = " </textarea> " ;
tbl + = " </td></tr></table> " ;
2023-06-02 10:14:56 +02:00
tbl + = " <button class='button' value='save' name='save' type='submit'>Save Calibration Data</button> " ;
2023-05-11 10:49:43 +02:00
tbl + = " </form> " ;
conf_textareas = tbl ;
}
// generates the table with generic configuration items
void build_config_table ( ) {
conf_config_table = " <form action= \" /modcfg \" method= \" POST \" > " ;
conf_config_table + = " <table class='styled-table'> " ;
2023-05-30 18:58:50 +02:00
//conf_config_table += "<thead><tr><td>Key</td><td>Value</td></td></tr></thead>";
2023-05-24 14:20:12 +02:00
for ( int i = 0 ; i < sizeof band_config_items / sizeof band_config_items [ 0 ] ; i + + ) {
if ( ! band_config_items [ i ] . startsWith ( " x_ " ) ) {
String stored_val = config . getString ( band_config_items [ i ] . c_str ( ) , " xxx " ) ;
2023-05-24 14:01:19 +02:00
if ( stored_val = = " xxx " ) {
2023-05-24 14:20:12 +02:00
config . putString ( band_config_items [ i ] . c_str ( ) , band_config_defaults [ i ] ) ;
stored_val = config . getString ( band_config_items [ i ] . c_str ( ) , " " ) ;
2023-05-24 14:01:19 +02:00
}
conf_config_table + = " <tr><td> " ;
2023-05-24 14:20:12 +02:00
conf_config_table + = band_config_nice_names [ i ] ;
2023-05-24 14:01:19 +02:00
conf_config_table + = " </td><td> " ;
2023-06-02 10:14:56 +02:00
2023-05-24 14:01:19 +02:00
if ( String ( stored_val ) . equalsIgnoreCase ( " true " ) ) {
2023-05-24 14:20:12 +02:00
conf_config_table + = " <input type='checkbox' name=' " + band_config_items [ i ] + " ' id=' " + band_config_items [ i ] + " ' value='true' checked> " ;
2023-05-24 14:01:19 +02:00
} else if ( String ( stored_val ) . equalsIgnoreCase ( " false " ) ) {
2023-05-24 14:20:12 +02:00
conf_config_table + = " <input type='checkbox' name=' " + band_config_items [ i ] + " ' id=' " + band_config_items [ i ] + " ' value='false'> " ;
2023-05-24 14:01:19 +02:00
} else {
2023-05-24 14:20:12 +02:00
conf_config_table + = " <input name=' " + band_config_items [ i ] + " ' value=' " + String ( stored_val ) + " ' valuelength=16> " ;
2023-05-24 14:01:19 +02:00
}
conf_config_table + = " </td></tr> " ;
2023-05-11 10:49:43 +02:00
}
2023-05-24 14:01:19 +02:00
}
2023-06-02 10:14:56 +02:00
conf_config_table + = " </table><button class='button' value='save' name='save' type='submit'>Save Configuration</button></form> " ;
2023-05-11 10:49:43 +02:00
handleCONFIG ( ) ;
}
// Handle request from the config page to change or add values
// to the XXXX value table for the selected band
2023-06-02 10:14:56 +02:00
void handleMODCAL ( ) {
2023-05-11 10:49:43 +02:00
String fwd = server . arg ( " fwd_textarea " ) + " \n " ;
String ref = server . arg ( " ref_textarea " ) + " \n " ;
clear_fwd_ref_array ( ) ;
2023-05-24 11:13:54 +02:00
save_string_to_array ( fwd , fwd_array ) ;
save_string_to_array ( ref , ref_array ) ;
2023-05-11 10:49:43 +02:00
String fwd_of_array = " " ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < sizeof fwd_array / sizeof fwd_array [ 0 ] ; i + + ) {
if ( fwd_array [ i ] ! = 0 ) {
fwd_of_array + = String ( i ) + " : " + String ( fwd_array [ i ] , 5 ) + " \n " ;
2023-05-11 10:49:43 +02:00
}
}
writeFile ( SPIFFS , String ( " / " + band + " fwd.txt " ) . c_str ( ) , fwd_of_array . c_str ( ) ) ;
String ref_of_array = " " ;
2023-05-24 11:13:54 +02:00
for ( int i = 0 ; i < sizeof ref_array / sizeof ref_array [ 0 ] ; i + + ) {
if ( ref_array [ i ] ! = 0 ) {
ref_of_array + = String ( i ) + " : " + String ( ref_array [ i ] , 5 ) + " \n " ;
2023-05-11 10:49:43 +02:00
}
}
writeFile ( SPIFFS , String ( " / " + band + " ref.txt " ) . c_str ( ) , ref_of_array . c_str ( ) ) ;
2023-05-22 13:34:12 +02:00
2023-05-11 10:49:43 +02:00
build_textareas ( ) ;
handleCONFIG ( ) ;
}
2023-05-22 13:34:12 +02:00
// resets all vlaues in the FWD and REF array
2023-05-24 11:13:54 +02:00
void clear_fwd_ref_array ( ) {
for ( int x = 0 ; x < sizeof ( fwd_array ) / sizeof ( fwd_array [ 0 ] ) ; x + + ) {
2023-05-11 10:49:43 +02:00
fwd_array [ x ] = 0 ;
ref_array [ x ] = 0 ;
}
}
2023-05-22 13:34:12 +02:00
// after the user edited the calibration table via the frontend,
// this function takes the resulting string, detonates it and
// writes all rows into an array
2023-05-24 11:13:54 +02:00
void save_string_to_array ( String table_data , double arr [ ] ) {
int r = 0 , t = 0 ;
for ( int i = 0 ; i < table_data . length ( ) ; i + + ) {
if ( table_data [ i ] = = ' \n ' | | i = = table_data . length ( ) ) {
if ( i - r > 1 ) {
String row = table_data . substring ( r , i ) ;
2023-05-11 10:49:43 +02:00
t + + ;
2023-05-24 11:13:54 +02:00
int r2 = 0 , t2 = 0 ;
for ( int j = 0 ; j < row . length ( ) ; j + + ) {
if ( row [ j ] = = ' : ' | | row [ j ] = = ' \n ' ) {
if ( j - r2 > 1 ) {
int key = row . substring ( r2 , j ) . toInt ( ) ;
double val = row . substring ( j + 1 ) . toDouble ( ) ;
2023-05-11 10:49:43 +02:00
arr [ key ] = val ;
t2 + + ;
}
2023-05-24 11:13:54 +02:00
r2 = ( j + 1 ) ;
2023-05-11 10:49:43 +02:00
}
}
}
2023-05-24 11:13:54 +02:00
r = ( i + 1 ) ;
2023-05-11 10:49:43 +02:00
}
}
}
// Handle request from the config page to change or add values
2023-05-24 14:01:19 +02:00
// to the general config value table for the selected band
2023-05-11 10:49:43 +02:00
void handleMODCFG ( ) {
2023-05-24 14:20:12 +02:00
for ( int i = 0 ; i < sizeof band_config_items / sizeof band_config_items [ 0 ] ; i + + ) {
2023-06-02 10:14:56 +02:00
if ( ! server . hasArg ( band_config_items [ i ] ) and band_config_items [ i ] . startsWith ( " b_ " ) ) {
2023-05-24 14:20:12 +02:00
config . putString ( band_config_items [ i ] . c_str ( ) , " false " ) ;
2023-06-02 10:14:56 +02:00
} else if ( server . hasArg ( band_config_items [ i ] ) and band_config_items [ i ] . startsWith ( " b_ " ) ) {
2023-05-24 14:20:12 +02:00
config . putString ( band_config_items [ i ] . c_str ( ) , " true " ) ;
2023-05-24 14:01:19 +02:00
} else {
2023-05-24 14:20:12 +02:00
config . putString ( band_config_items [ i ] . c_str ( ) , server . arg ( band_config_items [ i ] ) ) ;
2023-06-02 10:14:56 +02:00
}
2023-05-11 10:49:43 +02:00
}
2023-05-24 14:01:19 +02:00
conf_config_table = " " ;
2023-05-11 10:49:43 +02:00
build_config_table ( ) ;
}
// changes the band according to the user's selection
2023-06-02 10:14:56 +02:00
// regenerates the calibration tables and fills them
2023-05-11 10:49:43 +02:00
// with the values assigned to the respective band
2023-05-24 14:01:19 +02:00
// invoked by selecting a band from the select box of the config page
2023-05-11 10:49:43 +02:00
void handleBAND ( ) {
band = server . arg ( " bands " ) ;
band_fwd = band + " _fwd " ;
band_ref = band + " _ref " ;
2023-05-24 14:20:12 +02:00
global_config . putString ( String ( " x_selected_band " ) . c_str ( ) , band ) ;
config . end ( ) ;
String bnd_cnf = " config_ " + band ;
config . begin ( bnd_cnf . c_str ( ) , false ) ;
2023-05-11 10:49:43 +02:00
conf_textareas = " " ;
conf_config_table = " " ;
//build_config_table();
//build_textareas();
handleCONFIG ( ) ;
}
2023-09-13 12:41:13 +02:00
// reads the temperature from the aboce defined sensor
// and returns it in either C or F as a string
String getTemp ( ) {
String ret = " " ;
if ( config . getString ( String ( " b_show_temp " ) . c_str ( ) ) = = " true " ) {
String label = " Temp: " ;
String temp_string = " -- " ;
String unit = " " ;
float temp_float ;
sensors . requestTemperatures ( ) ;
if ( config . getString ( String ( " b_celsius " ) . c_str ( ) ) ! = " false " ) {
unit = " °C " ;
temp_float = sensors . getTempCByIndex ( 0 ) ;
} else {
unit = " °F " ;
temp_float = sensors . getTempFByIndex ( 0 ) ;
}
if ( temp_float > - 100 ) {
temp_string = String ( temp_float , 1 ) ;
}
ret = label + temp_string + unit ;
}
return ret ;
}
2023-05-11 10:49:43 +02:00
// initialization routine
2023-05-24 11:13:54 +02:00
void setup ( ) {
2023-05-24 14:01:19 +02:00
2023-05-11 10:49:43 +02:00
Serial . begin ( 115200 ) ;
2023-09-13 12:41:13 +02:00
// initialize temperature sensor
sensors . begin ( ) ;
2023-05-11 10:49:43 +02:00
Serial . print ( " \n Starting AdvancedWebServer on " + String ( ARDUINO_BOARD ) ) ;
Serial . println ( " with " + String ( SHIELD_TYPE ) ) ;
Serial . println ( WEBSERVER_WT32_ETH01_VERSION ) ;
// To be called before ETH.begin()
WT32_ETH01_onEvent ( ) ;
2023-05-24 11:13:54 +02:00
2023-05-11 10:49:43 +02:00
ETH . begin ( ETH_PHY_ADDR , ETH_PHY_POWER ) ;
2023-05-22 13:34:12 +02:00
// Static IP, leave without this line to get IP via DHCP
2023-05-11 10:49:43 +02:00
//ETH.config(myIP, myGW, mySN, myDNS);
WT32_ETH01_waitForConnect ( ) ;
// activates single web server endpoints
server . on ( F ( " / " ) , handleRoot ) ;
server . on ( " /readDATA " , handleDATA ) ;
server . on ( " /config " , handleCONFIG ) ;
server . on ( " /modcfg " , handleMODCFG ) ;
server . on ( " /selectband " , handleBAND ) ;
2023-06-02 10:14:56 +02:00
server . on ( " /modcal " , handleMODCAL ) ;
2023-05-11 10:49:43 +02:00
2023-05-24 11:13:54 +02:00
if ( ! SPIFFS . begin ( FORMAT_SPIFFS_IF_FAILED ) ) {
2023-05-11 10:49:43 +02:00
Serial . println ( " SPIFFS Mount Failed " ) ;
return ;
2023-05-24 11:13:54 +02:00
}
2023-05-11 10:49:43 +02:00
server . onNotFound ( handleNotFound ) ;
server . begin ( ) ;
Serial . print ( F ( " HTTP EthernetWebServer is @ IP : " ) ) ;
Serial . println ( ETH . localIP ( ) ) ;
analogReadResolution ( 12 ) ;
2023-05-24 14:20:12 +02:00
global_config . begin ( " config " , false ) ;
band = global_config . getString ( String ( " x_selected_band " ) . c_str ( ) ) ;
2023-05-24 11:13:54 +02:00
if ( band = = " " ) {
2023-05-24 14:20:12 +02:00
global_config . putString ( String ( " x_selected_band " ) . c_str ( ) , default_band ) ;
2023-05-11 10:49:43 +02:00
band = default_band ;
}
2023-05-24 14:20:12 +02:00
String bnd_cnf = " config_ " + band ;
config . begin ( bnd_cnf . c_str ( ) , false ) ;
2023-05-11 10:49:43 +02:00
build_textareas ( ) ;
}
2023-05-24 11:13:54 +02:00
void loop ( ) {
2023-05-11 10:49:43 +02:00
server . handleClient ( ) ;
}