@ -6,21 +6,32 @@
# include "app.h"
# include <ArduinoJson.h>
# include "utils/sun.h"
# include "plugins/SML_OBIS_Parser.h"
# ifndef min
# define min(a,b) (((a) < (b)) ? (a) : (b))
# endif
//-----------------------------------------------------------------------------
app : : app ( ) : ah : : Scheduler ( ) { }
//-----------------------------------------------------------------------------
void app : : setup ( ) {
# ifdef AHOY_SML_OBIS_SUPPORT
/* Assumptions made:
Electricity meter sends SML telegrams via IR interface ( 9600 , 8 , n , 1 ) without being asked ( typical behaviour ) .
An IR sensor is connected to the UART0 of AHOY DTU . Connected pins : GND - GND , 3 V3 - VCC , RX - RX , TX - TX .
*/
Serial . begin ( 9600 , SERIAL_8N1 , SERIAL_RX_ONLY ) ;
# else
Serial . begin ( 115200 ) ;
# endif
while ( ! Serial )
yield ( ) ;
ah : : Scheduler : : setup ( ) ;
resetSystem ( ) ;
mSettings . setup ( ) ;
mSettings . getPtr ( mConfig ) ;
DPRINT ( DBG_INFO , F ( " Settings valid: " ) ) ;
@ -30,7 +41,7 @@ void app::setup() {
DBGPRINTLN ( F ( " false " ) ) ;
mSys . enableDebug ( ) ;
mSys . setup ( mConfig - > nrf . amplifierPower , mConfig - > nrf . pinIrq , mConfig - > nrf . pinCe , mConfig - > nrf . pinCs , mConfig - > nrf . pinSclk , mConfig - > nrf . pinMosi , mConfig - > nrf . pinMiso ) ;
mSys . setup ( & mTimestamp , mConfig - > nrf . amplifierPower , mConfig - > nrf . pinIrq , mConfig - > nrf . pinCe , mConfig - > nrf . pinCs , mConfig - > nrf . pinSclk , mConfig - > nrf . pinMosi , mConfig - > nrf . pinMiso ) ;
# if defined(AP_ONLY)
mInnerLoopCb = std : : bind ( & app : : loopStandard , this ) ;
@ -62,7 +73,7 @@ void app::setup() {
DPRINTLN ( DBG_WARN , F ( " WARNING! your NRF24 module can't be reached, check the wiring " ) ) ;
// when WiFi is in client mode, then enable mqtt broker
# if !defined(AP_ONLY)
# if !defined(AP_ONLY) && defined (AHOY_MQTT_SUPPORT)
mMqttEnabled = ( mConfig - > mqtt . broker [ 0 ] > 0 ) ;
if ( mMqttEnabled ) {
mMqtt . setup ( & mConfig - > mqtt , mConfig - > sys . deviceName , mVersion , & mSys , & mTimestamp ) ;
@ -84,8 +95,11 @@ void app::setup() {
mPubSerial . setup ( mConfig , & mSys , & mTimestamp ) ;
regularTickers ( ) ;
# ifdef AHOY_SML_OBIS_SUPPORT
sml_setup ( this , & mTimestamp ) ;
# endif
regularTickers ( ) ;
// DBGPRINTLN("--- end setup");
// DBGPRINTLN(String(ESP.getFreeHeap()));
@ -109,11 +123,16 @@ void app::loopStandard(void) {
if ( mConfig - > serial . debug ) {
DPRINT ( DBG_INFO , F ( " RX " ) ) ;
DBGPRINT ( String ( p - > len ) ) ;
# ifdef undef
DBGPRINT ( F ( " B Ch " ) ) ;
DBGPRINT ( String ( p - > ch ) ) ;
DBGPRINT ( F ( " | " ) ) ;
mSys . Radio . dumpBuf ( p - > packet , p - > len ) ;
# else
DBGPRINTLN ( " Bytes " ) ;
# endif
}
mStat . frmCnt + + ;
Inverter < > * iv = mSys . findInverter ( & p - > packet [ 1 ] ) ;
@ -132,8 +151,15 @@ void app::loopStandard(void) {
mPayload . loop ( ) ;
mMiPayload . loop ( ) ;
if ( mMqttEnabled )
# ifdef AHOY_MQTT_SUPPORT
if ( mMqttEnabled ) {
mMqtt . loop ( ) ;
}
# endif
# ifdef AHOY_SML_OBIS_SUPPORT
sml_loop ( ) ;
# endif
}
//-----------------------------------------------------------------------------
@ -150,11 +176,15 @@ void app::onWifi(bool gotIp) {
if ( gotIp ) {
mInnerLoopCb = std : : bind ( & app : : loopStandard , this ) ;
every ( std : : bind ( & app : : tickSend , this ) , mConfig - > nrf . sendInterval , " tSend " ) ;
mMqttReconnect = true ;
mSunrise = 0 ; // needs to be set to 0, to reinstall sunrise and ivComm tickers!
once ( std : : bind ( & app : : tickNtpUpdate , this ) , 2 , " ntp2 " ) ;
if ( WIFI_AP = = WiFi . getMode ( ) ) {
# ifdef AHOY_MQTT_SUPPORT
mMqttEnabled = false ;
# endif
everySec ( std : : bind ( & ahoywifi : : tickWifiLoop , & mWifi ) , " wifiL " ) ;
}
} else {
@ -178,21 +208,27 @@ void app::tickNtpUpdate(void) {
uint32_t nxtTrig = 5 ; // default: check again in 5 sec
bool isOK = mWifi . getNtpTime ( ) ;
if ( isOK | | mTimestamp ! = 0 ) {
# ifdef AHOY_MQTT_SUPPORT
if ( mMqttReconnect & & mMqttEnabled ) {
mMqtt . tickerSecond ( ) ;
everySec ( std : : bind ( & PubMqttType : : tickerSecond , & mMqtt ) , " mqttS " ) ;
everyMin ( std : : bind ( & PubMqttType : : tickerMinute , & mMqtt ) , " mqttM " ) ;
}
# endif
// only install schedulers once even if NTP wasn't successful in first loop
if ( mMqttReconnect ) { // @TODO: mMqttReconnect is variable which scope has changed
if ( mConfig - > inst . rstValsNotAvail )
everyMin ( std : : bind ( & app : : tickMinute , this ) , " tMin " ) ;
if ( mConfig - > inst . rstYieldMidNight ) {
uint32_t localTime = gTimezone . toLocal ( mTimestamp ) ;
uint32_t midTrig = gTimezone . toUTC ( localTime - ( localTime % 86400 ) + 86400 ) ; // next midnight local time
onceAt ( std : : bind ( & app : : tickMidnight , this ) , midTrig , " midNi " ) ;
}
mSys . cleanup_history ( ) ;
# ifdef AHOY_SML_OBIS_SUPPORT
sml_cleanup_history ( ) ;
# endif
}
nxtTrig = isOK ? 43200 : 60 ; // depending on NTP update success check again in 12 h or in 1 min
@ -226,8 +262,10 @@ void app::tickCalcSunrise(void) {
uint32_t nxtTrig = mSunset + mConfig - > sun . offsetSec + 60 ; // set next trigger to communication stop, +60 for safety that it is certain past communication stop
onceAt ( std : : bind ( & app : : tickCalcSunrise , this ) , nxtTrig , " Sunri " ) ;
# ifdef AHOY_MQTT_SUPPORT
if ( mMqttEnabled )
tickSun ( ) ;
# endif
}
//-----------------------------------------------------------------------------
@ -251,22 +289,26 @@ void app::tickIVCommunication(void) {
tickComm ( ) ;
}
# ifdef AHOY_MQTT_SUPPORT
//-----------------------------------------------------------------------------
void app : : tickSun ( void ) {
// only used and enabled by MQTT (see setup())
if ( ! mMqtt . tickerSun ( mSunrise , mSunset , mConfig - > sun . offsetSec , mConfig - > sun . disNightCom ) )
once ( std : : bind ( & app : : tickSun , this ) , 1 , " mqSun " ) ; // MQTT not connected, retry
}
# endif
//-----------------------------------------------------------------------------
void app : : tickComm ( void ) {
if ( ( ! mIVCommunicationOn ) & & ( mConfig - > inst . rstValsCommStop ) )
once ( std : : bind ( & app : : tickZeroValues , this ) , mConfig - > nrf . sendInterval , " tZero " ) ;
# ifdef AHOY_MQTT_SUPPORT
if ( mMqttEnabled ) {
if ( ! mMqtt . tickerComm ( ! mIVCommunicationOn ) )
once ( std : : bind ( & app : : tickComm , this ) , 5 , " mqCom " ) ; // MQTT not connected, retry after 5s
}
# endif
}
//-----------------------------------------------------------------------------
@ -300,7 +342,8 @@ void app::tickMinute(void) {
//-----------------------------------------------------------------------------
void app : : tickMidnight ( void ) {
// only triggered if 'reset values at midnight is enabled'
if ( mConfig - > inst . rstYieldMidNight ) {
// only if 'reset values at midnight is enabled'
uint32_t localTime = gTimezone . toLocal ( mTimestamp ) ;
uint32_t nxtTrig = gTimezone . toUTC ( localTime - ( localTime % 86400 ) + 86400 ) ; // next midnight local time
onceAt ( std : : bind ( & app : : tickMidnight , this ) , nxtTrig , " mid2 " ) ;
@ -315,9 +358,15 @@ void app::tickMidnight(void) {
mPayload . zeroInverterValues ( iv ) ;
mPayload . zeroYieldDay ( iv ) ;
}
# ifdef AHOY_MQTT_SUPPORT
if ( mMqttEnabled )
mMqtt . tickerMidnight ( ) ;
# endif
}
mSys . cleanup_history ( ) ;
# ifdef AHOY_SML_OBIS_SUPPORT
sml_cleanup_history ( ) ;
# endif
}
//-----------------------------------------------------------------------------
@ -329,7 +378,7 @@ void app::tickSend(void) {
if ( mIVCommunicationOn ) {
if ( ! mSys . Radio . mBufCtrl . empty ( ) ) {
if ( mConfig - > serial . debug ) {
DPRINT ( DBG_DEBUG , F ( " recbuf not empty! # " ) ) ;
DPRINT ( DBG_INFO , F ( " recbuf not empty! # " ) ) ;
DBGPRINTLN ( String ( mSys . Radio . mBufCtrl . size ( ) ) ) ;
}
}
@ -347,7 +396,11 @@ void app::tickSend(void) {
mPayload . ivSend ( iv ) ;
else
mMiPayload . ivSend ( iv ) ;
} else {
DPRINTLN ( DBG_INFO , " iv not enabled " ) ;
}
} else {
DPRINTLN ( DBG_INFO , " no inverter " ) ;
}
} else {
if ( mConfig - > serial . debug )
@ -371,7 +424,9 @@ void app::resetSystem(void) {
mSunrise = 0 ;
mSunset = 0 ;
# ifdef AHOY_MQTT_SUPPORT
mMqttEnabled = false ;
# endif
mSendLastIvId = 0 ;
mShowRebootRequest = false ;
@ -382,10 +437,12 @@ void app::resetSystem(void) {
memset ( & mStat , 0 , sizeof ( statistics_t ) ) ;
}
# ifdef AHOY_MQTT_SUPPORT
//-----------------------------------------------------------------------------
void app : : mqttSubRxCb ( JsonObject obj ) {
mApi . ctrlRequest ( obj ) ;
}
# endif
//-----------------------------------------------------------------------------
void app : : setupLed ( void ) {
@ -416,6 +473,7 @@ void app::updateLed(void) {
}
}
# ifdef AHOY_MQTT_SUPPORT
if ( mConfig - > led . led1 ! = 0xff ) {
if ( getMqttIsConnected ( ) ) {
digitalWrite ( mConfig - > led . led1 , led_on ) ;
@ -423,4 +481,41 @@ void app::updateLed(void) {
digitalWrite ( mConfig - > led . led1 , led_off ) ;
}
}
# endif
}
//-----------------------------------------------------------------------------
void app : : check_hist_file ( File file )
{
if ( file ) {
uint16_t exp_index = AHOY_MIN_PAC_SUN_HOUR * 60 / AHOY_PAC_INTERVAL , index ;
unsigned char data [ 4 ] ;
while ( file . read ( data , sizeof ( data ) ) = = sizeof ( data ) ) {
index = data [ 0 ] + ( data [ 1 ] < < 8 ) ;
if ( index ! = exp_index ) {
DPRINTLN ( DBG_WARN , " Unexpected " + String ( index ) + " <-> " + String ( exp_index ) ) ;
}
exp_index = index + 1 ;
}
file . close ( ) ;
}
}
//-----------------------------------------------------------------------------
void app : : show_history ( String path )
{
Dir dir = LittleFS . openDir ( path ) ;
DPRINTLN ( DBG_INFO , " Enter Dir: " + path ) ;
while ( dir . next ( ) ) {
if ( dir . isDirectory ( ) ) {
show_history ( path + " / " + dir . fileName ( ) ) ;
} else {
DPRINTLN ( DBG_INFO , " file " + dir . fileName ( ) +
" , Size: " + String ( dir . fileSize ( ) ) ) ;
check_hist_file ( dir . openFile ( " r " ) ) ;
}
}
DPRINTLN ( DBG_INFO , " Leave Dir: " + path ) ;
}