Browse Source

Merge remote-tracking branch 'origin/dev' into HEAD

ech1560
Maxim Prokhorov 6 years ago
parent
commit
17d12cdd05
18 changed files with 3282 additions and 3130 deletions
  1. +3
    -3
      README.md
  2. +20
    -9
      code/build.sh
  3. +54
    -0
      code/espurna/config/hardware.h
  4. +14
    -10
      code/espurna/config/progmem.h
  5. +5
    -0
      code/espurna/config/sensors.h
  6. +3
    -2
      code/espurna/config/types.h
  7. BIN
      code/espurna/data/index.all.html.gz
  8. BIN
      code/espurna/data/index.sensor.html.gz
  9. +1
    -1
      code/espurna/led.ino
  10. +8
    -2
      code/espurna/ota.ino
  11. +4
    -0
      code/espurna/relay.ino
  12. +88
    -65
      code/espurna/sensor.ino
  13. +1
    -1
      code/espurna/sensors/BaseSensor.h
  14. +29
    -12
      code/espurna/sensors/EventSensor.h
  15. +1690
    -1690
      code/espurna/static/index.all.html.gz.h
  16. +1332
    -1332
      code/espurna/static/index.sensor.html.gz.h
  17. +3
    -2
      code/html/custom.js
  18. +27
    -1
      code/platformio.ini

+ 3
- 3
README.md View File

