Skip to content

Commit

Permalink
v1.2.36
Browse files Browse the repository at this point in the history
- Added automation schedules to smart light and smart sensor examples
- Added `Status.IdleTime` field to motion sensor example
- Added support for TCS 3472x RGB color sensor
- Improved scheduler with module events handling
- Added API method to set system name which is also applied to SSDP/UPnP friendly name
- UPnP device UUID now visible in SSDP service path
- Fixes bug in WPS pairing
- Fixed bug in `$$.net.webService(url).call()` scripting method
  • Loading branch information
genemars committed Oct 22, 2024
1 parent 24739ed commit 05f8b6a
Show file tree
Hide file tree
Showing 35 changed files with 971 additions and 210 deletions.
5 changes: 5 additions & 0 deletions examples/color-light/color-light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ void setup() {
// Setup control buttons
setupControlButtons(module);

#ifndef DISABLE_AUTOMATION
// Setup example schedules/scenes
setupDefaultSchedules();
#endif

// Initialize FX buffer
fx_init(ledsCount, currentColor);

Expand Down
52 changes: 52 additions & 0 deletions examples/color-light/color-light.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,55 @@ void setupControlButtons(Module* miniModule) {
}

}

#ifndef DISABLE_AUTOMATION
void setupDefaultSchedules() {

// Create default Dawn scene
if (Scheduler::get("Dawn") == nullptr) {
auto s = new Schedule("Dawn", "Dawn scene colors, 24 minutes before sunrise.", "", "@SolarTimes.Sunrise - 24", "$$.boundModules.on();");
s->onModuleEvent = false;
//s->eventModules.add(miniModule->getReference());
// UI state data
s->data = R"({"action":{"template":{"forEach":{"config":{"color":"#FF9100|30.0"},"enabled":true,"id":"command_set_color"},"forEnd":{"config":{},"enabled":false,"id":null},"forStart":{"config":{},"enabled":false,"id":null}},"type":"template"},"event":[],"from":"","itemType":3,"occur_dayom_sel":[],"occur_dayom_type":1,"occur_dayow_sel":[],"occur_hour_sel":[],"occur_hour_step":12,"occur_hour_type":1,"occur_min_sel":[],"occur_min_step":30,"occur_min_type":1,"occur_month_sel":[],"occur_month_type":1,"time":[],"to":""})";
// Device types allowed
s->boundDevices.add(new String("Dimmer"));
s->boundDevices.add(new String("Color"));
Scheduler::addSchedule(s);
}

// Create default Dusk scene
if (Scheduler::get("Dusk") == nullptr) {
auto s = new Schedule("Dusk", "Dusk scene colors, 42 minutes after sunset.", "", "@SolarTimes.Sunset + 42", "$$.boundModules.on();");
s->onModuleEvent = false;
//s->eventModules.add(miniModule->getReference());
// UI state data
s->data = R"({"action":{"template":{"forEach":{"config":{"color":"#0099FF|30.0"},"enabled":true,"id":"command_set_color"},"forEnd":{"config":{},"enabled":false,"id":null},"forStart":{"config":{},"enabled":false,"id":null}},"type":"template"},"event":[],"from":"","itemType":3,"occur_dayom_sel":[],"occur_dayom_type":1,"occur_dayow_sel":[],"occur_hour_sel":[],"occur_hour_step":12,"occur_hour_type":1,"occur_min_sel":[],"occur_min_step":30,"occur_min_type":1,"occur_month_sel":[],"occur_month_type":1,"time":[],"to":""})";
// Device types allowed
s->boundDevices.add(new String("Dimmer"));
s->boundDevices.add(new String("Color"));
Scheduler::addSchedule(s);
}

// Create default Light.OFF scene
if (Scheduler::get("Lights.Off") == nullptr) {
auto s = new Schedule("Lights.Off", "Ensure lights are turned off every day at 2AM.", "", "0 2 * * *", "$$.boundModules.off();");
s->onModuleEvent = false;
//s->eventModules.add(miniModule->getReference());
// UI state data
s->data = R"({"action":{"template":{"forEach":{"config":{},"enabled":true,"id":"command_turn_off"},"forEnd":{"config":{},"enabled":false,"id":null},"forStart":{"config":{},"enabled":false,"id":null}},"type":"template"},"event":[],"from":"","itemType":1,"occur_dayom_sel":[],"occur_dayom_type":1,"occur_dayow_sel":[],"occur_hour_sel":[],"occur_hour_step":12,"occur_hour_type":1,"occur_min_sel":[],"occur_min_step":30,"occur_min_type":1,"occur_month_sel":[],"occur_month_type":1,"time":[{"end":"02:00","start":"02:00"}],"to":""})";
// Device types allowed
s->boundDevices.add(new String("Light"));
s->boundDevices.add(new String("Dimmer"));
s->boundDevices.add(new String("Color"));
Scheduler::addSchedule(s);
}

if (true || Scheduler::getScheduleList().size() == 0) {

// TODO: if added at least one schedule then -> Scheduler::save();

}

}
#endif // DISABLE_AUTOMATION
70 changes: 64 additions & 6 deletions examples/smart-sensor/CommonSensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,102 @@
#include "io/sensors/MotionSensor.h"
#include "io/sensors/DHTxx.h"
#include "io/sensors/LightSensor.h"
#include "io/sensors/TCS34725.h"

