Skip to content

Commit

Permalink
v1.2.47
Browse files Browse the repository at this point in the history
- Added unified `ir-rf-transceiver` firmware
- Added `BOARD_HAS_RGB_LED` flag to enable onboard RGB status LED
- Enabled scheduling of X10 RF events
  • Loading branch information
genemars committed Jan 11, 2025
1 parent abca6c5 commit dd81e27
Show file tree
Hide file tree
Showing 18 changed files with 462 additions and 220 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/platformio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ jobs:
bash ./.github/post-build.sh
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
./artifacts/*.zip
generate_release_notes: true
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ cmake-build-debug
CMakeFiles
.idea
artifacts
managed_components
.dummy
CMakeLists.txt
sdkconfig.*
!sdkconfig.esp32
dependencies.lock

# Clion

Expand Down
104 changes: 45 additions & 59 deletions examples/color-light/color-fx.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* HomeGenie-Mini (c) 2018-2024 G-Labs
* HomeGenie-Mini (c) 2018-2025 G-Labs
*
*
* This file is part of HomeGenie-Mini (HGM).
Expand Down Expand Up @@ -63,37 +63,32 @@ float currentSaturation;
float cursorDirection = 1;
unsigned long rainbow_refresh_ts = 0;
void fx_rainbow(Adafruit_NeoPixel* pixels, LightColor& color, float iterations = 1) {
if (pixels == nullptr) return;
if (pixels == nullptr || millis() - rainbow_refresh_ts <= 100) return;

uint numPixels = pixels->numPixels();
currentSaturation = color.getSaturation();
float length = numPixels * hueZoom;

float hueStep = 1.0f / (float) length * iterations;

// animate
if (millis() - rainbow_refresh_ts > 100) {
rainbow_refresh_ts = millis();

float v = color.getValue();
for (int i = 0; i < numPixels; i++) {
float inc = (i < numPixels / iterations ? (float)i : (float)(numPixels - i)) * hueStep;
float h = FX_DEG_NORM((color.getHue() + hueOffset) + inc);
animatedColors[i]->setColor(h, currentSaturation, v, currentSaturation * 100);
}
float v = color.getValue();
for (int i = 0; i < numPixels; i++) {
float inc = (i < numPixels / iterations ? (float)i : (float)(numPixels - i)) * hueStep;
float h = FX_DEG_NORM((color.getHue() + hueOffset) + inc);
animatedColors[i]->setColor(h, currentSaturation, v, currentSaturation * 100);
}

// animate
hueOffset += hueStep;
if (hueOffset > 1) FX_DEG_NORM(hueOffset);
hueZoom += (0.05f * (float)cursorDirection);
if (hueZoom > 3) {
cursorDirection = -1;
} else if (hueZoom < 1) {
cursorDirection = 1;
hueZoom = 1;
}
hueOffset += hueStep;
if (hueOffset > 1) FX_DEG_NORM(hueOffset);
hueZoom += (0.05f * (float)cursorDirection);
if (hueZoom > 3) {
cursorDirection = -1;
} else if (hueZoom < 1) {
cursorDirection = 1;
hueZoom = 1;
}

rainbow_refresh_ts = millis();
}


Expand All @@ -105,64 +100,55 @@ float stripe_cycle = 0;
float stripe_previous_hue;

void fx_white_stripes(Adafruit_NeoPixel* pixels, LightColor& color, bool brightWhite = false) {
if (pixels == nullptr) return;
if (pixels == nullptr || millis() - stripe_refresh_ts <= stripe_delay) return;

uint numPixels = pixels->numPixels();
int stripe_length = (int)round((float)numPixels / 5.0f);
float shift;

// animate
if (millis() - stripe_refresh_ts > stripe_delay) {
if (stripe_length <= stripe_step) stripe_length = stripe_step * 2;

//shift = shift % stripe_length;
stripe_cycle += /*color.getValue() * */ ((float)stripe_length / (float)50);
if (stripe_cycle >= stripe_length) stripe_cycle = 0;

stripe_cycle += /*color.getValue() * */ ((float)stripe_length / (float)50);
if (stripe_cycle >= stripe_length) stripe_cycle = 0;
shift = ((float)stripe_length) + (stripe_cycle * cursorDirection);

shift = ((float)stripe_length) + (stripe_cycle * cursorDirection);
cursorDirection = (color.getHue() - stripe_previous_hue > 0) ? 1 : -1;
stripe_previous_hue = color.getHue();

cursorDirection = (color.getHue() - stripe_previous_hue > 0) ? 1 : -1;
stripe_previous_hue = color.getHue();

