mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 18:56:38 +00:00
6.3.0.17 Add features
6.3.0.17 20181211 * Add support for TheoV2 sensors as documented on https://sidweb.nl * Add support for SDM220 (#3610) * Enhance support for MPU6050 using DMP (#4581)
This commit is contained in:
parent
a913c4459a
commit
67ec0678a3
@ -1,4 +1,9 @@
|
||||
/* 6.3.0.16 20181201
|
||||
/* 6.3.0.17 20181211
|
||||
* Add support for TheoV2 sensors as documented on https://sidweb.nl
|
||||
* Add support for SDM220 (#3610)
|
||||
* Enhance support for MPU6050 using DMP (#4581)
|
||||
*
|
||||
* 6.3.0.16 20181201
|
||||
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
|
||||
* Add Announce Switches to MQTT Discovery (#4531)
|
||||
* Update MCP230xx driver to support interrupt retention over teleperiod (#4547)
|
||||
|
@ -49,12 +49,6 @@
|
||||
#define D_JSON_COUNT "Count"
|
||||
#define D_JSON_COUNTER "Counter"
|
||||
#define D_JSON_CURRENT "Current" // As in Voltage and Current
|
||||
#define D_JSON_PHASE_ANGLE "Phase angle"
|
||||
#define D_JSON_IMPORT_ACTIVE "Import Active Power"
|
||||
#define D_JSON_EXPORT_ACTIVE "Export Active Power"
|
||||
#define D_JSON_IMPORT_REACTIVE "Import Reactive Power"
|
||||
#define D_JSON_EXPORT_REACTIVE "Export Reactive Power"
|
||||
#define D_JSON_TOTAL_REACTIVE "Total Reactive Power"
|
||||
#define D_JSON_DATA "Data"
|
||||
#define D_JSON_DISTANCE "Distance"
|
||||
#define D_JSON_DNSSERVER "DNSServer"
|
||||
@ -65,6 +59,8 @@
|
||||
#define D_JSON_ERASE "Erase"
|
||||
#define D_JSON_ERROR "Error"
|
||||
#define D_JSON_EVERY "Every"
|
||||
#define D_JSON_EXPORT_ACTIVE "ExportActivePower"
|
||||
#define D_JSON_EXPORT_REACTIVE "ExportReactivePower"
|
||||
#define D_JSON_FAILED "Failed"
|
||||
#define D_JSON_FALLBACKTOPIC "FallbackTopic"
|
||||
#define D_JSON_FEATURES "Features"
|
||||
@ -86,6 +82,8 @@
|
||||
#define D_JSON_I2CSCAN_NO_DEVICES_FOUND "No devices found"
|
||||
#define D_JSON_ID "Id"
|
||||
#define D_JSON_ILLUMINANCE "Illuminance"
|
||||
#define D_JSON_IMPORT_ACTIVE "ImportActivePower"
|
||||
#define D_JSON_IMPORT_REACTIVE "ImportReactivePower"
|
||||
#define D_JSON_INFRARED "Infrared"
|
||||
#define D_JSON_UNKNOWN "Unknown"
|
||||
#define D_JSON_LIGHT "Light"
|
||||
@ -99,6 +97,7 @@
|
||||
#define D_JSON_NONE "None"
|
||||
#define D_JSON_OR "or"
|
||||
#define D_JSON_PERIOD "Period"
|
||||
#define D_JSON_PHASE_ANGLE "PhaseAngle"
|
||||
#define D_JSON_POWERFACTOR "Factor"
|
||||
#define D_JSON_POWERUSAGE "Power"
|
||||
#define D_JSON_ACTIVE_POWERUSAGE "ActivePower"
|
||||
@ -135,6 +134,7 @@
|
||||
#define D_JSON_TIME "Time"
|
||||
#define D_JSON_TODAY "Today"
|
||||
#define D_JSON_TOTAL "Total"
|
||||
#define D_JSON_TOTAL_REACTIVE "TotalReactivePower"
|
||||
#define D_JSON_TOTAL_START_TIME "TotalStartTime"
|
||||
#define D_JSON_TVOC "TVOC"
|
||||
#define D_JSON_TYPE "Type"
|
||||
@ -546,6 +546,7 @@ const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}";
|
||||
const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
|
||||
#if defined(USE_MHZ19) || defined(USE_SENSEAIR)
|
||||
const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,7 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
@ -594,6 +594,7 @@
|
||||
#define D_LOG_UPNP "UPP: " // UPnP
|
||||
#define D_LOG_WIFI "WIF: " // Wifi
|
||||
|
||||
//SDM220
|
||||
#define D_PHASE_ANGLE "Phase Angle"
|
||||
#define D_IMPORT_ACTIVE "Import Active"
|
||||
#define D_EXPORT_ACTIVE "Export Active"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,7 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -536,7 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
@ -594,6 +594,7 @@
|
||||
#define D_LOG_UPNP "UPP: " // UPnP
|
||||
#define D_LOG_WIFI "WIF: " // Wifi
|
||||
|
||||
//SDM220
|
||||
#define D_PHASE_ANGLE "Phase Angle"
|
||||
#define D_IMPORT_ACTIVE "Import Active"
|
||||
#define D_EXPORT_ACTIVE "Export Active"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -536,6 +536,7 @@
|
||||
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
|
||||
#define D_SENSOR_SSPI_CS "SSPI CS"
|
||||
#define D_SENSOR_SSPI_DC "SSPI DC"
|
||||
#define D_SENSOR_RF_SENSOR "RF Sensor"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -357,7 +357,7 @@
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
|
||||
#define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
||||
#define USE_SDM220 // add extra parameters for SDM220 (+0k1 code)
|
||||
#define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code)
|
||||
//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
||||
#define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud)
|
||||
//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
|
||||
@ -399,6 +399,10 @@
|
||||
|
||||
#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram)
|
||||
|
||||
//#define USE_RF_SENSOR // Add support for RF (434MHz or 868MHz) receiver (+2k code)
|
||||
// #define USE_THEO_V2 // Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl
|
||||
// #define USE_ALECTO_V2 // Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Debug features are only supported in development branch
|
||||
\*********************************************************************************************/
|
||||
|
@ -2766,6 +2766,7 @@ void loop(void)
|
||||
uint32_t my_sleep = millis();
|
||||
|
||||
XdrvCall(FUNC_LOOP);
|
||||
XsnsCall(FUNC_LOOP);
|
||||
|
||||
OsWatchLoop();
|
||||
|
||||
|
@ -140,6 +140,7 @@ enum UserSelectablePins {
|
||||
GPIO_SSPI_SCLK, // Software SPI Serial Clock
|
||||
GPIO_SSPI_CS, // Software SPI Chip Select
|
||||
GPIO_SSPI_DC, // Software SPI Data or Command
|
||||
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
@ -199,7 +200,8 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
|
||||
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
|
||||
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|"
|
||||
D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC;
|
||||
D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|"
|
||||
D_SENSOR_RF_SENSOR;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
@ -382,6 +384,9 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_RFSEND, // RF transmitter
|
||||
GPIO_RFRECV, // RF receiver
|
||||
#endif
|
||||
#ifdef USE_RF_SENSOR
|
||||
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
|
||||
#endif
|
||||
#ifdef USE_SR04
|
||||
GPIO_SR04_TRIG, // SR04 Trigger pin
|
||||
GPIO_SR04_ECHO, // SR04 Echo pin
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
#define VERSION 0x06030010
|
||||
#define VERSION 0x06030011
|
||||
|
||||
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
||||
#define D_AUTHOR "Theo Arends"
|
||||
|
@ -361,10 +361,15 @@ void GetFeatures(void)
|
||||
#ifdef USE_MGC3130
|
||||
feature_sns2 |= 0x00004000; // xsns_36_mgc3130.ino
|
||||
#endif
|
||||
|
||||
// feature_sns2 |= 0x00008000;
|
||||
// feature_sns2 |= 0x00010000;
|
||||
// feature_sns2 |= 0x00020000;
|
||||
#ifdef USE_RF_SENSOR
|
||||
feature_sns2 |= 0x00008000; // xsns_37_rfsensor.ino
|
||||
#endif
|
||||
#ifdef USE_THEO_V2
|
||||
feature_sns2 |= 0x00010000;
|
||||
#endif
|
||||
#ifdef USE_ALECTO_V2
|
||||
feature_sns2 |= 0x00020000;
|
||||
#endif
|
||||
// feature_sns2 |= 0x00040000;
|
||||
// feature_sns2 |= 0x00080000;
|
||||
// feature_sns2 |= 0x00100000;
|
||||
|
@ -87,6 +87,20 @@ String GetTimeZone(void)
|
||||
return String(tz); // -03:45
|
||||
}
|
||||
|
||||
String GetDT(uint32_t time)
|
||||
{
|
||||
// "2017-03-07T11:08:02" - ISO8601:2004
|
||||
|
||||
char dt[20];
|
||||
TIME_T tmpTime;
|
||||
|
||||
BreakTime(time, tmpTime);
|
||||
snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
|
||||
tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second);
|
||||
|
||||
return String(dt); // 2017-03-07T11:08:02
|
||||
}
|
||||
|
||||
/*
|
||||
* timestamps in https://en.wikipedia.org/wiki/ISO_8601 format
|
||||
*
|
||||
@ -101,39 +115,27 @@ String GetTimeZone(void)
|
||||
String GetDateAndTime(byte time_type)
|
||||
{
|
||||
// "2017-03-07T11:08:02-07:00" - ISO8601:2004
|
||||
char dt[27];
|
||||
TIME_T tmpTime;
|
||||
uint32_t time = local_time;
|
||||
|
||||
switch (time_type) {
|
||||
case DT_ENERGY:
|
||||
BreakTime(Settings.energy_kWhtotal_time, tmpTime);
|
||||
tmpTime.year += 1970;
|
||||
time = Settings.energy_kWhtotal_time;
|
||||
break;
|
||||
case DT_UTC:
|
||||
BreakTime(utc_time, tmpTime);
|
||||
tmpTime.year += 1970;
|
||||
time = utc_time;
|
||||
break;
|
||||
case DT_RESTART:
|
||||
if (restart_time == 0) {
|
||||
return "";
|
||||
}
|
||||
BreakTime(restart_time, tmpTime);
|
||||
tmpTime.year += 1970;
|
||||
time = restart_time;
|
||||
break;
|
||||
default:
|
||||
tmpTime = RtcTime;
|
||||
}
|
||||
|
||||
|
||||
snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
|
||||
tmpTime.year, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second);
|
||||
|
||||
String dt = GetDT(time); // 2017-03-07T11:08:02
|
||||
if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) {
|
||||
// if (Settings.flag3.time_append_timezone && ((DT_LOCAL == time_type) || (DT_ENERGY == time_type))) {
|
||||
strncat(dt, GetTimeZone().c_str(), sizeof(dt) - strlen(dt) -1);
|
||||
dt += GetTimeZone(); // 2017-03-07T11:08:02-07:00
|
||||
}
|
||||
|
||||
return String(dt); // 2017-03-07T11:08:02-07:00
|
||||
return dt; // 2017-03-07T11:08:02-07:00
|
||||
}
|
||||
|
||||
String GetTime(int type)
|
||||
|
@ -89,11 +89,6 @@ void Bh1750EverySecond(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_ILLUMINANCE[] PROGMEM =
|
||||
"%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void Bh1750Show(boolean json)
|
||||
{
|
||||
if (bh1750_valid) {
|
||||
|
634
sonoff/xsns_37_rfsensor.ino
Normal file
634
sonoff/xsns_37_rfsensor.ino
Normal file
@ -0,0 +1,634 @@
|
||||
/*
|
||||
xsns_37_rfsensor.ino - RF sensor receiver for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_RF_SENSOR
|
||||
/*********************************************************************************************\
|
||||
* RF receive based on work by Paul Tonkes (www.nodo-domotica.nl)
|
||||
*
|
||||
* USE_THEO_V2 Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl
|
||||
* USE_ALECTO_V2 Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_37 37
|
||||
|
||||
//#define USE_THEO_V2 // Add support for 434MHz Theo V2 sensors as documented on https://sidweb.nl
|
||||
//#define USE_ALECTO_V2 // Add support for 868MHz Alecto V2 sensors like ACH2010, WS3000 and DKW2012
|
||||
|
||||
#define RFSNS_VALID_WINDOW 1800 // Number of seconds for sensor to respond (1800 = 30 minutes)
|
||||
|
||||
#define RFSNS_LOOPS_PER_MILLI 1900 // (345 voor 16MHz ATMega) Voor 80MHz NodeMCU (ESP-12E). Getest met TheoV2 Protocol.
|
||||
#define RFSNS_RAW_BUFFER_SIZE 180 // (256) Maximum number of RF pulses that can be captured
|
||||
#define RFSNS_MIN_RAW_PULSES 112 // (16) =8 bits. Minimaal aantal ontvangen bits*2 alvorens cpu tijd wordt besteed aan decodering, etc.
|
||||
// Zet zo hoog mogelijk om CPU-tijd te sparen en minder 'onzin' te ontvangen.
|
||||
#define RFSNS_MIN_PULSE_LENGTH 300 // (50) Pulsen korter dan deze tijd uSec. worden als stoorpulsen beschouwd.
|
||||
#define RFSNS_RAWSIGNAL_SAMPLE 50 // Sample grootte / Resolutie in uSec waarmee ontvangen Rawsignalen pulsen worden opgeslagen
|
||||
#define RFSNS_SIGNAL_TIMEOUT 10 // Pulse timings in mSec. Beyond this value indicate end of message
|
||||
#define RFSNS_SIGNAL_REPEAT_TIME 500 // (500) Tijd in mSec. waarbinnen hetzelfde event niet nogmaals via RF mag binnenkomen. Onderdrukt ongewenste herhalingen van signaal
|
||||
|
||||
struct RawSignalStruct // Variabelen geplaatst in struct zodat deze later eenvoudig kunnen worden weggeschreven naar SDCard
|
||||
{
|
||||
int Number; // aantal bits, maal twee omdat iedere bit een mark en een space heeft.
|
||||
byte Repeats; // Aantal maal dat de pulsreeks verzonden moet worden bij een zendactie.
|
||||
byte Multiply; // Pulses[] * Multiply is de echte tijd van een puls in microseconden
|
||||
unsigned long Time; // Tijdstempel wanneer signaal is binnengekomen (millis())
|
||||
byte Pulses[RFSNS_RAW_BUFFER_SIZE+2]; // Tabel met de gemeten pulsen in microseconden gedeeld door rfsns_raw_signal.Multiply. Dit scheelt helft aan RAM geheugen.
|
||||
// Om legacy redenen zit de eerste puls in element 1. Element 0 wordt dus niet gebruikt.
|
||||
} rfsns_raw_signal = {0, 0, 0, 0L};
|
||||
|
||||
uint8_t rfsns_rf_bit;
|
||||
uint8_t rfsns_rf_port;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Fetch signals from RF pin
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean RfSnsFetchSignal(byte DataPin, boolean StateSignal)
|
||||
{
|
||||
uint8_t Fbit = digitalPinToBitMask(DataPin);
|
||||
uint8_t Fport = digitalPinToPort(DataPin);
|
||||
uint8_t FstateMask = (StateSignal ? Fbit : 0);
|
||||
|
||||
if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is
|
||||
const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI;
|
||||
|
||||
// Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze
|
||||
// routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit
|
||||
// geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte
|
||||
// rust tussen de signalen. Op deze wijze wordt het aantal zinloze captures teruggebracht.
|
||||
|
||||
unsigned long PulseLength = 0;
|
||||
if (rfsns_raw_signal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel...
|
||||
if (rfsns_raw_signal.Repeats && (rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { // ...want deze check duurt enkele micro's langer!
|
||||
PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; // Wachttijd
|
||||
while (((rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) {
|
||||
if ((*portInputRegister(Fport) & Fbit) == FstateMask) {
|
||||
PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000;
|
||||
}
|
||||
}
|
||||
while (((rfsns_raw_signal.Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask));
|
||||
}
|
||||
}
|
||||
|
||||
int RawCodeLength = 1; // We starten bij 1, dit om legacy redenen. Vroeger had element 0 een speciaal doel.
|
||||
bool Ftoggle = false;
|
||||
unsigned long numloops = 0;
|
||||
unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli;
|
||||
rfsns_raw_signal.Multiply = RFSNS_RAWSIGNAL_SAMPLE; // Ingestelde sample groote.
|
||||
do { // lees de pulsen in microseconden en plaats deze in de tijdelijke buffer rfsns_raw_signal
|
||||
numloops = 0;
|
||||
while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { // while() loop *A*
|
||||
if (numloops++ == maxloops) { break; } // timeout opgetreden
|
||||
}
|
||||
PulseLength = (numloops *1000) / LoopsPerMilli; // Bevat nu de pulslengte in microseconden
|
||||
if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; }
|
||||
Ftoggle = !Ftoggle;
|
||||
rfsns_raw_signal.Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal.Multiply; // sla op in de tabel rfsns_raw_signal
|
||||
}
|
||||
while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); // Zolang nog ruimte in de buffer, geen timeout en geen stoorpuls
|
||||
|
||||
if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) {
|
||||
rfsns_raw_signal.Repeats = 0; // Op dit moment weten we nog niet het type signaal, maar de variabele niet ongedefinieerd laten.
|
||||
rfsns_raw_signal.Number = RawCodeLength -1; // Aantal ontvangen tijden (pulsen *2)
|
||||
rfsns_raw_signal.Pulses[rfsns_raw_signal.Number] = 0; // Laatste element bevat de timeout. Niet relevant.
|
||||
rfsns_raw_signal.Time = millis();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
rfsns_raw_signal.Number = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_THEO_V2
|
||||
/*********************************************************************************************\
|
||||
* Theo V2 protocol
|
||||
* Dit protocol zorgt voor ontvangst van Theo sensoren met protocol V2
|
||||
*
|
||||
* Auteur : Theo Arends
|
||||
* Support : www.sidweb.nl
|
||||
* Datum : 17 Apr 2014
|
||||
* Versie : 0.1 - Initiele versie
|
||||
**********************************************************************************************
|
||||
* Technische informatie:
|
||||
*
|
||||
* Theo Sensor V2 type 1 Message Format (7 Bytes, 57 bits):
|
||||
* Checksum Type Chl BsVoltag Temperature Light
|
||||
* S AAAAAAAA BBBBBCCC DEFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH HHHHHHHH
|
||||
* idx: 0 1 2 3 4 5 6
|
||||
*
|
||||
* Theo Sensor V2 type 2 Message Format (7 Bytes, 57 bits):
|
||||
* Checksum Type Chl BsVoltag Temperature Humidity
|
||||
* S AAAAAAAA BBBBBCCC DEFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH HHHHHHHH
|
||||
* idx: 0 1 2 3 4 5 6
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define RFSNS_THEOV2_MAX_CHANNEL 2 // Max number of ATTiny sensor channels supported
|
||||
|
||||
#define RFSNS_THEOV2_PULSECOUNT 114
|
||||
#define RFSNS_THEOV2_RF_PULSE_MID 1000 // PWM: Pulsen langer zijn '1'
|
||||
|
||||
typedef struct {
|
||||
uint32_t time;
|
||||
int16_t temp;
|
||||
uint16_t lux;
|
||||
uint8_t volt;
|
||||
} theo_v2_t1_t;
|
||||
|
||||
theo_v2_t1_t rfsns_theo_v2_t1[RFSNS_THEOV2_MAX_CHANNEL];
|
||||
|
||||
typedef struct {
|
||||
uint32_t time;
|
||||
int16_t temp;
|
||||
uint16_t hum;
|
||||
uint8_t volt;
|
||||
} theo_v2_t2_t;
|
||||
|
||||
theo_v2_t2_t rfsns_theo_v2_t2[RFSNS_THEOV2_MAX_CHANNEL];
|
||||
|
||||
boolean RfSnsAnalyzeTheov2(void)
|
||||
{
|
||||
if (rfsns_raw_signal.Number != RFSNS_THEOV2_PULSECOUNT) return false;
|
||||
|
||||
byte Checksum; // 8 bits Checksum over following bytes
|
||||
byte Channel; // 3 bits channel
|
||||
byte Type; // 5 bits type
|
||||
byte Voltage; // 8 bits Vcc like 45 = 4.5V, bit 8 is batt low
|
||||
int Payload1; // 16 bits
|
||||
int Payload2; // 16 bits
|
||||
|
||||
byte b, bytes, bits, id;
|
||||
char log[128];
|
||||
|
||||
byte idx = 3;
|
||||
byte chksum = 0;
|
||||
for (bytes = 0; bytes < 7; bytes++) {
|
||||
b = 0;
|
||||
for (bits = 0; bits <= 7; bits++)
|
||||
{
|
||||
if ((rfsns_raw_signal.Pulses[idx] * rfsns_raw_signal.Multiply) > RFSNS_THEOV2_RF_PULSE_MID) {
|
||||
b |= 1 << bits;
|
||||
}
|
||||
idx += 2;
|
||||
}
|
||||
if (bytes > 0) { chksum += b; } // bereken checksum
|
||||
|
||||
switch (bytes) {
|
||||
case 0:
|
||||
Checksum = b;
|
||||
break;
|
||||
case 1:
|
||||
id = b;
|
||||
Channel = b & 0x7;
|
||||
Type = (b >> 3) & 0x1f;
|
||||
break;
|
||||
case 2:
|
||||
Voltage = b;
|
||||
break;
|
||||
case 3:
|
||||
Payload1 = b;
|
||||
break;
|
||||
case 4:
|
||||
Payload1 = (b << 8) | Payload1;
|
||||
break;
|
||||
case 5:
|
||||
Payload2 = b;
|
||||
break;
|
||||
case 6:
|
||||
Payload2 = (b << 8) | Payload2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Checksum != chksum) { return false; }
|
||||
if (Channel == 0) { return false; }
|
||||
|
||||
rfsns_raw_signal.Repeats = 1; // het is een herhalend signaal. Bij ontvangst herhalingen onderdukken
|
||||
|
||||
int Payload3 = Voltage & 0x3f;
|
||||
Channel--;
|
||||
|
||||
switch (Type) {
|
||||
case 1: // Temp / Lux
|
||||
rfsns_theo_v2_t1[Channel].time = LocalTime();
|
||||
rfsns_theo_v2_t1[Channel].volt = Payload3;
|
||||
rfsns_theo_v2_t1[Channel].temp = Payload1;
|
||||
rfsns_theo_v2_t1[Channel].lux = Payload2;
|
||||
break;
|
||||
case 2: // Temp / Hum
|
||||
rfsns_theo_v2_t2[Channel].time = LocalTime();
|
||||
rfsns_theo_v2_t2[Channel].volt = Payload3;
|
||||
rfsns_theo_v2_t2[Channel].temp = Payload1;
|
||||
rfsns_theo_v2_t2[Channel].hum = Payload2;
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"),
|
||||
chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RfSnsTheoV2Show(boolean json)
|
||||
{
|
||||
bool sensor_once = false;
|
||||
|
||||
for (uint8_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) {
|
||||
if (rfsns_theo_v2_t1[i].time) {
|
||||
char sensor[10];
|
||||
snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1);
|
||||
char voltage[10];
|
||||
dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage);
|
||||
|
||||
if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) {
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"),
|
||||
mqtt_data, sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage);
|
||||
}
|
||||
} else {
|
||||
char temperature[10];
|
||||
dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"),
|
||||
mqtt_data, sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && !sensor_once) {
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux);
|
||||
sensor_once = true;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, sensor, rfsns_theo_v2_t1[i].lux);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sensor_once = false;
|
||||
for (uint8_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) {
|
||||
if (rfsns_theo_v2_t2[i].time) {
|
||||
char sensor[10];
|
||||
snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1);
|
||||
char voltage[10];
|
||||
dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage);
|
||||
|
||||
if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) {
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"),
|
||||
mqtt_data, sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage);
|
||||
}
|
||||
} else {
|
||||
float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100);
|
||||
char temperature[10];
|
||||
dtostrfd(temp, Settings.flag2.temperature_resolution, temperature);
|
||||
float humi = (float)rfsns_theo_v2_t2[i].hum / 100;
|
||||
char humidity[10];
|
||||
dtostrfd(humi, Settings.flag2.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"),
|
||||
mqtt_data, sensor, temperature, humidity, voltage);
|
||||
if ((0 == tele_period) && !sensor_once) {
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
KnxSensor(KNX_TEMPERATURE, temp);
|
||||
KnxSensor(KNX_HUMIDITY, humi);
|
||||
#endif // USE_KNX
|
||||
sensor_once = true;
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_THEO_V2 ************************************************************************
|
||||
|
||||
#ifdef USE_ALECTO_V2
|
||||
/*********************************************************************************************\
|
||||
* Alecto V2 protocol
|
||||
* Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren
|
||||
*
|
||||
* Auteur : Nodo-team (Martinus van den Broek) www.nodo-domotica.nl
|
||||
* Support ACH2010 en code optimalisatie door forumlid: Arendst
|
||||
* Support : www.nodo-domotica.nl
|
||||
* Datum : 25 Jan 2013
|
||||
* Versie : 1.3
|
||||
**********************************************************************************************
|
||||
* Technische informatie:
|
||||
* DKW2012 Message Format: (11 Bytes, 88 bits):
|
||||
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH IIIIIIII
|
||||
* Temperature Humidity Windspd_ Windgust Rain____ ________ Winddir Checksum
|
||||
* A = start/unknown, first 8 bits are always 11111111
|
||||
* B = Rolling code
|
||||
* C = Temperature (10 bit value with -400 base)
|
||||
* D = Humidity
|
||||
* E = windspeed (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
|
||||
* F = windgust (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
|
||||
* G = Rain ( * 0.3 mm)
|
||||
* H = winddirection (0 = north, 4 = east, 8 = south 12 = west)
|
||||
* I = Checksum, calculation is still under investigation
|
||||
*
|
||||
* WS3000 and ACH2010 systems have no winddirection, message format is 8 bit shorter
|
||||
* Message Format: (10 Bytes, 80 bits):
|
||||
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH
|
||||
* Temperature Humidity Windspd_ Windgust Rain____ ________ Checksum
|
||||
*
|
||||
* DCF Time Message Format: (NOT DECODED!)
|
||||
* AAAAAAAA BBBBCCCC DDDDDDDD EFFFFFFF GGGGGGGG HHHHHHHH IIIIIIII JJJJJJJJ KKKKKKKK LLLLLLLL MMMMMMMM
|
||||
* 11 Hours Minutes Seconds Year Month Day ? Checksum
|
||||
* B = 11 = DCF
|
||||
* C = ?
|
||||
* D = ?
|
||||
* E = ?
|
||||
* F = Hours BCD format (7 bits only for this byte, MSB could be '1')
|
||||
* G = Minutes BCD format
|
||||
* H = Seconds BCD format
|
||||
* I = Year BCD format (only two digits!)
|
||||
* J = Month BCD format
|
||||
* K = Day BCD format
|
||||
* L = ?
|
||||
* M = Checksum
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define RFSNS_DKW2012_PULSECOUNT 176
|
||||
#define RFSNS_ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception
|
||||
#define RFSNS_ACH2010_MAX_PULSECOUNT 160
|
||||
|
||||
typedef struct {
|
||||
uint32_t time;
|
||||
float temp;
|
||||
float rain;
|
||||
float wind;
|
||||
float gust;
|
||||
uint8_t type;
|
||||
uint8_t humi;
|
||||
uint8_t wdir;
|
||||
} alecto_v2_t;
|
||||
|
||||
alecto_v2_t rfsns_alecto_v2;
|
||||
|
||||
uint16_t rfsns_alecto_rain_base = 0;
|
||||
//unsigned long rfsns_alecto_time = 60000;
|
||||
|
||||
boolean RfSnsAnalyzeAlectov2()
|
||||
{
|
||||
if (!(((rfsns_raw_signal.Number >= RFSNS_ACH2010_MIN_PULSECOUNT) &&
|
||||
(rfsns_raw_signal.Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal.Number == RFSNS_DKW2012_PULSECOUNT))) { return false; }
|
||||
|
||||
byte c = 0;
|
||||
byte rfbit;
|
||||
byte data[9];
|
||||
byte msgtype = 0;
|
||||
byte rc = 0;
|
||||
int temp;
|
||||
byte checksum = 0;
|
||||
byte checksumcalc = 0;
|
||||
byte maxidx = 8;
|
||||
unsigned long atime;
|
||||
float factor;
|
||||
char buf1[16];
|
||||
|
||||
if (rfsns_raw_signal.Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; }
|
||||
// Get message back to front as the header is almost never received complete for ACH2010
|
||||
byte idx = maxidx;
|
||||
for (byte x = rfsns_raw_signal.Number; x > 0; x = x-2) {
|
||||
if (rfsns_raw_signal.Pulses[x-1] * rfsns_raw_signal.Multiply < 0x300) {
|
||||
rfbit = 0x80;
|
||||
} else {
|
||||
rfbit = 0;
|
||||
}
|
||||
data[idx] = (data[idx] >> 1) | rfbit;
|
||||
c++;
|
||||
if (c == 8) {
|
||||
if (idx == 0) { break; }
|
||||
c = 0;
|
||||
idx--;
|
||||
}
|
||||
}
|
||||
|
||||
checksum = data[maxidx];
|
||||
checksumcalc = RfSnsAlectoCRC8(data, maxidx);
|
||||
|
||||
msgtype = (data[0] >> 4) & 0xf;
|
||||
rc = (data[0] << 4) | (data[1] >> 4);
|
||||
|
||||
if (checksum != checksumcalc) { return false; }
|
||||
if ((msgtype != 10) && (msgtype != 5)) { return true; }
|
||||
|
||||
rfsns_raw_signal.Repeats = 1; // het is een herhalend signaal. Bij ontvangst herhalingen onderdukken
|
||||
|
||||
factor = 1.22; // (1.08)
|
||||
// atime = rfsns_raw_signal.Time - rfsns_alecto_time;
|
||||
// if ((atime > 10000) && (atime < 60000)) factor = (float)60000 / atime;
|
||||
// rfsns_alecto_time = rfsns_raw_signal.Time;
|
||||
// Serial.printf("atime %d, rfsns_alecto_time %d\n", atime, rfsns_alecto_time);
|
||||
|
||||
rfsns_alecto_v2.time = LocalTime();
|
||||
rfsns_alecto_v2.type = (rfsns_raw_signal.Number == RFSNS_DKW2012_PULSECOUNT);
|
||||
rfsns_alecto_v2.temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10;
|
||||
rfsns_alecto_v2.humi = data[3];
|
||||
uint16_t rain = (data[6] * 256) + data[7];
|
||||
// check if rain unit has been reset!
|
||||
if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; }
|
||||
if (rfsns_alecto_rain_base > 0) {
|
||||
rfsns_alecto_v2.rain += ((float)rain - rfsns_alecto_rain_base) * 0.30;
|
||||
}
|
||||
rfsns_alecto_rain_base = rain;
|
||||
rfsns_alecto_v2.wind = (float)data[4] * factor;
|
||||
rfsns_alecto_v2.gust = (float)data[5] * factor;
|
||||
if (rfsns_alecto_v2.type) {
|
||||
rfsns_alecto_v2.wdir = data[8] & 0xf;
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RFS: AlectoV2, ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"),
|
||||
checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1));
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RfSnsAlectoResetRain(void)
|
||||
{
|
||||
if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) {
|
||||
rfsns_alecto_v2.rain = 0; // Reset Rain
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Calculates CRC-8 checksum
|
||||
* reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/
|
||||
* http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/
|
||||
* https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp
|
||||
\*********************************************************************************************/
|
||||
uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
while (len--) {
|
||||
uint8_t inbyte = *addr++;
|
||||
for (uint8_t i = 8; i; i--) {
|
||||
uint8_t mix = (crc ^ inbyte) & 0x80;
|
||||
crc <<= 1;
|
||||
if (mix) { crc ^= 0x31; }
|
||||
inbyte <<= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void RfSnsAlectoV2Show(boolean json)
|
||||
{
|
||||
if (rfsns_alecto_v2.time) {
|
||||
char sensor[10];
|
||||
snprintf_P(sensor, sizeof(sensor), PSTR("AlectoV2"));
|
||||
|
||||
if (rfsns_alecto_v2.time < LocalTime() - RFSNS_VALID_WINDOW) {
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"),
|
||||
mqtt_data, sensor, GetDT(rfsns_alecto_v2.time).c_str());
|
||||
}
|
||||
} else {
|
||||
float temp = ConvertTemp(rfsns_alecto_v2.temp);
|
||||
char temperature[10];
|
||||
dtostrfd(temp, Settings.flag2.temperature_resolution, temperature);
|
||||
float humi = (float)rfsns_alecto_v2.humi;
|
||||
char humidity[10];
|
||||
dtostrfd(humi, Settings.flag2.humidity_resolution, humidity);
|
||||
char rain[10];
|
||||
dtostrfd(rfsns_alecto_v2.rain, 2, rain);
|
||||
char wind[10];
|
||||
dtostrfd(rfsns_alecto_v2.wind, 2, wind);
|
||||
char gust[10];
|
||||
dtostrfd(rfsns_alecto_v2.gust, 2, gust);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s, \"Rain\":%s,\"Wind\":%s,\"Gust\":%s}"),
|
||||
mqtt_data, sensor, temperature, humidity, rain, wind, gust);
|
||||
if (0 == tele_period) {
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
// KnxSensor(KNX_TEMPERATURE, temp);
|
||||
// KnxSensor(KNX_HUMIDITY, humi);
|
||||
#endif // USE_KNX
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sensor, temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sensor, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_ALECTO_V2 **********************************************************************
|
||||
|
||||
void RfSnsInit(void)
|
||||
{
|
||||
rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]);
|
||||
rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]);
|
||||
pinMode(pin[GPIO_RF_SENSOR], INPUT);
|
||||
}
|
||||
|
||||
void RfSnsAnalyzeRawSignal(void)
|
||||
{
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal.Number);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
// if (Settings.flag3.rf_type) {
|
||||
#ifdef USE_THEO_V2
|
||||
RfSnsAnalyzeTheov2();
|
||||
#endif
|
||||
// } else {
|
||||
#ifdef USE_ALECTO_V2
|
||||
RfSnsAnalyzeAlectov2();
|
||||
#endif
|
||||
// }
|
||||
}
|
||||
|
||||
void RfSnsEverySecond(void)
|
||||
{
|
||||
#ifdef USE_ALECTO_V2
|
||||
RfSnsAlectoResetRain();
|
||||
#endif
|
||||
}
|
||||
|
||||
void RfSnsShow(boolean json)
|
||||
{
|
||||
#ifdef USE_THEO_V2
|
||||
RfSnsTheoV2Show(json);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALECTO_V2
|
||||
RfSnsAlectoV2Show(json);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean Xsns37(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (pin[GPIO_RF_SENSOR] < 99) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
RfSnsInit();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) {
|
||||
if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) {
|
||||
RfSnsAnalyzeRawSignal();
|
||||
}
|
||||
}
|
||||
sleep = 0;
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
RfSnsEverySecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
RfSnsShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_APPEND:
|
||||
RfSnsShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_RF_SENSOR
|
@ -134,8 +134,8 @@ a_features = [[
|
||||
"USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050",
|
||||
"USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766",
|
||||
"USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711",
|
||||
"USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","",
|
||||
"","","","",
|
||||
"USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR",
|
||||
"USE_THEO_V2","USE_ALECTO_V2","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","",""]]
|
||||
|
Loading…
x
Reference in New Issue
Block a user