using namespace IO::Sensors;

void includeCommonSensors(HomeGenie* homeGenie, Module* miniModule) {
#ifndef DISABLE_AUTOMATION
void setupMotionSensorSchedules(Module* sensorModule) {

// Create default Dawn scene
if (Scheduler::get("Motion.Activated") == nullptr) {
auto s = new Schedule("Motion.Activated", "Turn on light if motion is detected and luminosity is low.", "", "", "$$.boundModules.on();");
s->onModuleEvent = true;
s->eventModules.add(sensorModule->getReference());
// UI state data
s->data = R"({"action":{"template":{"forEach":{"config":{},"enabled":true,"id":"command_turn_on"},"forEnd":{"config":{},"enabled":false,"id":null},"forStart":{"config":{},"enabled":false,"id":null}},"type":"template"},"event":[{"condition":">","module":"34b7da5-2220-6e69-654d-696e69dab734/HomeAutomation.HomeGenie/mini","property":"Sensor.MotionDetect","value":"0"},{"condition":"<","module":"34b7da5-2220-6e69-654d-696e69dab734/HomeAutomation.HomeGenie/mini","property":"Sensor.Luminance","value":"70"}],"from":"","itemType":1,"occur_dayom_sel":[],"occur_dayom_type":1,"occur_dayow_sel":[],"occur_hour_sel":[],"occur_hour_step":12,"occur_hour_type":1,"occur_min_sel":[],"occur_min_step":30,"occur_min_type":1,"occur_month_sel":[],"occur_month_type":1,"time":[],"to":""})";
// Device types allowed
s->boundDevices.add(new String("Switch"));
s->boundDevices.add(new String("Light"));
s->boundDevices.add(new String("Dimmer"));
s->boundDevices.add(new String("Color"));
Scheduler::addSchedule(s);
}

// Create default Dusk scene
if (Scheduler::get("Motion.Timeout") == nullptr) {
auto s = new Schedule("Motion.Timeout", "Turn off light if no motion is detected for 5 minutes.", "", "", "$$.boundModules.off();");
s->onModuleEvent = true;
s->eventModules.add(sensorModule->getReference());
// UI state data
s->data = R"({"action":{"template":{"forEach":{"config":{},"enabled":true,"id":"command_turn_off"},"forEnd":{"config":{},"enabled":false,"id":null},"forStart":{"config":{},"enabled":false,"id":null}},"type":"template"},"event":[{"condition":">=","module":"34b7da5-2220-6e69-654d-696e69dab734/HomeAutomation.HomeGenie/mini","property":"Status.IdleTime","value":"5"},{"condition":">","module":"34b7da5-2220-6e69-654d-696e69dab734/HomeAutomation.HomeGenie/mini","property":"Sensor.Luminance","value":"50"}],"from":"","itemType":1,"occur_dayom_sel":[],"occur_dayom_type":1,"occur_dayow_sel":[],"occur_hour_sel":[],"occur_hour_step":12,"occur_hour_type":1,"occur_min_sel":[],"occur_min_step":30,"occur_min_type":1,"occur_month_sel":[],"occur_month_type":1,"time":[],"to":""})";
// Device types allowed
s->boundDevices.add(new String("Switch"));
s->boundDevices.add(new String("Light"));
s->boundDevices.add(new String("Dimmer"));
s->boundDevices.add(new String("Color"));
Scheduler::addSchedule(s);
}

if (true || Scheduler::getScheduleList().size() == 0) {

// TODO: if added at least one schedule then -> Scheduler::save();

}

}
#endif

void includeCommonSensors(HomeGenie* homeGenie, Module* sensorModule) {

// Light sensor
if (Config::getSetting("ligh-typ").equals("ldr")) {
auto lightSensor = new LightSensor(Config::getSetting("ligh-pin").toInt());
lightSensor->setModule(miniModule);
lightSensor->setModule(sensorModule);
homeGenie->addIOHandler(lightSensor);
}

// Color sensor TCS-3472x
if (Config::getSetting("colr-typ").equals("tcs3472")) {
//TCS34725 colorSensor;
auto sdaPin = Config::getSetting("colr-sda").toInt();
auto sclPin = Config::getSetting("colr-scl").toInt();
auto colorSensor = new TCS34725(sdaPin, sclPin);
colorSensor->setModule(sensorModule);
homeGenie->addIOHandler(colorSensor);
}

// Motion sensor
if (Config::getSetting("motn-typ").equals("switch")) {
uint8_t motionSensorPin = Config::getSetting("motn-pin").toInt();
auto motionSensor = new MotionSensor(motionSensorPin);
motionSensor->setModule(miniModule);
motionSensor->setModule(sensorModule);
homeGenie->addIOHandler(motionSensor);
#ifndef DISABLE_AUTOMATION
// Add example schedules/scenes for motion sensor
setupMotionSensorSchedules(sensorModule);
#endif
}

// Temperature sensor
if (Config::getSetting("soth-typ").equals("ds18b20")) {
auto temperatureSensor = new DS18B20(Config::getSetting("soth-pin").toInt());
temperatureSensor->setModule(miniModule);
temperatureSensor->setModule(sensorModule);
homeGenie->addIOHandler(temperatureSensor);
}

// DHT-xx Temperature and humidity sensor
uint8_t dhtSensorPint = Config::getSetting("sdht-pin").toInt();
if (Config::getSetting("sdht-typ").equals("22")) {
auto dhtSensor = new DHTxx(22, dhtSensorPint);
dhtSensor->setModule(miniModule);
dhtSensor->setModule(sensorModule);
homeGenie->addIOHandler((IIOEventSender*)dhtSensor);
} else if (Config::getSetting("sdht-typ").equals("11")) {
auto dhtSensor = new DHTxx(11, dhtSensorPint);
dhtSensor->setModule(miniModule);
dhtSensor->setModule(sensorModule);
homeGenie->addIOHandler((IIOEventSender*)dhtSensor);
}

}

#endif //HOMEGENIE_MINI_COMMONSENSORS_H
3 changes: 3 additions & 0 deletions examples/smart-sensor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ In addition to default system options the following configuration options are av
| `soth-pin` | Temperature sensor GPIO# | -1 |
| `sdht-typ` | Temperature + Humidity sensor type | -1 |
| `sdht-pin` | Temperature + Humidity sensor GPIO# | -1 |
| `colr-typ` | Color sensor type | -1 |
| `colr-sda` | Color sensor SDA pin | -1 |
| `colr-scl` | Color sensor SCL pin | -1 |


### Manual build and install
Expand Down
4 changes: 2 additions & 2 deletions examples/smart-sensor/io/sensors/DHTxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ namespace IO { namespace Sensors {
// signal value changes
if (currentData.temperature != t) {
Logger::info("@%s [%s %0.2f]", DHTXX_NS_PREFIX, IOEventPaths::Sensor_Temperature, currentData.temperature);
sendEvent(IOEventPaths::Sensor_Temperature, (float_t *)&currentData.temperature, SensorTemperature);
sendEvent(IOEventPaths::Sensor_Temperature, &currentData.temperature, SensorTemperature);
}
if (currentData.humidity != h) {
Logger::info("@%s [%s %0.2f]", DHTXX_NS_PREFIX, IOEventPaths::Sensor_Humidity, currentData.humidity);
sendEvent(IOEventPaths::Sensor_Humidity, (float_t *)&currentData.humidity, SensorHumidity);
sendEvent(IOEventPaths::Sensor_Humidity, &currentData.humidity, SensorHumidity);
}

Logger::verbose(" > %s::loop() << END", DHTXX_NS_PREFIX);
Expand Down
10 changes: 5 additions & 5 deletions examples/smart-sensor/io/sensors/DHTxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
#ifndef HOMEGENIE_MINI_DHTXX_H
#define HOMEGENIE_MINI_DHTXX_H

#include <dhtnew.h>

#include <HomeGenie.h>

#include <dhtnew.h>

#define DHTXX_NS_PREFIX "IO::Sensors::DHTxx"
#define SENSOR_SAMPLING_RATE 30000L

Expand All @@ -45,7 +45,7 @@ namespace IO { namespace Sensors {
public:
float_t temperature;
float_t humidity;
DHTxxSensorData(DHTxxSensorData* data = nullptr) {
explicit DHTxxSensorData(DHTxxSensorData* data = nullptr) {
if (data != nullptr) {
temperature = data->temperature;
humidity = data->humidity;
Expand All @@ -63,9 +63,9 @@ namespace IO { namespace Sensors {
}
void setModule(Module* m) override {
IIOEventSender::setModule(m);
auto temperature = new ModuleParameter(IOEventPaths::Sensor_Temperature);
auto temperature = new ModuleParameter(IOEventPaths::Sensor_Temperature, "0");
m->properties.add(temperature);
auto humidity = new ModuleParameter(IOEventPaths::Sensor_Humidity);
auto humidity = new ModuleParameter(IOEventPaths::Sensor_Humidity, "0");
m->properties.add(humidity);
}
void begin() override;
Expand Down
2 changes: 1 addition & 1 deletion examples/smart-sensor/io/sensors/DS18B20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace IO { namespace Sensors {
if (currentTemperature != temperature) {
currentTemperature = temperature;
Logger::info("@%s [%s %0.2f]", DS18B20_NS_PREFIX, IOEventPaths::Sensor_Temperature, currentTemperature);
sendEvent(domain.c_str(), address.c_str(), IOEventPaths::Sensor_Temperature, (float_t *)&currentTemperature, SensorTemperature);
sendEvent(domain.c_str(), address.c_str(), IOEventPaths::Sensor_Temperature, &currentTemperature, SensorTemperature);
}

Logger::verbose(" > %s::loop() << END", DS18B20_NS_PREFIX);
Expand Down
8 changes: 4 additions & 4 deletions examples/smart-sensor/io/sensors/DS18B20.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
#ifndef HOMEGENIE_MINI_DS18B20_H
#define HOMEGENIE_MINI_DS18B20_H

#include "src/HomeGenie.h"
#include <HomeGenie.h>

#include ".pio/libdeps/smart-sensor/OneWire/OneWire.h"
#include <OneWire.h>

#define DS18B20_NS_PREFIX "IO::Sensors::DS18B10"
#define DS18B20_SAMPLING_RATE 60000L
Expand All @@ -46,13 +46,13 @@ namespace IO { namespace Sensors {

class DS18B20 : Task, public IIOEventSender {
public:
DS18B20(uint8_t pin) {
explicit DS18B20(uint8_t pin) {
setLoopInterval(DS18B20_SAMPLING_RATE);
inputPin = pin;
}
void setModule(Module* m) override {
IIOEventSender::setModule(m);
auto temperature = new ModuleParameter(IOEventPaths::Sensor_Temperature);
auto temperature = new ModuleParameter(IOEventPaths::Sensor_Temperature, "0");
m->properties.add(temperature);
}
void begin() override;
Expand Down
2 changes: 1 addition & 1 deletion examples/smart-sensor/io/sensors/LightSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace IO { namespace Sensors {
if (lightLevel != currentLevel) {
currentLevel = lightLevel;
Logger::info("@%s [%s %d]", LIGHTSENSOR_NS_PREFIX, IOEventPaths::Sensor_Luminance, currentLevel);
sendEvent(IOEventPaths::Sensor_Luminance, (uint16_t *)&currentLevel, SensorLight);
sendEvent(IOEventPaths::Sensor_Luminance, &currentLevel, SensorLight);
}
}

Expand Down
6 changes: 3 additions & 3 deletions examples/smart-sensor/io/sensors/LightSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#ifndef HOMEGENIE_MINI_LIGHTSENSOR_H
#define HOMEGENIE_MINI_LIGHTSENSOR_H

#include "src/HomeGenie.h"
#include <HomeGenie.h>

#define LIGHTSENSOR_NS_PREFIX "IO::Sensors::LightSensor"
#define LIGHTSENSOR_SAMPLING_RATE 5000L
Expand All @@ -41,13 +41,13 @@ namespace IO { namespace Sensors {

class LightSensor : Task, public IIOEventSender {
public:
LightSensor(uint8_t pin) {
explicit LightSensor(uint8_t pin) {
setLoopInterval(LIGHTSENSOR_SAMPLING_RATE);
inputPin = pin;
}
void setModule(Module* m) override {
IIOEventSender::setModule(m);
auto luminance = new ModuleParameter(IOEventPaths::Sensor_Luminance);
auto luminance = new ModuleParameter(IOEventPaths::Sensor_Luminance, "0");
m->properties.add(luminance);
}

Expand Down
21 changes: 19 additions & 2 deletions examples/smart-sensor/io/sensors/MotionSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,40 @@ namespace IO { namespace Sensors {
void MotionSensor::loop() {
int motionValue = digitalRead(sensorPin);
if (motionValue == HIGH && !motionDetected) {
clearIdle();
// MOTION DETECTED
motionDetected = true;
Logger::info("@%s [%s %d]", MOTION_SENSOR_NS_PREFIX, IOEventPaths::Sensor_MotionDetect, motionValue);
sendEvent(IOEventPaths::Sensor_MotionDetect, (int*)&motionValue, IOEventDataType::Number);
sendEvent(IOEventPaths::Sensor_MotionDetect, &motionValue, IOEventDataType::Number);
#ifdef CONFIG_ENABLE_POWER_MANAGER
PowerManager::setActive();
#endif
} else if (motionValue == LOW && motionDetected) {
clearIdle();
// MOTION CLEAR
motionDetected = false;
Logger::info("@%s [%s %d]", MOTION_SENSOR_NS_PREFIX, IOEventPaths::Sensor_MotionDetect, motionValue);
sendEvent(IOEventPaths::Sensor_MotionDetect, (int*)&motionValue, IOEventDataType::Number);
sendEvent(IOEventPaths::Sensor_MotionDetect, &motionValue, IOEventDataType::Number);
} else if (motionDetected) {
// MOTION ACTIVE
#ifdef CONFIG_ENABLE_POWER_MANAGER
PowerManager::setActive();
#endif
}

updateIdle();
}
void MotionSensor::clearIdle() {
idleTime = millis();
lastUpdate = idleTime - 60000; // forces update
updateIdle();
}
void MotionSensor::updateIdle() {
uint32_t elapsed = millis() - lastUpdate;
if (elapsed >= 60000) {
lastUpdate = millis();
uint32_t idleMinutes = (millis() - idleTime) / 60000;
sendEvent(IOEventPaths::Status_IdleTime, &idleMinutes, IOEventDataType::Number);
}
}
}} // Sensors
12 changes: 9 additions & 3 deletions examples/smart-sensor/io/sensors/MotionSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#ifndef HOMEGENIE_MINI_MOTIONSENSOR_H
#define HOMEGENIE_MINI_MOTIONSENSOR_H

#include "src/HomeGenie.h"
#include <HomeGenie.h>

#define MOTION_SENSOR_NS_PREFIX "IO::Sensors::MotionSensor"

Expand All @@ -15,21 +15,27 @@ namespace IO { namespace Sensors {

class MotionSensor : Task, public IIOEventSender {
public:
MotionSensor(uint8_t pin) {
explicit MotionSensor(uint8_t pin) {
setLoopInterval(200);
sensorPin = pin;
}
void setModule(Module* m) override {
IIOEventSender::setModule(m);
auto motionDetect = new ModuleParameter(IOEventPaths::Sensor_MotionDetect);
auto motionDetect = new ModuleParameter(IOEventPaths::Sensor_MotionDetect, "0");
m->properties.add(motionDetect);
auto idleTime = new ModuleParameter(IOEventPaths::Status_IdleTime, "0");
m->properties.add(idleTime);
}
void begin() override;
void loop() override;

private:
uint8_t sensorPin = 0;
bool motionDetected = false;
unsigned long idleTime = 0;
unsigned long lastUpdate = 0;
void clearIdle();
void updateIdle();
};

}} // Sensors
Expand Down
Loading

0 comments on commit 05f8b6a

Please sign in to comment.