for (int i = 0; i < numPixels; i++) {
float v = color.getValue();
float s = color.getSaturation();
if ((int)round(i + shift) % stripe_length < stripe_step) {
// draw stripe
animatedColors[i]->setColor(0, 0, brightWhite && v > 0 ? 1 : v,
(float)stripe_transition / numPixels);
} else {
// draw solid color
animatedColors[i]->setColor(color.getHue(), s, v,
(float)stripe_transition * v);
}
for (int i = 0; i < numPixels; i++) {
float v = color.getValue();
float s = color.getSaturation();
if ((int)round(i + shift) % stripe_length < stripe_step) {
// draw stripe
animatedColors[i]->setColor(0, 0, brightWhite && v > 0 ? 1 : v,
(float)stripe_transition / numPixels);
} else {
// draw solid color
animatedColors[i]->setColor(color.getHue(), s, v,
(float)stripe_transition * v);
}

stripe_refresh_ts = millis();
}

stripe_refresh_ts = millis();
}


unsigned long kaleidoscope_refresh_ts = 0;
int kaleidoscope_delay = 500;

void fx_kaleidoscope(Adafruit_NeoPixel* pixels, LightColor& color) {
if (pixels == nullptr) return;
if (pixels == nullptr || millis() - kaleidoscope_refresh_ts <= kaleidoscope_delay) return;

// animate
if (millis() - kaleidoscope_refresh_ts > kaleidoscope_delay) {
for (int i = 0; i < pixels->numPixels(); i++) {
float rnd1 = random(1000);
float rnd2 = random(1000);
if ((int)rnd1 % 2 == 0) {
animatedColors[i]->setColor(color.getHue(), color.getSaturation(), color.getValue(), 300);
} else {
animatedColors[i]->setColor(rnd1 / 1000, rnd2 / 1000, color.getValue(), 500);
}
for (int i = 0; i < pixels->numPixels(); i++) {
float rnd1 = random(1000);
float rnd2 = random(1000);
if ((int)rnd1 % 2 == 0) {
animatedColors[i]->setColor(color.getHue(), color.getSaturation(), color.getValue(), 300);
} else {
animatedColors[i]->setColor(rnd1 / 1000, rnd2 / 1000, color.getValue(), 500);
}

kaleidoscope_refresh_ts = millis();
}

kaleidoscope_refresh_ts = millis();
}
25 changes: 7 additions & 18 deletions examples/color-light/color-light.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* HomeGenie-Mini (c) 2018-2024 G-Labs
* HomeGenie-Mini (c) 2018-2025 G-Labs
*
*
* This file is part of HomeGenie-Mini (HGM).
Expand Down Expand Up @@ -57,16 +57,7 @@ void setup() {
mpMaxPower = new ModuleParameter("LED.power", "25");
miniModule->properties.add(mpMaxPower);

// Get status LED config
auto pin = Config::getSetting("stld-pin");
int statusLedPin = pin.isEmpty() ? -1 : pin.toInt();
if (statusLedPin >= 0) {
int statusLedType = Config::getSetting("stld-typ", "82").toInt();
int statusLedSpeed = Config::getSetting("stld-spd", "0").toInt();
statusLED = new Adafruit_NeoPixel(1, statusLedPin, statusLedType + statusLedSpeed);
statusLED->setPixelColor(0, 0, 0, 0);
statusLED->begin();
}
colorLight = statusLedSetup();

isConfigured = Config::isDeviceConfigured();
if (!isConfigured) {
Expand Down Expand Up @@ -94,10 +85,6 @@ void setup() {
mpMaxPower->value = String(maxPower);

// Setup main LEDs control module
colorLight = new ColorLight(IO::IOEventDomains::HomeAutomation_HomeGenie, COLOR_LIGHT_ADDRESS, "Color Light");
colorLight->module->setProperty("Widget.Implements.Scheduling", "1");
colorLight->module->setProperty("Widget.Implements.Scheduling.ModuleEvents", "1");
colorLight->module->setProperty("Widget.Preference.AudioLight", "true");
colorLight->onSetColor([](LightColor color) {
currentColor = color;
fx_reset(pixels, color);
Expand Down Expand Up @@ -148,9 +135,6 @@ void loop()
{
homeGenie->loop();

// Custom status led (builtin NeoPixel RGB LED)
statusLedLoop();

if (isConfigured) {

if (millis() - lastRefreshTs > refreshMs)
Expand Down Expand Up @@ -246,4 +230,9 @@ void loop()
}

}

#ifdef BOARD_HAS_RGB_LED
// Custom status led (builtin NeoPixel RGB LED)
statusLedLoop();
#endif
}
59 changes: 53 additions & 6 deletions examples/color-light/status-led.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* HomeGenie-Mini (c) 2018-2024 G-Labs
* HomeGenie-Mini (c) 2018-2025 G-Labs
*
*
* This file is part of HomeGenie-Mini (HGM).
Expand All @@ -23,16 +23,29 @@
*
*/

#ifndef HOMEGENIE_MINI_STATUS_LED_H_
#define HOMEGENIE_MINI_STATUS_LED_H_

#include <Config.h>
#include <service/api/devices/ColorLight.h>

#include <Adafruit_NeoPixel.h>

#define COLOR_LIGHT_ADDRESS "C1"

using namespace Service::API::devices;

// Optional RGB Status LED
Adafruit_NeoPixel* statusLED = nullptr;
bool _statusLedWifiConnected = true;

// Blinks only first 20 seconds right after boot
unsigned long helloWorldDuration = 20000;
bool helloWorldActive = true;

// Status LED Blink callback used if statusLED is enabled
void statusLedCallback(bool isLedOn) {
if (statusLED == nullptr) return;
if (isLedOn) {
statusLED->setPixelColor(0, Adafruit_NeoPixel::Color(1, 1, 0));
} else {
Expand All @@ -41,13 +54,47 @@ void statusLedCallback(bool isLedOn) {
statusLED->show();
}

ColorLight* statusLedSetup() {

#ifdef BOARD_HAS_RGB_LED
// Get status LED config
auto pin = Config::getSetting("stld-pin");
int statusLedPin = pin.isEmpty() ? -1 : pin.toInt();
if (statusLedPin >= 0) {
int statusLedType = Config::getSetting("stld-typ", "82").toInt();
int statusLedSpeed = Config::getSetting("stld-spd", "0").toInt();
statusLED = new Adafruit_NeoPixel(1, statusLedPin, statusLedType + statusLedSpeed);
statusLED->setPixelColor(0, 0, 0, 0);
statusLED->begin();
Config::statusLedCallback(&statusLedCallback);
}
#endif
// Setup master LED control module
auto colorLight = new ColorLight(IO::IOEventDomains::HomeAutomation_HomeGenie, COLOR_LIGHT_ADDRESS, "Color Light");
colorLight->module->setProperty("Widget.Implements.Scheduling", "1");
colorLight->module->setProperty("Widget.Implements.Scheduling.ModuleEvents", "1");
colorLight->module->setProperty("Widget.Preference.AudioLight", "true");

return colorLight;
}

void statusLedLoop() {
if (statusLED != nullptr && WiFi.isConnected() != _statusLedWifiConnected) {
_statusLedWifiConnected = WiFi.isConnected();
if (_statusLedWifiConnected) {
if (statusLED != nullptr) {
if (helloWorldActive && millis() > helloWorldDuration && Config::isDeviceConfigured()) {
// stops blinking if "helloWorldDuration" is elapsed
helloWorldActive = false;
Config::statusLedCallback(nullptr);
} else {
Config::statusLedCallback(&statusLedCallback);
} else if (WiFi.isConnected() != _statusLedWifiConnected) {
_statusLedWifiConnected = WiFi.isConnected();
if (_statusLedWifiConnected) {
// turn off status LED blinking if connected
Config::statusLedCallback(nullptr);
} else {
// blinks status LED rapidly if not connected
Config::statusLedCallback(&statusLedCallback);
}
}
}
}

#endif
43 changes: 43 additions & 0 deletions examples/ir-rf-transceiver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# ir-rf-transceiver

A smart IR and RF (433/315MHz) gateway device.

- [Documentation and firmware install page](https://homegenie.it/mini/1.2/examples/ir-rf-gateway/)


## Firmware configuration

In addition to default system options the following configuration options are available:

| Key | Description | Default |
|------------|----------------------|-----------------------------------------|
| `stld-pin` | Status LED (RGB) pin | -1 (-1=not used) |
| `stld-typ` | Status LED type | RGB/RGBW order mask (see code for ref.) |
| `stld-spd` | Status LED speed | 0 (0=800kHz, 256=400kHz) |
| `irrc-pin` | IR Receiver GPIO # | 7 |
| `irtr-pin` | IR Transmitter GPIO# | 5 |
| `rfrc-pin` | RF Receiver GPIO # | 6 |
| `rftr-pin` | RF Transmitter GPIO# | 4 |


### Manual build and install

You can also manually build and install the firmware from source code
as explained in the [Getting started](../../getting-started#custom-firmware) page
and using the following commands for flashing the firmware:

```bash
pio run -e ir-transceiver[<target>] -t upload
```

where the optional `<target>` suffix can be one of the following:
- ESP8266
`-d1-mini`
- ESP32 (generic)
*none*
- ESP32-C3
`-c3`
- ESP32-S3
`-s3`
- ESP32 D1 Mini
`-d1-mini-esp32`
6 changes: 6 additions & 0 deletions examples/ir-rf-transceiver/configuration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Default config

#include "../ir-transceiver/configuration.h"
// TODO: verify if X10 and RCSwitch can share same module address
#include "../rf-transceiver/configuration.h"
#include "../x10-transceiver/configuration.h"
Loading

0 comments on commit dd81e27

Please sign in to comment.