2017-05-20 13:03:34 +01:00
/*
2017-11-07 14:57:24 +00:00
xsns_01_counter . ino - Counter sensors ( water meters , electricity meters etc . ) sensor support for Sonoff - Tasmota
2017-05-20 13:03:34 +01:00
2017-12-22 13:55:24 +00:00
Copyright ( C ) 2018 Maarten Damen and Theo Arends
2017-05-20 13:03:34 +01:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
/*********************************************************************************************\
* Counter sensors ( water meters , electricity meters etc . )
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-08-09 12:24:13 +01:00
unsigned long last_counter_timer [ MAX_COUNTERS ] ; // Last counter time in micro seconds
2017-05-20 13:03:34 +01:00
2017-10-18 17:22:34 +01:00
void CounterUpdate ( byte index )
2017-05-20 13:03:34 +01:00
{
2018-08-09 12:24:13 +01:00
unsigned long counter_debounce_time = micros ( ) - last_counter_timer [ index - 1 ] ;
if ( counter_debounce_time > Settings . pulse_counter_debounce * 1000 ) {
last_counter_timer [ index - 1 ] = micros ( ) ;
2017-10-18 17:22:34 +01:00
if ( bitRead ( Settings . pulse_counter_type , index - 1 ) ) {
RtcSettings . pulse_counter [ index - 1 ] = counter_debounce_time ;
2017-05-20 13:03:34 +01:00
} else {
2017-10-18 17:22:34 +01:00
RtcSettings . pulse_counter [ index - 1 ] + + ;
2017-05-20 13:03:34 +01:00
}
2017-09-13 13:19:34 +01:00
// snprintf_P(log_data, sizeof(log_data), PSTR("CNTR: Interrupt %d"), index);
2017-10-18 17:22:34 +01:00
// AddLog(LOG_LEVEL_DEBUG);
2017-05-20 13:03:34 +01:00
}
}
2017-10-18 17:22:34 +01:00
void CounterUpdate1 ( )
2017-05-20 13:03:34 +01:00
{
2017-10-18 17:22:34 +01:00
CounterUpdate ( 1 ) ;
2017-05-20 13:03:34 +01:00
}
2017-10-18 17:22:34 +01:00
void CounterUpdate2 ( )
2017-05-20 13:03:34 +01:00
{
2017-10-18 17:22:34 +01:00
CounterUpdate ( 2 ) ;
2017-05-20 13:03:34 +01:00
}
2017-10-18 17:22:34 +01:00
void CounterUpdate3 ( )
2017-05-20 13:03:34 +01:00
{
2017-10-18 17:22:34 +01:00
CounterUpdate ( 3 ) ;
2017-05-20 13:03:34 +01:00
}
2017-10-18 17:22:34 +01:00
void CounterUpdate4 ( )
2017-05-20 13:03:34 +01:00
{
2017-10-18 17:22:34 +01:00
CounterUpdate ( 4 ) ;
2017-05-20 13:03:34 +01:00
}
2017-12-16 19:11:12 +00:00
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void CounterSaveState ( )
2017-05-20 13:03:34 +01:00
{
for ( byte i = 0 ; i < MAX_COUNTERS ; i + + ) {
if ( pin [ GPIO_CNTR1 + i ] < 99 ) {
2017-10-18 17:22:34 +01:00
Settings . pulse_counter [ i ] = RtcSettings . pulse_counter [ i ] ;
2017-05-20 13:03:34 +01:00
}
}
}
2017-10-18 17:22:34 +01:00
void CounterInit ( )
2017-05-20 13:03:34 +01:00
{
typedef void ( * function ) ( ) ;
2017-10-18 17:22:34 +01:00
function counter_callbacks [ ] = { CounterUpdate1 , CounterUpdate2 , CounterUpdate3 , CounterUpdate4 } ;
2017-09-02 13:37:02 +01:00
2017-05-20 13:03:34 +01:00
for ( byte i = 0 ; i < MAX_COUNTERS ; i + + ) {
if ( pin [ GPIO_CNTR1 + i ] < 99 ) {
pinMode ( pin [ GPIO_CNTR1 + i ] , INPUT_PULLUP ) ;
attachInterrupt ( pin [ GPIO_CNTR1 + i ] , counter_callbacks [ i ] , FALLING ) ;
}
}
}
2017-11-04 15:36:51 +00:00
# ifdef USE_WEBSERVER
const char HTTP_SNS_COUNTER [ ] PROGMEM =
" %s{s} " D_COUNTER " %d{m}%s%s{e} " ; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
# endif // USE_WEBSERVER
2017-05-20 13:03:34 +01:00
2017-11-04 15:36:51 +00:00
void CounterShow ( boolean json )
2017-05-20 13:03:34 +01:00
{
2018-04-28 14:55:38 +01:00
char stemp [ 10 ] ;
2017-11-04 15:36:51 +00:00
char counter [ 16 ] ;
2017-05-20 13:03:34 +01:00
byte dsxflg = 0 ;
2018-04-28 14:55:38 +01:00
byte header = 0 ;
2017-05-20 13:03:34 +01:00
for ( byte i = 0 ; i < MAX_COUNTERS ; i + + ) {
if ( pin [ GPIO_CNTR1 + i ] < 99 ) {
2017-10-18 17:22:34 +01:00
if ( bitRead ( Settings . pulse_counter_type , i ) ) {
2018-08-09 12:24:13 +01:00
dtostrfd ( ( double ) RtcSettings . pulse_counter [ i ] / 1000000 , 6 , counter ) ;
2017-05-20 13:03:34 +01:00
} else {
dsxflg + + ;
2017-11-04 15:36:51 +00:00
dtostrfd ( RtcSettings . pulse_counter [ i ] , 0 , counter ) ;
2017-05-20 13:03:34 +01:00
}
2017-11-04 15:36:51 +00:00
if ( json ) {
2018-04-28 14:55:38 +01:00
if ( ! header ) {
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" COUNTER \" :{ " ) , mqtt_data ) ;
stemp [ 0 ] = ' \0 ' ;
}
header + + ;
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s%s \" C%d \" :%s " ) , mqtt_data , stemp , i + 1 , counter ) ;
strcpy ( stemp , " , " ) ;
2017-05-20 13:03:34 +01:00
# ifdef USE_DOMOTICZ
2018-04-11 09:11:20 +01:00
if ( ( 0 = = tele_period ) & & ( 1 = = dsxflg ) ) {
2017-11-04 15:36:51 +00:00
DomoticzSensor ( DZ_COUNT , RtcSettings . pulse_counter [ i ] ) ;
dsxflg + + ;
}
2017-05-20 13:03:34 +01:00
# endif // USE_DOMOTICZ
# ifdef USE_WEBSERVER
} else {
2017-11-04 15:36:51 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , HTTP_SNS_COUNTER , mqtt_data , i + 1 , counter , ( bitRead ( Settings . pulse_counter_type , i ) ) ? " " D_UNIT_SECOND : " " ) ;
# endif // USE_WEBSERVER
2017-05-20 13:03:34 +01:00
}
}
2018-08-09 12:24:13 +01:00
if ( bitRead ( Settings . pulse_counter_type , i ) ) RtcSettings . pulse_counter [ i ] = 0xFFFFFFFF ; // Set Timer to max in case of no more interrupts due to stall of measured device
2017-05-20 13:03:34 +01:00
}
2018-04-28 14:55:38 +01:00
if ( json ) {
if ( header ) {
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s} " ) , mqtt_data ) ;
}
}
2017-05-20 13:03:34 +01:00
}
2017-11-03 17:07:25 +00:00
/*********************************************************************************************\
* Interface
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define XSNS_01
boolean Xsns01 ( byte function )
{
boolean result = false ;
switch ( function ) {
2017-12-25 16:41:12 +00:00
case FUNC_INIT :
2017-11-03 17:07:25 +00:00
CounterInit ( ) ;
break ;
2017-12-25 16:41:12 +00:00
case FUNC_JSON_APPEND :
2017-11-04 15:36:51 +00:00
CounterShow ( 1 ) ;
2017-11-03 17:07:25 +00:00
break ;
# ifdef USE_WEBSERVER
2017-12-25 16:41:12 +00:00
case FUNC_WEB_APPEND :
2017-11-04 15:36:51 +00:00
CounterShow ( 0 ) ;
2017-11-03 17:07:25 +00:00
break ;
# endif // USE_WEBSERVER
2017-12-25 16:41:12 +00:00
case FUNC_SAVE_BEFORE_RESTART :
2017-12-16 19:11:12 +00:00
CounterSaveState ( ) ;
break ;
2017-11-03 17:07:25 +00:00
}
return result ;
}