@ -4,9 +4,9 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smar
It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries. It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries.
[![version](https://img.shields.io/badge/version-1.13.1-brightgreen.svg)](CHANGELOG.md) [![version](https://img.shields.io/badge/version-1.13.1-brightgreen.svg)](CHANGELOG.md)
[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://img.shields.io/codacy/grade/c9496e25cf07434cba786b462cb15f49/dev.svg)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![branch](https://img.shields.io/badge/branch-sensors-orange.svg)](https://github.com/xoseperez/espurna/tree/sensors/)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=sensors)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://img.shields.io/codacy/grade/c9496e25cf07434cba786b462cb15f49/sensors.svg)](https://www.codacy.com/app/xoseperez/espurna/dashboard)
[![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE) [![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
<br /> <br />
[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest) [![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest)


+ 20
- 9
code/build.sh View File

@ -1,19 +1,26 @@
#!/bin/bash #!/bin/bash
set -e set -e
# Utility
is_git() {
command -v git >/dev/null 2>&1 || return 1
command git rev-parse >/dev/null 2>&1 || return 1
return 0
}
# Script settings # Script settings
version=$(grep APP_VERSION espurna/config/version.h | awk '{print $3}' | sed 's/"//g') version=$(grep APP_VERSION espurna/config/version.h | awk '{print $3}' | sed 's/"//g')
(command -v git && git rev-parse --is-inside-work-tree) 2>&1>/dev/null
if [ $? -eq 0 ]; then
if is_git; then
git_revision=$(git rev-parse --short HEAD) git_revision=$(git rev-parse --short HEAD)
git_version=$(git describe --tags)
git_version=${version}-${git_revision}
else else
git_revision= git_revision=
git_version=$version git_version=$version
fi fi
par_build=0
par_build=false
par_thread=${BUILDER_THREAD:-0} par_thread=${BUILDER_THREAD:-0}
par_total_threads=${BUILDER_TOTAL_THREADS:-4} par_total_threads=${BUILDER_TOTAL_THREADS:-4}
if [ ${par_thread} -ne ${par_thread} -o \ if [ ${par_thread} -ne ${par_thread} -o \
@ -27,8 +34,12 @@ if [ ${par_thread} -ge ${par_total_threads} ]; then
fi fi
# Available environments # Available environments
travis=$(grep env: platformio.ini | grep travis | sed 's/\[env://' | sed 's/\]/ /' | sort)
available=$(grep env: platformio.ini | grep -v ota | grep -v ssl | grep -v travis | sed 's/\[env://' | sed 's/\]/ /' | sort)
list_envs() {
grep env: platformio.ini | sed 's/\[env:\(.*\)\]/\1/g'
}
travis=$(list_envs | grep travis | sort)
available=$(list_envs | grep -Ev -- '-ota$|-ssl$|^travis' | sort)
# Build tools settings # Build tools settings
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DAPP_REVISION='\"$git_revision\"'" export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DAPP_REVISION='\"$git_revision\"'"
@ -52,7 +63,7 @@ print_environments() {
set_default_environments() { set_default_environments() {
# Hook to build in parallel when using travis # Hook to build in parallel when using travis
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Release" ]] && [ ${par_build} ]; then
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Release" ]] && ${par_build}; then
environments=$(echo ${available} | \ environments=$(echo ${available} | \
awk -v par_thread=${par_thread} -v par_total_threads=${par_total_threads} \ awk -v par_thread=${par_thread} -v par_total_threads=${par_total_threads} \
'{ for (i = 1; i <= NF; i++) if (++j % par_total_threads == par_thread ) print $i; }') '{ for (i = 1; i <= NF; i++) if (++j % par_total_threads == par_thread ) print $i; }')
@ -106,7 +117,7 @@ while getopts "lp" opt; do
exit exit
;; ;;
p) p)
par_build=1
par_build=true
;; ;;
esac esac
done done
@ -125,7 +136,7 @@ if [ $# -eq 0 ]; then
set_default_environments set_default_environments
fi fi
if [[ "${CI}" = true ]]; then
if ${CI:-false}; then
print_environments print_environments
fi fi


+ 54
- 0
code/espurna/config/hardware.h View File

@ -2384,6 +2384,60 @@
#define HLW8012_POWER_RATIO 3414290 #define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING #define HLW8012_INTERRUPT_ON FALLING
// ----------------------------------------------------------------------------------------
// Homecube 16A is similar but some pins differ and it also has RGB LEDs
// https://www.amazon.de/gp/product/B07D7RVF56/ref=oh_aui_detailpage_o00_s01?ie=UTF8&psc=1
// ----------------------------------------------------------------------------------------
#elif defined(HOMECUBE_16A)
// Info
#define MANUFACTURER "HOMECUBE"
#define DEVICE "16A"
// Buttons
#define BUTTON1_PIN 13
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 15
#define RELAY1_TYPE RELAY_TYPE_NORMAL
// LEDs
//LED Pin 4 - ESP8266 onboard LED
//Red LED: 0
//Green LED: 12
//Blue LED: 2
// Blue
#define LED1_PIN 2
#define LED1_PIN_INVERSE 0
// Green
#define LED2_PIN 12
#define LED2_PIN_INVERSE 1
#define LED2_MODE LED_MODE_RELAY
// Red
#define LED3_PIN 0
#define LED3_PIN_INVERSE 0
#define LED2_MODE LED_MODE_OFF
// HJL01 / BL0937
#ifndef HLW8012_SUPPORT
#define HLW8012_SUPPORT 1
#endif
#define HLW8012_SEL_PIN 16
#define HLW8012_CF1_PIN 14
#define HLW8012_CF_PIN 5
#define HLW8012_SEL_CURRENT LOW
#define HLW8012_CURRENT_RATIO 25740
#define HLW8012_VOLTAGE_RATIO 313400
#define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// VANZAVANZU Smart Outlet Socket (based on BL0937 or HJL-01) // VANZAVANZU Smart Outlet Socket (based on BL0937 or HJL-01)
// https://www.amazon.com/Smart-Plug-Wifi-Mini-VANZAVANZU/dp/B078PHD6S5 // https://www.amazon.com/Smart-Plug-Wifi-Mini-VANZAVANZU/dp/B078PHD6S5


+ 14
- 10
code/espurna/config/progmem.h View File

@ -204,12 +204,13 @@ PROGMEM const char espurna_sensors[] =
PROGMEM const unsigned char magnitude_decimals[] = { PROGMEM const unsigned char magnitude_decimals[] = {
0, 0,
1, 0, 2,
3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 3, 3,
4, 4 // Geiger Counter decimals
1, 0, 2, // THP
3, 0, 0, 0, 0, 0, 0, 0, // Power decimals
0, 0, 0, // analog, digital, event
0, 0, 0, // PM
0, 0, 3, 3, 0,
4, 4, // Geiger Counter decimals
0
}; };
PROGMEM const char magnitude_unknown_topic[] = "unknown"; PROGMEM const char magnitude_unknown_topic[] = "unknown";
@ -226,7 +227,7 @@ PROGMEM const char magnitude_energy_topic[] = "energy";
PROGMEM const char magnitude_energy_delta_topic[] = "energy_delta"; PROGMEM const char magnitude_energy_delta_topic[] = "energy_delta";
PROGMEM const char magnitude_analog_topic[] = "analog"; PROGMEM const char magnitude_analog_topic[] = "analog";
PROGMEM const char magnitude_digital_topic[] = "digital"; PROGMEM const char magnitude_digital_topic[] = "digital";
PROGMEM const char magnitude_events_topic[] = "events";
PROGMEM const char magnitude_event_topic[] = "event";
PROGMEM const char magnitude_pm1dot0_topic[] = "pm1dot0"; PROGMEM const char magnitude_pm1dot0_topic[] = "pm1dot0";
PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5"; PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5";
PROGMEM const char magnitude_pm10_topic[] = "pm10"; PROGMEM const char magnitude_pm10_topic[] = "pm10";
@ -237,17 +238,19 @@ PROGMEM const char magnitude_distance_topic[] = "distance";
PROGMEM const char magnitude_hcho_topic[] = "hcho"; PROGMEM const char magnitude_hcho_topic[] = "hcho";
PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute] PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute]
PROGMEM const char magnitude_geiger_sv_topic[] = "ldr_uSvh"; // local dose rate [µSievert per hour] PROGMEM const char magnitude_geiger_sv_topic[] = "ldr_uSvh"; // local dose rate [µSievert per hour]
PROGMEM const char magnitude_count_topic[] = "count";
PROGMEM const char* const magnitude_topics[] = { PROGMEM const char* const magnitude_topics[] = {
magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic, magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic,
magnitude_pressure_topic, magnitude_current_topic, magnitude_voltage_topic, magnitude_pressure_topic, magnitude_current_topic, magnitude_voltage_topic,
magnitude_active_power_topic, magnitude_apparent_power_topic, magnitude_reactive_power_topic, magnitude_active_power_topic, magnitude_apparent_power_topic, magnitude_reactive_power_topic,
magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic, magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_events_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic,
magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic, magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic,
magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic, magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic,
magnitude_distance_topic, magnitude_hcho_topic, magnitude_distance_topic, magnitude_hcho_topic,
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic // Geiger Counter topics
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic,
magnitude_count_topic
}; };
PROGMEM const char magnitude_empty[] = ""; PROGMEM const char magnitude_empty[] = "";
@ -280,7 +283,8 @@ PROGMEM const char* const magnitude_units[] = {
magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3,
magnitude_ppm, magnitude_lux, magnitude_uv, magnitude_ppm, magnitude_lux, magnitude_uv,
magnitude_distance, magnitude_mgm3, magnitude_distance, magnitude_mgm3,
magnitude_geiger_cpm, magnitude_geiger_sv // Geiger counter units
magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units
magnitude_empty
}; };
#endif #endif

+ 5
- 0
code/espurna/config/sensors.h View File

@ -281,6 +281,11 @@
#define EVENTS_SUPPORT 0 // Do not build with counter support by default #define EVENTS_SUPPORT 0 // Do not build with counter support by default
#endif #endif
#ifndef EVENTS_TRIGGER
#define EVENTS_TRIGGER 1 // 1 to trigger callback on events,
// 0 to only count them and report periodically
#endif
#ifndef EVENTS_PIN #ifndef EVENTS_PIN
#define EVENTS_PIN 2 // GPIO to monitor #define EVENTS_PIN 2 // GPIO to monitor
#endif #endif


+ 3
- 2
code/espurna/config/types.h View File

@ -288,7 +288,7 @@
#define MAGNITUDE_ENERGY_DELTA 11 #define MAGNITUDE_ENERGY_DELTA 11
#define MAGNITUDE_ANALOG 12 #define MAGNITUDE_ANALOG 12
#define MAGNITUDE_DIGITAL 13 #define MAGNITUDE_DIGITAL 13
#define MAGNITUDE_EVENTS 14
#define MAGNITUDE_EVENT 14
#define MAGNITUDE_PM1dot0 15 #define MAGNITUDE_PM1dot0 15
#define MAGNITUDE_PM2dot5 16 #define MAGNITUDE_PM2dot5 16
#define MAGNITUDE_PM10 17 #define MAGNITUDE_PM10 17
@ -299,5 +299,6 @@
#define MAGNITUDE_HCHO 22 #define MAGNITUDE_HCHO 22
#define MAGNITUDE_GEIGER_CPM 23 #define MAGNITUDE_GEIGER_CPM 23
#define MAGNITUDE_GEIGER_SIEVERT 24 #define MAGNITUDE_GEIGER_SIEVERT 24
#define MAGNITUDE_COUNT 25
#define MAGNITUDE_MAX 25
#define MAGNITUDE_MAX 26

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


+ 1
- 1
code/espurna/led.ino View File

@ -293,4 +293,4 @@ void ledLoop() {
} }
#endif LED_SUPPORT
#endif // LED_SUPPORT

+ 8
- 2
code/espurna/ota.ino View File

@ -238,8 +238,14 @@ void otaSetup() {
deferredReset(100, CUSTOM_RESET_OTA); deferredReset(100, CUSTOM_RESET_OTA);
}); });
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %u%%\r"), (progress / (total / 100)));
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
static unsigned int _progOld;
unsigned int _prog = (progress / (total / 100));
if (_prog != _progOld) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %u%%\r"), _prog);
_progOld = _prog;
}
}); });
ArduinoOTA.onError([](ota_error_t error) { ArduinoOTA.onError([](ota_error_t error) {


+ 4
- 0
code/espurna/relay.ino View File

@ -521,6 +521,10 @@ void _relayConfigure() {
if (GPIO_NONE != _relays[i].reset_pin) { if (GPIO_NONE != _relays[i].reset_pin) {
pinMode(_relays[i].reset_pin, OUTPUT); pinMode(_relays[i].reset_pin, OUTPUT);
} }
if (_relays[i].type == RELAY_TYPE_INVERSE) {
//set to high to block short opening of relay
digitalWrite(_relays[i].pin, HIGH);
}
_relays[i].pulse = getSetting("relayPulse", i, RELAY_PULSE_MODE).toInt(); _relays[i].pulse = getSetting("relayPulse", i, RELAY_PULSE_MODE).toInt();
_relays[i].pulse_ms = 1000 * getSetting("relayTime", i, RELAY_PULSE_MODE).toFloat(); _relays[i].pulse_ms = 1000 * getSetting("relayTime", i, RELAY_PULSE_MODE).toFloat();
} }


+ 88
- 65
code/espurna/sensor.ino View File

@ -114,6 +114,8 @@ void _sensorWebSocketSendData(JsonObject& root) {
for (unsigned char i=0; i<_magnitudes.size(); i++) { for (unsigned char i=0; i<_magnitudes.size(); i++) {
sensor_magnitude_t magnitude = _magnitudes[i]; sensor_magnitude_t magnitude = _magnitudes[i];
if (magnitude.type == MAGNITUDE_EVENT) continue;
unsigned char decimals = _magnitudeDecimals(magnitude.type); unsigned char decimals = _magnitudeDecimals(magnitude.type);
dtostrf(magnitude.current, 1-sizeof(buffer), decimals, buffer); dtostrf(magnitude.current, 1-sizeof(buffer), decimals, buffer);
@ -446,7 +448,8 @@ void _sensorLoad() {
{ {
EventSensor * sensor = new EventSensor(); EventSensor * sensor = new EventSensor();
sensor->setGPIO(EVENTS_PIN); sensor->setGPIO(EVENTS_PIN);
sensor->setMode(EVENTS_PIN_MODE);
sensor->setTrigger(EVENTS_TRIGGER);
sensor->setPinMode(EVENTS_PIN_MODE);
sensor->setDebounceTime(EVENTS_DEBOUNCE); sensor->setDebounceTime(EVENTS_DEBOUNCE);
sensor->setInterruptMode(EVENTS_INTERRUPT_MODE); sensor->setInterruptMode(EVENTS_INTERRUPT_MODE);
_sensors.push_back(sensor); _sensors.push_back(sensor);
@ -583,8 +586,17 @@ void _sensorLoad() {
} }
void _sensorCallback(unsigned char i, unsigned char type, const char * payload) {
DEBUG_MSG_P(PSTR("[SENSOR] Sensor #%u callback, type %u, payload: '%s'\n"), i, type, payload);
void _sensorCallback(unsigned char i, unsigned char type, double value) {
DEBUG_MSG_P(PSTR("[SENSOR] Sensor #%u callback, type %u, payload: '%s'\n"), i, type, String(value).c_str());
for (unsigned char k=0; k<_magnitudes.size(); k++) {
if ((_sensors[i] == _magnitudes[k].sensor) && (type == _magnitudes[k].type)) {
_sensorReport(k, value);
return;
}
}
} }
void _sensorInit() { void _sensorInit() {
@ -621,7 +633,7 @@ void _sensorInit() {
new_magnitude.min_change = 0; new_magnitude.min_change = 0;
if (type == MAGNITUDE_DIGITAL) { if (type == MAGNITUDE_DIGITAL) {
new_magnitude.filter = new MaxFilter(); new_magnitude.filter = new MaxFilter();
} else if (type == MAGNITUDE_EVENTS || type == MAGNITUDE_GEIGER_CPM|| type == MAGNITUDE_GEIGER_SIEVERT) { // For geiger counting moving average filter is the most appropriate if needed at all.
} else if (type == MAGNITUDE_COUNT || type == MAGNITUDE_GEIGER_CPM|| type == MAGNITUDE_GEIGER_SIEVERT) { // For geiger counting moving average filter is the most appropriate if needed at all.
new_magnitude.filter = new MovingAverageFilter(); new_magnitude.filter = new MovingAverageFilter();
} else { } else {
new_magnitude.filter = new MedianFilter(); new_magnitude.filter = new MedianFilter();
@ -636,8 +648,8 @@ void _sensorInit() {
} }
// Hook callback // Hook callback
_sensors[i]->onEvent([i](unsigned char type, const char * payload) {
_sensorCallback(i, type, payload);
_sensors[i]->onEvent([i](unsigned char type, double value) {
_sensorCallback(i, type, value);
}); });
// Custom initializations // Custom initializations
@ -855,6 +867,72 @@ void _sensorConfigure() {
} }
void _sensorReport(unsigned char index, double value) {
sensor_magnitude_t magnitude = _magnitudes[index];
unsigned char decimals = _magnitudeDecimals(magnitude.type);
char buffer[10];
dtostrf(value, 1-sizeof(buffer), decimals, buffer);
#if BROKER_SUPPORT
brokerPublish(magnitudeTopic(magnitude.type).c_str(), magnitude.local, buffer);
#endif
#if MQTT_SUPPORT
mqttSend(magnitudeTopicIndex(index).c_str(), buffer);
#if SENSOR_PUBLISH_ADDRESSES
char topic[32];
snprintf(topic, sizeof(topic), "%s/%s", SENSOR_ADDRESS_TOPIC, magnitudeTopic(magnitude.type).c_str());
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
mqttSend(topic, magnitude.global, magnitude.sensor->address(magnitude.local).c_str());
} else {
mqttSend(topic, magnitude.sensor->address(magnitude.local).c_str());
}
#endif // SENSOR_PUBLISH_ADDRESSES
#endif // MQTT_SUPPORT
#if INFLUXDB_SUPPORT
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
idbSend(magnitudeTopic(magnitude.type).c_str(), magnitude.global, buffer);
} else {
idbSend(magnitudeTopic(magnitude.type).c_str(), buffer);
}
#endif // INFLUXDB_SUPPORT
#if THINGSPEAK_SUPPORT
tspkEnqueueMeasurement(index, buffer);
#endif
#if DOMOTICZ_SUPPORT
{
char key[15];
snprintf_P(key, sizeof(key), PSTR("dczMagnitude%d"), index);
if (magnitude.type == MAGNITUDE_HUMIDITY) {
int status;
if (value > 70) {
status = HUMIDITY_WET;
} else if (value > 45) {
status = HUMIDITY_COMFORTABLE;
} else if (value > 30) {
status = HUMIDITY_NORMAL;
} else {
status = HUMIDITY_DRY;
}
char status_buf[5];
itoa(status, status_buf, 10);
domoticzSend(key, buffer, status_buf);
} else {
domoticzSend(key, 0, buffer);
}
}
#endif // DOMOTICZ_SUPPORT
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Public // Public
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -991,7 +1069,6 @@ void sensorLoop() {
double current; double current;
double filtered; double filtered;
char buffer[64];
// Pre-read hook // Pre-read hook
_sensorPre(); _sensorPre();
@ -1027,7 +1104,7 @@ void sensorLoop() {
magnitude.filter->add(current); magnitude.filter->add(current);
// Special case // Special case
if (magnitude.type == MAGNITUDE_EVENTS) {
if (magnitude.type == MAGNITUDE_COUNT) {
current = magnitude.filter->result(); current = magnitude.filter->result();
} }
@ -1037,6 +1114,7 @@ void sensorLoop() {
// Debug // Debug
#if SENSOR_DEBUG #if SENSOR_DEBUG
{ {
char buffer[64];
dtostrf(current, 1-sizeof(buffer), _magnitudeDecimals(magnitude.type), buffer); dtostrf(current, 1-sizeof(buffer), _magnitudeDecimals(magnitude.type), buffer);
DEBUG_MSG_P(PSTR("[SENSOR] %s - %s: %s%s\n"), DEBUG_MSG_P(PSTR("[SENSOR] %s - %s: %s%s\n"),
magnitude.sensor->slot(magnitude.local).c_str(), magnitude.sensor->slot(magnitude.local).c_str(),
@ -1059,63 +1137,8 @@ void sensorLoop() {
if (fabs(filtered - magnitude.reported) >= magnitude.min_change) { if (fabs(filtered - magnitude.reported) >= magnitude.min_change) {
_magnitudes[i].reported = filtered; _magnitudes[i].reported = filtered;
dtostrf(filtered, 1-sizeof(buffer), decimals, buffer);
#if BROKER_SUPPORT
brokerPublish(magnitudeTopic(magnitude.type).c_str(), magnitude.local, buffer);
#endif
#if MQTT_SUPPORT
mqttSend(magnitudeTopicIndex(i).c_str(), buffer);
#if SENSOR_PUBLISH_ADDRESSES
char topic[32];
snprintf(topic, sizeof(topic), "%s/%s", SENSOR_ADDRESS_TOPIC, magnitudeTopic(magnitude.type).c_str());
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
mqttSend(topic, magnitude.global, magnitude.sensor->address(magnitude.local).c_str());
} else {
mqttSend(topic, magnitude.sensor->address(magnitude.local).c_str());
}
#endif // SENSOR_PUBLISH_ADDRESSES
#endif // MQTT_SUPPORT
#if INFLUXDB_SUPPORT
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
idbSend(magnitudeTopic(magnitude.type).c_str(), magnitude.global, buffer);
} else {
idbSend(magnitudeTopic(magnitude.type).c_str(), buffer);
}
#endif // INFLUXDB_SUPPORT
#if THINGSPEAK_SUPPORT
tspkEnqueueMeasurement(i, buffer);
#endif
#if DOMOTICZ_SUPPORT
{
char key[15];
snprintf_P(key, sizeof(key), PSTR("dczMagnitude%d"), i);
if (magnitude.type == MAGNITUDE_HUMIDITY) {
int status;
if (filtered > 70) {
status = HUMIDITY_WET;
} else if (filtered > 45) {
status = HUMIDITY_COMFORTABLE;
} else if (filtered > 30) {
status = HUMIDITY_NORMAL;
} else {
status = HUMIDITY_DRY;
}
char status_buf[5];
itoa(status, status_buf, 10);
domoticzSend(key, buffer, status_buf);
} else {
domoticzSend(key, 0, buffer);
}
}
#endif // DOMOTICZ_SUPPORT
_sensorReport(i, filtered);
} // if (fabs(filtered - magnitude.reported) >= magnitude.min_change) } // if (fabs(filtered - magnitude.reported) >= magnitude.min_change)
} // if (report_count == 0) } // if (report_count == 0)


+ 1
- 1
code/espurna/sensors/BaseSensor.h View File

@ -21,7 +21,7 @@
#define SENSOR_ERROR_CALIBRATION 8 // Calibration error or Not calibrated #define SENSOR_ERROR_CALIBRATION 8 // Calibration error or Not calibrated
#define SENSOR_ERROR_OTHER 99 // Any other error #define SENSOR_ERROR_OTHER 99 // Any other error
typedef std::function<void(unsigned char, const char *)> TSensorCallback;
typedef std::function<void(unsigned char, double)> TSensorCallback;
class BaseSensor { class BaseSensor {


+ 29
- 12
code/espurna/sensors/EventSensor.h View File

@ -33,12 +33,16 @@ class EventSensor : public BaseSensor {
_gpio = gpio; _gpio = gpio;
} }
void setMode(unsigned char mode) {
_mode = mode;
void setTrigger(bool trigger) {
_trigger = trigger;
} }
void setInterruptMode(unsigned char mode) {
_interrupt_mode = mode;
void setPinMode(unsigned char pin_mode) {
_pin_mode = pin_mode;
}
void setInterruptMode(unsigned char interrupt_mode) {
_interrupt_mode = interrupt_mode;
} }
void setDebounceTime(unsigned long debounce) { void setDebounceTime(unsigned long debounce) {
@ -51,8 +55,12 @@ class EventSensor : public BaseSensor {
return _gpio; return _gpio;
} }
unsigned char getMode() {
return _mode;
bool getTrigger() {
return _trigger;
}
unsigned char getPinMode() {
return _pin_mode;
} }
unsigned char getInterruptMode() { unsigned char getInterruptMode() {
@ -70,8 +78,9 @@ class EventSensor : public BaseSensor {
// Initialization method, must be idempotent // Initialization method, must be idempotent
// Defined outside the class body // Defined outside the class body
void begin() { void begin() {
pinMode(_gpio, _mode);
pinMode(_gpio, _pin_mode);
_enableInterrupts(true); _enableInterrupts(true);
_count = _trigger ? 2 : 1;
_ready = true; _ready = true;
} }
@ -94,7 +103,8 @@ class EventSensor : public BaseSensor {
// Type for slot # index // Type for slot # index
unsigned char type(unsigned char index) { unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_EVENTS;
if (index == 0) return MAGNITUDE_COUNT;
if (index == 1) return MAGNITUDE_EVENT;
return MAGNITUDE_NONE; return MAGNITUDE_NONE;
} }
@ -113,8 +123,14 @@ class EventSensor : public BaseSensor {
(void) gpio; (void) gpio;
static unsigned long last = 0; static unsigned long last = 0;
if (millis() - last > _debounce) { if (millis() - last > _debounce) {
_events = _events + 1;
last = millis(); last = millis();
_events = _events + 1;
if (_trigger) {
if (_callback) _callback(MAGNITUDE_EVENT, digitalRead(gpio));
}
} }
} }
@ -148,9 +164,10 @@ class EventSensor : public BaseSensor {
volatile unsigned long _events = 0; volatile unsigned long _events = 0;
unsigned long _debounce = EVENTS_DEBOUNCE; unsigned long _debounce = EVENTS_DEBOUNCE;
unsigned char _gpio;
unsigned char _mode;
unsigned char _interrupt_mode;
unsigned char _gpio = GPIO_NONE;
bool _trigger = false;
unsigned char _pin_mode = INPUT;
unsigned char _interrupt_mode = RISING;
}; };


+ 1690
- 1690
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 1332
- 1332
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 3
- 2
code/html/custom.js View File

@ -59,9 +59,10 @@ function magnitudeType(type) {
"Temperature", "Humidity", "Pressure", "Temperature", "Humidity", "Pressure",
"Current", "Voltage", "Active Power", "Apparent Power", "Current", "Voltage", "Active Power", "Apparent Power",
"Reactive Power", "Power Factor", "Energy", "Energy (delta)", "Reactive Power", "Power Factor", "Energy", "Energy (delta)",
"Analog", "Digital", "Events",
"Analog", "Digital", "Event",
"PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UV", "Distance" , "HCHO", "PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UV", "Distance" , "HCHO",
"Local Dose Rate", "Local Dose Rate"
"Local Dose Rate", "Local Dose Rate",
"Count"
]; ];
if (1 <= type && type <= types.length) { if (1 <= type && type <= types.length) {
return types[type - 1]; return types[type - 1];


+ 27
- 1
code/platformio.ini View File

@ -545,7 +545,7 @@ lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DITEAD_SONOFF_DUAL_R2 build_flags = ${common.build_flags_1m0m} -DITEAD_SONOFF_DUAL_R2
extra_scripts = ${common.extra_scripts} extra_scripts = ${common.extra_scripts}
[env:itead-sonoff-dual-ota-r2]
[env:itead-sonoff-dual-r2-ota]
platform = ${common.platform} platform = ${common.platform}
framework = ${common.framework} framework = ${common.framework}
board = ${common.board_1m} board = ${common.board_1m}
@ -2358,6 +2358,32 @@ upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags} upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts} extra_scripts = ${common.extra_scripts}
[env:homecube-16a]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DHOMECUBE_16A
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:homecube-16a-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DHOMECUBE_16A
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:bh-onofre] [env:bh-onofre]
platform = ${common.platform} platform = ${common.platform}
framework = ${common.framework} framework = ${common.framework}


Loading…
Cancel
Save