Skip to content

Commit

Permalink
v1.2.1
Browse files Browse the repository at this point in the history
- fixed bug in API request options parsing
- new BluetoothManager class supporting device configuration via LE
- added `DISABLE_MQTT`, `DISABLE_BLUETOOTH` and `DISABLE_BLUETOOTH_LE` flags
- implemented *HomeGenie API* method `Config/Modules.ParameterSet`
- added smart sensor with touch display example for generic *ESP32* and *ESP32-S3*
- added configuration to target *ESP32-C3* for playground example
- updated Shutter control example
- added minimal UI system with touch and gestures support
  • Loading branch information
genemars committed Feb 16, 2024
1 parent 916ca45 commit f2cca1f
Show file tree
Hide file tree
Showing 79 changed files with 6,762 additions and 490 deletions.
49 changes: 30 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# HomeGenie Mini v1.2 <small>`ESP32 / ESP8266`</small>

HomeGenie mini *(code name **Sbirulino**)* is an **open source library** for building custom firmwares for smart devices
HomeGenie mini *(code name **Sbirulino**)* is an **open source library** for building custom firmware for smart devices
based on *ESP32* or *ESP8266* chip.


Expand Down Expand Up @@ -74,7 +74,7 @@ different hardware and functionality as explained later in this file.
## Connecting the device

Once the firmware is installed you can configure and control the device using
the [HomeGenie Panel](https://play.google.com/store/apps/details?id=com.glabs.homegenieplus) app available from Google PlayStore.
the [HomeGenie Panel](https://play.google.com/store/apps/details?id=com.glabs.homegenieplus) app available on Google Play.

The device status LED will blink continuously indicating that the device is not
connected to Wi-Fi, and is in pairing mode accepting connections via Bluetooth.
Expand Down Expand Up @@ -103,13 +103,13 @@ firmware that implements temperature and light sensor and 4 GPIO switches.

### Connecting to HomeGenie Automation Server

HG-Mini devices can also be connected to [HomeGenie Automation Server](https://github.com/genielabs/HomeGenie)
HG-Mini devices can also be connected to [HomeGenie Server](https://github.com/genielabs/HomeGenie)
configuring the *MQTT client* as shown in the following picture.

![HomeGenie Server - MQTT configuration](data/images/phone/hg_server_mqtt_config.png)

Is then possible to use HG-mini device for automation tasks, logging, statistics and use of all other
features of *HomeGenie*.
features available in *HomeGenie Server*.

![HomeGenie Server - Dashboard](data/images/phone/hg_server_dashboard.png)

Expand Down Expand Up @@ -162,7 +162,7 @@ pio device monitor -b 115200

In the examples folder you can find some smart device projects using *HomeGenie Mini* library.

### Smart sensor example
### Smart sensor

This example implements a smart sensor with temperature and luminance sensing. It can also control
4 GPIO switches.
Expand All @@ -182,7 +182,20 @@ pio run -e smart-sensor-d1-mini -t upload
pio run -e smart-sensor-d1-mini-esp32 -t upload
```

### Shutter control example

### Smart sensor with touch display


- `smart-sensor-display`
Humidity and temperature sensor with touch display. For generic *ESP32*,
GC9A01 240x240 round display, and CST816S capacitive touch
- `smart-sensor-display-s3`
Like above but with 1.28" round display and integrated ESP32-S3 on board.




### Shutter control

Wi-Fi controlled shutter motor.

Expand All @@ -192,7 +205,7 @@ pio run -e shutter -t upload
```


### X10 transceiver example
### X10 transceiver

Smart Wi-Fi connected X10 transceiver.

Expand All @@ -203,7 +216,7 @@ The data pins number can be modified from the `configuration.h` file.
pio run -e x10-transceiver -t upload
```

### RF transceiver example
### RF transceiver

Smart Wi-Fi connected RF transceiver with RF commands capturing and playback.

Expand All @@ -225,6 +238,14 @@ pio run -e playground -t upload



-`playground-c3`
Same as above but compiling for *ESP32-C3*









Expand Down Expand Up @@ -321,20 +342,10 @@ Where `<pin_name>` can be `D5`, `D6`, `D7` or `D8` and `<level>` a integer betwe
/api/HomeAutomation.HomeGenie/D8/Control.Off
```

### [HomeAutomation.X10](https://genielabs.github.io/HomeGenie/api/mig/mig_api_x10.html) API (x10-transceiver firmware)

Implemented subset:

- [`/api/HomeAutomation.X10/<module_address>/Control.On`](https://genielabs.github.io/HomeGenie/api/mig/mig_api_x10.html#1)
- [`/api/HomeAutomation.X10/<module_address>/Control.Off`](https://genielabs.github.io/HomeGenie/api/mig/mig_api_x10.html#2)
- [`/api/HomeAutomation.X10/<module_address>/Control.Level`](https://genielabs.github.io/HomeGenie/api/mig/mig_api_x10.html#5)
- [`/api/HomeAutomation.X10/<module_address>/Control.Toggle`](https://genielabs.github.io/HomeGenie/api/mig/mig_api_x10.html#6)



---

## Disclaimer
# Disclaimer

<small><code>
THIS PROJECT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS PROJECT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Expand Down
16 changes: 9 additions & 7 deletions examples/shutter/api/ShutterHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@

namespace Service { namespace API {

ShutterHandler::ShutterHandler(ShutterControl* servoControl) {
this->servoControl = servoControl;
ShutterHandler::ShutterHandler(ShutterControl* shutterControl) {
this->shutterControl = shutterControl;

auto domain = IO::IOEventDomains::Automation_Components;
// Shutter module
Expand Down Expand Up @@ -62,17 +62,17 @@ namespace Service { namespace API {

float level = command->OptionsString.toFloat();

servoControl->setLevel(level);
shutterControl->setLevel(level);

responseCallback->writeAll(R"({ "ResponseText": "OK" })");

} else if (command->Command == "Control.Close" || command->Command == "Control.Off") {

servoControl->close();
shutterControl->close();

} else if (command->Command == "Control.Open" || command->Command == "Control.On") {

servoControl->open();
shutterControl->open();

} else {

Expand All @@ -96,7 +96,8 @@ namespace Service { namespace API {
if (module) {
auto event = String((char *) eventPath);
// Event Stream Message Enqueue (for MQTT/SSE/WebSocket propagation)
auto m = QueuedMessage(domain, address, event.c_str(), "");
auto m = QueuedMessage(domain, address, event.c_str(), "",
nullptr, IOEventDataType::Undefined);
// Data type handling
switch (dataType) {
case Number:
Expand All @@ -108,7 +109,8 @@ namespace Service { namespace API {
default:
m.value = String(*(int32_t *) eventData);
}
module->setProperty(event, m.value);
module->setProperty(event, m.value,
nullptr, IOEventDataType::Undefined);
HomeGenie::getInstance()->getEventRouter().signalEvent(m);
}
return false;
Expand Down
4 changes: 2 additions & 2 deletions examples/shutter/api/ShutterHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ namespace Service { namespace API {
LinkedList<Module*> moduleList;
Module* shutterModule;
ModuleParameter* shutterLevel;
ShutterControl* servoControl;
ShutterControl* shutterControl;
public:
ShutterHandler(ShutterControl* servoControl);
ShutterHandler(ShutterControl* shutterControl);
void init() override;
bool canHandleDomain(String* domain) override;
bool handleRequest(APIRequest *request, ResponseCallback* responseCallback) override;
Expand Down
11 changes: 11 additions & 0 deletions examples/shutter/io/IShutterDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,24 @@
#ifndef HOMEGENIE_MINI_ISHUTTERDRIVER_H
#define HOMEGENIE_MINI_ISHUTTERDRIVER_H

#define SHUTTER_CONTROL_NS_PREFIX "IO::Components:ShutterControl"
#define SERVO_MODULE_ADDRESS "S1"

#define SHUTTER_COMMAND_NONE 0
#define SHUTTER_COMMAND_OPEN 1
#define SHUTTER_COMMAND_CLOSE 2

#define EVENT_EMIT_FREQUENCY 500

namespace IO { namespace Components {
class IShutterDriver {
public:
virtual void init() = 0;
virtual void stop() = 0;
virtual void open() = 0;
virtual void close() = 0;
virtual void level(float) = 0;
IIOEventSender* eventSender = nullptr;
};
}}

Expand Down
81 changes: 3 additions & 78 deletions examples/shutter/io/ShutterControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,92 +32,17 @@
namespace IO { namespace Components {

void ShutterControl::begin() {

shutterDriver->init();

}

void ShutterControl::loop() {

long elapsed = millis() - lastCommandTs;
float percent = ((float)elapsed / totalTimeSpanMs);
if (stopRequested || (stopTime != 0 && millis() >= stopTime)) {

stopRequested = false;
stopTime = 0;
shutterDriver->stop();
if (lastCommand == SHUTTER_COMMAND_OPEN) {
currentLevel += percent;
} else if (lastCommand == SHUTTER_COMMAND_CLOSE) {
currentLevel -= percent;
}
lastCommand = SHUTTER_COMMAND_NONE;
Logger::info("@%s [%s %.2f]", SHUTTER_CONTROL_NS_PREFIX, (IOEventPaths::Status_Level), currentLevel);
sendEvent(domain.c_str(), address.c_str(), (const uint8_t*)(IOEventPaths::Status_Level), &currentLevel, IOEventDataType::Float);

} else if (lastCommand == SHUTTER_COMMAND_OPEN) {

if (elapsed > (totalTimeSpanMs - (currentLevel * totalTimeSpanMs))) {
lastCommand = SHUTTER_COMMAND_NONE;
shutterDriver->stop();
currentLevel = 1;
Logger::info("@%s [%s %.2f]", SHUTTER_CONTROL_NS_PREFIX, (IOEventPaths::Status_Level), currentLevel);
sendEvent(domain.c_str(), address.c_str(), (const uint8_t *) (IOEventPaths::Status_Level),
&currentLevel, IOEventDataType::Float);
} else if (millis() - lastEventMs > EVENT_EMIT_FREQUENCY) {
float level = currentLevel + percent;
Logger::info("@%s [%s %.2f]", SHUTTER_CONTROL_NS_PREFIX, (IOEventPaths::Status_Level), level);
sendEvent(domain.c_str(), address.c_str(), (const uint8_t *) (IOEventPaths::Status_Level),
&level, IOEventDataType::Float);
}

} else if (lastCommand == SHUTTER_COMMAND_CLOSE) {

if (elapsed > (currentLevel * totalTimeSpanMs)) {
lastCommand = SHUTTER_COMMAND_NONE;
shutterDriver->stop();
currentLevel = 0;
Logger::info("@%s [%s %.2f]", SHUTTER_CONTROL_NS_PREFIX, (IOEventPaths::Status_Level), currentLevel);
sendEvent(domain.c_str(), address.c_str(), (const uint8_t*)(IOEventPaths::Status_Level), &currentLevel, IOEventDataType::Float);
} else if (millis() - lastEventMs > EVENT_EMIT_FREQUENCY) {
float level = currentLevel - percent;
Logger::info("@%s [%s %.2f]", SHUTTER_CONTROL_NS_PREFIX, (IOEventPaths::Status_Level), level);
sendEvent(domain.c_str(), address.c_str(), (const uint8_t *) (IOEventPaths::Status_Level),
&level, IOEventDataType::Float);
}

}

}

void ShutterControl::open() {
if (lastCommand != SHUTTER_COMMAND_NONE) {
stopRequested = true;
} else {
shutterDriver->open();
lastCommand = SHUTTER_COMMAND_OPEN;
lastCommandTs = millis();
}
shutterDriver->open();
}
void ShutterControl::close() {
if (lastCommand != SHUTTER_COMMAND_NONE) {
stopRequested = true;
} else {
shutterDriver->close();
lastCommand = SHUTTER_COMMAND_CLOSE;
lastCommandTs = millis();
}
shutterDriver->close();
}
void ShutterControl::setLevel(float level) {

float levelDiff = (level / 100.f) - currentLevel;
if (levelDiff < 0) {
stopTime = millis() - (totalTimeSpanMs * levelDiff);
close();
} else if (levelDiff > 0) {
stopTime = millis() + (totalTimeSpanMs * levelDiff);
open();
}
shutterDriver->level(level);
}

void ShutterControl::calibrate() {
Expand Down
27 changes: 5 additions & 22 deletions examples/shutter/io/ShutterControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,43 +33,26 @@
#include <HomeGenie.h>
#include <Utility.h>

#include "IShutterDriver.h"
#include "examples/shutter/io/drivers/ServoDriver.h"
// TODO: --> StepperDriver.h

#define SHUTTER_CONTROL_NS_PREFIX "IO::Components:ShutterControl"
#define SERVO_MODULE_ADDRESS "S1"

#define SHUTTER_COMMAND_NONE 0
#define SHUTTER_COMMAND_OPEN 1
#define SHUTTER_COMMAND_CLOSE 2

#define EVENT_EMIT_FREQUENCY 500
#include "drivers/ServoDriver.h"
#include "drivers/StepperDriver.h"

namespace IO { namespace Components {

using namespace Service;

class ShutterControl : Task, public IIOEventSender {
class ShutterControl : public IIOEventSender {
private:
IShutterDriver* shutterDriver;
int lastCommand = 0;
long lastCommandTs = 0;
String domain = IO::IOEventDomains::Automation_Components;
String address = SERVO_MODULE_ADDRESS;
float currentLevel = 0;
//
float totalTimeSpanMs = 10000.0f;
bool stopRequested = false;
float stopTime;
public:
ShutterControl() {
shutterDriver = new ServoDriver();
// setLoopInterval(33); // see Task.h
//shutterDriver = new StepperDriver();
shutterDriver->eventSender = this;
}

void begin() override;
void loop() override;

void open();
void close();
Expand Down
Loading

0 comments on commit f2cca1f

Please sign in to comment.