mirror of
https://github.com/wled/WLED.git
synced 2025-07-22 18:26:32 +00:00
Merge pull request #4623 from willmmiles/more-usermod-fixes
More usermod fixes
This commit is contained in:
commit
d10714d1c1
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "ADS1115_v2",
|
"name": "ADS1115_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Adafruit BusIO": "https://github.com/adafruit/Adafruit_BusIO#1.13.2",
|
"Adafruit BusIO": "https://github.com/adafruit/Adafruit_BusIO#1.13.2",
|
||||||
"Adafruit ADS1X15": "https://github.com/adafruit/Adafruit_ADS1X15#2.4.0"
|
"Adafruit ADS1X15": "https://github.com/adafruit/Adafruit_ADS1X15#2.4.0"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "AHT10_v2",
|
"name": "AHT10_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"enjoyneering/AHT10":"~1.1.0"
|
"enjoyneering/AHT10":"~1.1.0"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "Analog_Clock"
|
"name": "Analog_Clock"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "Animated_Staircase"
|
"name": "Animated_Staircase"
|
||||||
}
|
}
|
@ -2,244 +2,176 @@
|
|||||||
#warning **** Included USERMOD_BH1750 ****
|
#warning **** Included USERMOD_BH1750 ****
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include <BH1750.h>
|
#include "BH1750_v2.h"
|
||||||
|
|
||||||
#ifdef WLED_DISABLE_MQTT
|
#ifdef WLED_DISABLE_MQTT
|
||||||
#error "This user mod requires MQTT to be enabled."
|
#error "This user mod requires MQTT to be enabled."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// the max frequency to check photoresistor, 10 seconds
|
static bool checkBoundSensor(float newValue, float prevValue, float maxDiff)
|
||||||
#ifndef USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL
|
|
||||||
#define USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// the min frequency to check photoresistor, 500 ms
|
|
||||||
#ifndef USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL
|
|
||||||
#define USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL 500
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// how many seconds after boot to take first measurement, 10 seconds
|
|
||||||
#ifndef USERMOD_BH1750_FIRST_MEASUREMENT_AT
|
|
||||||
#define USERMOD_BH1750_FIRST_MEASUREMENT_AT 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// only report if difference grater than offset value
|
|
||||||
#ifndef USERMOD_BH1750_OFFSET_VALUE
|
|
||||||
#define USERMOD_BH1750_OFFSET_VALUE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Usermod_BH1750 : public Usermod
|
|
||||||
{
|
{
|
||||||
private:
|
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff || (newValue == 0.0 && prevValue > 0.0);
|
||||||
int8_t offset = USERMOD_BH1750_OFFSET_VALUE;
|
}
|
||||||
|
|
||||||
unsigned long maxReadingInterval = USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL;
|
void Usermod_BH1750::_mqttInitialize()
|
||||||
unsigned long minReadingInterval = USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL;
|
{
|
||||||
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL - USERMOD_BH1750_FIRST_MEASUREMENT_AT);
|
mqttLuminanceTopic = String(mqttDeviceTopic) + F("/brightness");
|
||||||
unsigned long lastSend = UINT32_MAX - (USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL - USERMOD_BH1750_FIRST_MEASUREMENT_AT);
|
|
||||||
// flag to indicate we have finished the first readLightLevel call
|
|
||||||
// allows this library to report to the user how long until the first
|
|
||||||
// measurement
|
|
||||||
bool getLuminanceComplete = false;
|
|
||||||
|
|
||||||
// flag set at startup
|
if (HomeAssistantDiscovery) _createMqttSensor(F("Brightness"), mqttLuminanceTopic, F("Illuminance"), F(" lx"));
|
||||||
bool enabled = true;
|
}
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
|
||||||
static const char _name[];
|
void Usermod_BH1750::_createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
|
||||||
static const char _enabled[];
|
{
|
||||||
static const char _maxReadInterval[];
|
String t = String(F("homeassistant/sensor/")) + mqttClientID + F("/") + name + F("/config");
|
||||||
static const char _minReadInterval[];
|
|
||||||
static const char _offset[];
|
|
||||||
static const char _HomeAssistantDiscovery[];
|
|
||||||
|
|
||||||
bool initDone = false;
|
|
||||||
bool sensorFound = false;
|
|
||||||
|
|
||||||
// Home Assistant and MQTT
|
|
||||||
String mqttLuminanceTopic;
|
|
||||||
bool mqttInitialized = false;
|
|
||||||
bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages
|
|
||||||
|
|
||||||
BH1750 lightMeter;
|
|
||||||
float lastLux = -1000;
|
|
||||||
|
|
||||||
bool checkBoundSensor(float newValue, float prevValue, float maxDiff)
|
|
||||||
{
|
|
||||||
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff || (newValue == 0.0 && prevValue > 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up Home Assistant discovery entries
|
StaticJsonDocument<600> doc;
|
||||||
void _mqttInitialize()
|
|
||||||
{
|
doc[F("name")] = String(serverDescription) + " " + name;
|
||||||
mqttLuminanceTopic = String(mqttDeviceTopic) + F("/brightness");
|
doc[F("state_topic")] = topic;
|
||||||
|
doc[F("unique_id")] = String(mqttClientID) + name;
|
||||||
|
if (unitOfMeasurement != "")
|
||||||
|
doc[F("unit_of_measurement")] = unitOfMeasurement;
|
||||||
|
if (deviceClass != "")
|
||||||
|
doc[F("device_class")] = deviceClass;
|
||||||
|
doc[F("expire_after")] = 1800;
|
||||||
|
|
||||||
if (HomeAssistantDiscovery) _createMqttSensor(F("Brightness"), mqttLuminanceTopic, F("Illuminance"), F(" lx"));
|
JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device
|
||||||
|
device[F("name")] = serverDescription;
|
||||||
|
device[F("identifiers")] = "wled-sensor-" + String(mqttClientID);
|
||||||
|
device[F("manufacturer")] = F(WLED_BRAND);
|
||||||
|
device[F("model")] = F(WLED_PRODUCT_NAME);
|
||||||
|
device[F("sw_version")] = versionString;
|
||||||
|
|
||||||
|
String temp;
|
||||||
|
serializeJson(doc, temp);
|
||||||
|
DEBUG_PRINTLN(t);
|
||||||
|
DEBUG_PRINTLN(temp);
|
||||||
|
|
||||||
|
mqtt->publish(t.c_str(), 0, true, temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Usermod_BH1750::setup()
|
||||||
|
{
|
||||||
|
if (i2c_scl<0 || i2c_sda<0) { enabled = false; return; }
|
||||||
|
sensorFound = lightMeter.begin();
|
||||||
|
initDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Usermod_BH1750::loop()
|
||||||
|
{
|
||||||
|
if ((!enabled) || strip.isUpdating())
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
// check to see if we are due for taking a measurement
|
||||||
|
// lastMeasurement will not be updated until the conversion
|
||||||
|
// is complete the the reading is finished
|
||||||
|
if (now - lastMeasurement < minReadingInterval)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
|
bool shouldUpdate = now - lastSend > maxReadingInterval;
|
||||||
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
|
|
||||||
|
float lux = lightMeter.readLightLevel();
|
||||||
|
lastMeasurement = millis();
|
||||||
|
getLuminanceComplete = true;
|
||||||
|
|
||||||
|
if (shouldUpdate || checkBoundSensor(lux, lastLux, offset))
|
||||||
{
|
{
|
||||||
String t = String(F("homeassistant/sensor/")) + mqttClientID + F("/") + name + F("/config");
|
lastLux = lux;
|
||||||
|
lastSend = millis();
|
||||||
StaticJsonDocument<600> doc;
|
|
||||||
|
|
||||||
doc[F("name")] = String(serverDescription) + " " + name;
|
|
||||||
doc[F("state_topic")] = topic;
|
|
||||||
doc[F("unique_id")] = String(mqttClientID) + name;
|
|
||||||
if (unitOfMeasurement != "")
|
|
||||||
doc[F("unit_of_measurement")] = unitOfMeasurement;
|
|
||||||
if (deviceClass != "")
|
|
||||||
doc[F("device_class")] = deviceClass;
|
|
||||||
doc[F("expire_after")] = 1800;
|
|
||||||
|
|
||||||
JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device
|
if (WLED_MQTT_CONNECTED)
|
||||||
device[F("name")] = serverDescription;
|
{
|
||||||
device[F("identifiers")] = "wled-sensor-" + String(mqttClientID);
|
if (!mqttInitialized)
|
||||||
device[F("manufacturer")] = F(WLED_BRAND);
|
{
|
||||||
device[F("model")] = F(WLED_PRODUCT_NAME);
|
_mqttInitialize();
|
||||||
device[F("sw_version")] = versionString;
|
mqttInitialized = true;
|
||||||
|
}
|
||||||
String temp;
|
mqtt->publish(mqttLuminanceTopic.c_str(), 0, true, String(lux).c_str());
|
||||||
serializeJson(doc, temp);
|
DEBUG_PRINTLN(F("Brightness: ") + String(lux) + F("lx"));
|
||||||
DEBUG_PRINTLN(t);
|
}
|
||||||
DEBUG_PRINTLN(temp);
|
else
|
||||||
|
{
|
||||||
mqtt->publish(t.c_str(), 0, true, temp.c_str());
|
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
if (i2c_scl<0 || i2c_sda<0) { enabled = false; return; }
|
|
||||||
sensorFound = lightMeter.begin();
|
|
||||||
initDone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
void Usermod_BH1750::addToJsonInfo(JsonObject &root)
|
||||||
{
|
{
|
||||||
if ((!enabled) || strip.isUpdating())
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
JsonArray lux_json = user.createNestedArray(F("Luminance"));
|
||||||
|
if (!enabled) {
|
||||||
|
lux_json.add(F("disabled"));
|
||||||
|
} else if (!sensorFound) {
|
||||||
|
// if no sensor
|
||||||
|
lux_json.add(F("BH1750 "));
|
||||||
|
lux_json.add(F("Not Found"));
|
||||||
|
} else if (!getLuminanceComplete) {
|
||||||
|
// if we haven't read the sensor yet, let the user know
|
||||||
|
// that we are still waiting for the first measurement
|
||||||
|
lux_json.add((USERMOD_BH1750_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
||||||
|
lux_json.add(F(" sec until read"));
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
unsigned long now = millis();
|
lux_json.add(lastLux);
|
||||||
|
lux_json.add(F(" lx"));
|
||||||
// check to see if we are due for taking a measurement
|
|
||||||
// lastMeasurement will not be updated until the conversion
|
|
||||||
// is complete the the reading is finished
|
|
||||||
if (now - lastMeasurement < minReadingInterval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool shouldUpdate = now - lastSend > maxReadingInterval;
|
|
||||||
|
|
||||||
float lux = lightMeter.readLightLevel();
|
|
||||||
lastMeasurement = millis();
|
|
||||||
getLuminanceComplete = true;
|
|
||||||
|
|
||||||
if (shouldUpdate || checkBoundSensor(lux, lastLux, offset))
|
|
||||||
{
|
|
||||||
lastLux = lux;
|
|
||||||
lastSend = millis();
|
|
||||||
#ifndef WLED_DISABLE_MQTT
|
|
||||||
if (WLED_MQTT_CONNECTED)
|
|
||||||
{
|
|
||||||
if (!mqttInitialized)
|
|
||||||
{
|
|
||||||
_mqttInitialize();
|
|
||||||
mqttInitialized = true;
|
|
||||||
}
|
|
||||||
mqtt->publish(mqttLuminanceTopic.c_str(), 0, true, String(lux).c_str());
|
|
||||||
DEBUG_PRINTLN(F("Brightness: ") + String(lux) + F("lx"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline float getIlluminance() {
|
// (called from set.cpp) stores persistent properties to cfg.json
|
||||||
return (float)lastLux;
|
void Usermod_BH1750::addToConfig(JsonObject &root)
|
||||||
}
|
{
|
||||||
|
// we add JSON object.
|
||||||
|
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||||
|
top[FPSTR(_enabled)] = enabled;
|
||||||
|
top[FPSTR(_maxReadInterval)] = maxReadingInterval;
|
||||||
|
top[FPSTR(_minReadInterval)] = minReadingInterval;
|
||||||
|
top[FPSTR(_HomeAssistantDiscovery)] = HomeAssistantDiscovery;
|
||||||
|
top[FPSTR(_offset)] = offset;
|
||||||
|
|
||||||
void addToJsonInfo(JsonObject &root)
|
DEBUG_PRINTLN(F("BH1750 config saved."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// called before setup() to populate properties from values stored in cfg.json
|
||||||
|
bool Usermod_BH1750::readFromConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
// we look for JSON object.
|
||||||
|
JsonObject top = root[FPSTR(_name)];
|
||||||
|
if (top.isNull())
|
||||||
{
|
{
|
||||||
JsonObject user = root[F("u")];
|
|
||||||
if (user.isNull())
|
|
||||||
user = root.createNestedObject(F("u"));
|
|
||||||
|
|
||||||
JsonArray lux_json = user.createNestedArray(F("Luminance"));
|
|
||||||
if (!enabled) {
|
|
||||||
lux_json.add(F("disabled"));
|
|
||||||
} else if (!sensorFound) {
|
|
||||||
// if no sensor
|
|
||||||
lux_json.add(F("BH1750 "));
|
|
||||||
lux_json.add(F("Not Found"));
|
|
||||||
} else if (!getLuminanceComplete) {
|
|
||||||
// if we haven't read the sensor yet, let the user know
|
|
||||||
// that we are still waiting for the first measurement
|
|
||||||
lux_json.add((USERMOD_BH1750_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
|
||||||
lux_json.add(F(" sec until read"));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
lux_json.add(lastLux);
|
|
||||||
lux_json.add(F(" lx"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// (called from set.cpp) stores persistent properties to cfg.json
|
|
||||||
void addToConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
// we add JSON object.
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
|
||||||
top[FPSTR(_enabled)] = enabled;
|
|
||||||
top[FPSTR(_maxReadInterval)] = maxReadingInterval;
|
|
||||||
top[FPSTR(_minReadInterval)] = minReadingInterval;
|
|
||||||
top[FPSTR(_HomeAssistantDiscovery)] = HomeAssistantDiscovery;
|
|
||||||
top[FPSTR(_offset)] = offset;
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("BH1750 config saved."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// called before setup() to populate properties from values stored in cfg.json
|
|
||||||
bool readFromConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
// we look for JSON object.
|
|
||||||
JsonObject top = root[FPSTR(_name)];
|
|
||||||
if (top.isNull())
|
|
||||||
{
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
DEBUG_PRINT(F("BH1750"));
|
|
||||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool configComplete = !top.isNull();
|
|
||||||
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false);
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_maxReadInterval)], maxReadingInterval, 10000); //ms
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_minReadInterval)], minReadingInterval, 500); //ms
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_HomeAssistantDiscovery)], HomeAssistantDiscovery, false);
|
|
||||||
configComplete &= getJsonValue(top[FPSTR(_offset)], offset, 1);
|
|
||||||
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
if (!initDone) {
|
DEBUG_PRINT(F("BH1750"));
|
||||||
DEBUG_PRINTLN(F(" config loaded."));
|
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||||
} else {
|
return false;
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
}
|
||||||
}
|
bool configComplete = !top.isNull();
|
||||||
|
|
||||||
return configComplete;
|
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false);
|
||||||
|
configComplete &= getJsonValue(top[FPSTR(_maxReadInterval)], maxReadingInterval, 10000); //ms
|
||||||
|
configComplete &= getJsonValue(top[FPSTR(_minReadInterval)], minReadingInterval, 500); //ms
|
||||||
|
configComplete &= getJsonValue(top[FPSTR(_HomeAssistantDiscovery)], HomeAssistantDiscovery, false);
|
||||||
|
configComplete &= getJsonValue(top[FPSTR(_offset)], offset, 1);
|
||||||
|
|
||||||
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
|
if (!initDone) {
|
||||||
|
DEBUG_PRINTLN(F(" config loaded."));
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getId()
|
return configComplete;
|
||||||
{
|
|
||||||
return USERMOD_ID_BH1750;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
const char Usermod_BH1750::_name[] PROGMEM = "BH1750";
|
const char Usermod_BH1750::_name[] PROGMEM = "BH1750";
|
||||||
|
92
usermods/BH1750_v2/BH1750_v2.h
Normal file
92
usermods/BH1750_v2/BH1750_v2.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "wled.h"
|
||||||
|
#include <BH1750.h>
|
||||||
|
|
||||||
|
#ifdef WLED_DISABLE_MQTT
|
||||||
|
#error "This user mod requires MQTT to be enabled."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the max frequency to check photoresistor, 10 seconds
|
||||||
|
#ifndef USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL
|
||||||
|
#define USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// the min frequency to check photoresistor, 500 ms
|
||||||
|
#ifndef USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL
|
||||||
|
#define USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL 500
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// how many seconds after boot to take first measurement, 10 seconds
|
||||||
|
#ifndef USERMOD_BH1750_FIRST_MEASUREMENT_AT
|
||||||
|
#define USERMOD_BH1750_FIRST_MEASUREMENT_AT 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// only report if difference grater than offset value
|
||||||
|
#ifndef USERMOD_BH1750_OFFSET_VALUE
|
||||||
|
#define USERMOD_BH1750_OFFSET_VALUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Usermod_BH1750 : public Usermod
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int8_t offset = USERMOD_BH1750_OFFSET_VALUE;
|
||||||
|
|
||||||
|
unsigned long maxReadingInterval = USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL;
|
||||||
|
unsigned long minReadingInterval = USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL;
|
||||||
|
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL - USERMOD_BH1750_FIRST_MEASUREMENT_AT);
|
||||||
|
unsigned long lastSend = UINT32_MAX - (USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL - USERMOD_BH1750_FIRST_MEASUREMENT_AT);
|
||||||
|
// flag to indicate we have finished the first readLightLevel call
|
||||||
|
// allows this library to report to the user how long until the first
|
||||||
|
// measurement
|
||||||
|
bool getLuminanceComplete = false;
|
||||||
|
|
||||||
|
// flag set at startup
|
||||||
|
bool enabled = true;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _enabled[];
|
||||||
|
static const char _maxReadInterval[];
|
||||||
|
static const char _minReadInterval[];
|
||||||
|
static const char _offset[];
|
||||||
|
static const char _HomeAssistantDiscovery[];
|
||||||
|
|
||||||
|
bool initDone = false;
|
||||||
|
bool sensorFound = false;
|
||||||
|
|
||||||
|
// Home Assistant and MQTT
|
||||||
|
String mqttLuminanceTopic;
|
||||||
|
bool mqttInitialized = false;
|
||||||
|
bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages
|
||||||
|
|
||||||
|
BH1750 lightMeter;
|
||||||
|
float lastLux = -1000;
|
||||||
|
|
||||||
|
// set up Home Assistant discovery entries
|
||||||
|
void _mqttInitialize();
|
||||||
|
|
||||||
|
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
|
||||||
|
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup();
|
||||||
|
void loop();
|
||||||
|
inline float getIlluminance() {
|
||||||
|
return (float)lastLux;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToJsonInfo(JsonObject &root);
|
||||||
|
|
||||||
|
// (called from set.cpp) stores persistent properties to cfg.json
|
||||||
|
void addToConfig(JsonObject &root);
|
||||||
|
|
||||||
|
// called before setup() to populate properties from values stored in cfg.json
|
||||||
|
bool readFromConfig(JsonObject &root);
|
||||||
|
|
||||||
|
inline uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_BH1750;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "BH1750_v2",
|
"name": "BH1750_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"claws/BH1750":"^1.2.0"
|
"claws/BH1750":"^1.2.0"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "BME280_v2",
|
"name": "BME280_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"finitespace/BME280":"~3.0.0"
|
"finitespace/BME280":"~3.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @file usermod_BMW68X.h
|
* @file usermod_BMW68X.cpp
|
||||||
* @author Gabriel A. Sieben (GeoGab)
|
* @author Gabriel A. Sieben (GeoGab)
|
||||||
* @brief Usermod for WLED to implement the BME680/BME688 sensor
|
* @brief Usermod for WLED to implement the BME680/BME688 sensor
|
||||||
* @version 1.0.2
|
* @version 1.0.2
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "BME68X",
|
"name": "BME68X",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"boschsensortec/BSEC Software Library":"^1.8.1492"
|
"boschsensortec/BSEC Software Library":"^1.8.1492"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "Battery"
|
"name": "Battery"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "Cronixie"
|
"name": "Cronixie"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "DHT",
|
"name": "DHT",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"DHT_nonblocking":"https://github.com/alwynallan/DHT_nonblocking"
|
"DHT_nonblocking":"https://github.com/alwynallan/DHT_nonblocking"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name:": "EXAMPLE",
|
"name": "EXAMPLE",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name:": "Fix_unreachable_netservices_v2",
|
"name": "Fix_unreachable_netservices_v2",
|
||||||
"platforms": ["espressif8266"]
|
"platforms": ["espressif8266"]
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "INA226_v2",
|
"name": "INA226_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"wollewald/INA226_WE":"~1.2.9"
|
"wollewald/INA226_WE":"~1.2.9"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "Internal_Temperature_v2"
|
"name": "Internal_Temperature_v2"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "LD2410_v2",
|
"name": "LD2410_v2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ncmreynolds/ld2410":"^0.1.3"
|
"ncmreynolds/ld2410":"^0.1.3"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "LDR_Dusk_Dawn_v2"
|
"name": "LDR_Dusk_Dawn_v2"
|
||||||
}
|
}
|
@ -35,8 +35,8 @@ class Usermod_MAX17048 : public Usermod {
|
|||||||
unsigned long lastSend = UINT32_MAX - (USERMOD_MAX17048_MAX_MONITOR_INTERVAL - USERMOD_MAX17048_FIRST_MONITOR_AT);
|
unsigned long lastSend = UINT32_MAX - (USERMOD_MAX17048_MAX_MONITOR_INTERVAL - USERMOD_MAX17048_FIRST_MONITOR_AT);
|
||||||
|
|
||||||
|
|
||||||
uint8_t VoltageDecimals = 3; // Number of decimal places in published voltage values
|
unsigned VoltageDecimals = 3; // Number of decimal places in published voltage values
|
||||||
uint8_t PercentDecimals = 1; // Number of decimal places in published percent values
|
unsigned PercentDecimals = 1; // Number of decimal places in published percent values
|
||||||
|
|
||||||
// string that are used multiple time (this will save some flash memory)
|
// string that are used multiple time (this will save some flash memory)
|
||||||
static const char _name[];
|
static const char _name[];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "MAX17048_v2",
|
"name": "MAX17048_v2",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Adafruit_MAX1704X":"https://github.com/adafruit/Adafruit_MAX1704X#1.0.2"
|
"Adafruit_MAX1704X":"https://github.com/adafruit/Adafruit_MAX1704X#1.0.2"
|
@ -5,26 +5,16 @@ This usermod reads information from an Adafruit MAX17048 and outputs the follow
|
|||||||
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
Libraries:
|
|
||||||
- `Adafruit_BusIO@~1.14.5` (by [adafruit](https://github.com/adafruit/Adafruit_BusIO))
|
|
||||||
- `Adafruit_MAX1704X@~1.0.2` (by [adafruit](https://github.com/adafruit/Adafruit_MAX1704X))
|
|
||||||
|
|
||||||
These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
|
|
||||||
Data is published over MQTT - make sure you've enabled the MQTT sync interface.
|
Data is published over MQTT - make sure you've enabled the MQTT sync interface.
|
||||||
|
|
||||||
## Compilation
|
## Compilation
|
||||||
|
|
||||||
|
Add "MAX17048_v2" to your platformio.ini environment's custom_usermods and build.
|
||||||
To enable, compile with `USERMOD_MAX17048` define in the build_flags (e.g. in `platformio.ini` or `platformio_override.ini`) such as in the example below:
|
To enable, compile with `USERMOD_MAX17048` define in the build_flags (e.g. in `platformio.ini` or `platformio_override.ini`) such as in the example below:
|
||||||
```ini
|
```ini
|
||||||
[env:usermod_max17048_d1_mini]
|
[env:usermod_max17048_d1_mini]
|
||||||
extends = env:d1_mini
|
extends = env:d1_mini
|
||||||
build_flags =
|
custom_usermods = ${env:d1_mini.custom_usermods} MAX17048_v2
|
||||||
${common.build_flags_esp8266}
|
|
||||||
-D USERMOD_MAX17048
|
|
||||||
lib_deps =
|
|
||||||
${esp8266.lib_deps}
|
|
||||||
https://github.com/adafruit/Adafruit_BusIO @ 1.14.5
|
|
||||||
https://github.com/adafruit/Adafruit_MAX1704X @ 1.0.2
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration Options
|
### Configuration Options
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"name:": "MY9291",
|
"name": "MY9291",
|
||||||
"platforms": ["espressif8266"]
|
"platforms": ["espressif8266"]
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "PIR_sensor_switch"
|
"name": "PIR_sensor_switch"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "PWM_fan",
|
"name": "PWM_fan",
|
||||||
"build": {
|
"build": {
|
||||||
"extraScript": "setup_deps.py"
|
"extraScript": "setup_deps.py"
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,5 @@ if "Temperature" in usermods:
|
|||||||
env.Append(CPPDEFINES=[("USERMOD_DALLASTEMPERATURE")])
|
env.Append(CPPDEFINES=[("USERMOD_DALLASTEMPERATURE")])
|
||||||
elif "sht" in usermods:
|
elif "sht" in usermods:
|
||||||
env.Append(CPPDEFINES=[("USERMOD_SHT")])
|
env.Append(CPPDEFINES=[("USERMOD_SHT")])
|
||||||
else:
|
elif "PWM_fan" in usermods: # The script can be run if this module was previously selected
|
||||||
raise RuntimeError("PWM_fan usermod requires Temperature or sht to be enabled")
|
raise RuntimeError("PWM_fan usermod requires Temperature or sht to be enabled")
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "RTC"
|
"name": "RTC"
|
||||||
}
|
}
|
@ -1,204 +1,137 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#include "SN_Photoresistor.h"
|
||||||
|
|
||||||
//Pin defaults for QuinLed Dig-Uno (A0)
|
//Pin defaults for QuinLed Dig-Uno (A0)
|
||||||
#ifndef PHOTORESISTOR_PIN
|
#ifndef PHOTORESISTOR_PIN
|
||||||
#define PHOTORESISTOR_PIN A0
|
#define PHOTORESISTOR_PIN A0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// the frequency to check photoresistor, 10 seconds
|
static bool checkBoundSensor(float newValue, float prevValue, float maxDiff)
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// how many seconds after boot to take first measurement, 10 seconds
|
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// supplied voltage
|
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 10 bits
|
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_ADC_PRECISION
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_ADC_PRECISION 1024.0f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// resistor size 10K hms
|
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// only report if difference grater than offset value
|
|
||||||
#ifndef USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE
|
|
||||||
#define USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Usermod_SN_Photoresistor : public Usermod
|
|
||||||
{
|
{
|
||||||
private:
|
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff;
|
||||||
float referenceVoltage = USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE;
|
}
|
||||||
float resistorValue = USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE;
|
|
||||||
float adcPrecision = USERMOD_SN_PHOTORESISTOR_ADC_PRECISION;
|
|
||||||
int8_t offset = USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE;
|
|
||||||
|
|
||||||
unsigned long readingInterval = USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL;
|
uint16_t Usermod_SN_Photoresistor::getLuminance()
|
||||||
// set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
{
|
||||||
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT);
|
// http://forum.arduino.cc/index.php?topic=37555.0
|
||||||
// flag to indicate we have finished the first getTemperature call
|
// https://forum.arduino.cc/index.php?topic=185158.0
|
||||||
// allows this library to report to the user how long until the first
|
float volts = analogRead(PHOTORESISTOR_PIN) * (referenceVoltage / adcPrecision);
|
||||||
// measurement
|
float amps = volts / resistorValue;
|
||||||
bool getLuminanceComplete = false;
|
float lux = amps * 1000000 * 2.0;
|
||||||
uint16_t lastLDRValue = -1000;
|
|
||||||
|
|
||||||
// flag set at startup
|
lastMeasurement = millis();
|
||||||
bool disabled = false;
|
getLuminanceComplete = true;
|
||||||
|
return uint16_t(lux);
|
||||||
|
}
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
void Usermod_SN_Photoresistor::setup()
|
||||||
static const char _name[];
|
{
|
||||||
static const char _enabled[];
|
// set pinmode
|
||||||
static const char _readInterval[];
|
pinMode(PHOTORESISTOR_PIN, INPUT);
|
||||||
static const char _referenceVoltage[];
|
}
|
||||||
static const char _resistorValue[];
|
|
||||||
static const char _adcPrecision[];
|
|
||||||
static const char _offset[];
|
|
||||||
|
|
||||||
bool checkBoundSensor(float newValue, float prevValue, float maxDiff)
|
void Usermod_SN_Photoresistor::loop()
|
||||||
|
{
|
||||||
|
if (disabled || strip.isUpdating())
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
// check to see if we are due for taking a measurement
|
||||||
|
// lastMeasurement will not be updated until the conversion
|
||||||
|
// is complete the the reading is finished
|
||||||
|
if (now - lastMeasurement < readingInterval)
|
||||||
{
|
{
|
||||||
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getLuminance()
|
uint16_t currentLDRValue = getLuminance();
|
||||||
|
if (checkBoundSensor(currentLDRValue, lastLDRValue, offset))
|
||||||
{
|
{
|
||||||
// http://forum.arduino.cc/index.php?topic=37555.0
|
lastLDRValue = currentLDRValue;
|
||||||
// https://forum.arduino.cc/index.php?topic=185158.0
|
|
||||||
float volts = analogRead(PHOTORESISTOR_PIN) * (referenceVoltage / adcPrecision);
|
|
||||||
float amps = volts / resistorValue;
|
|
||||||
float lux = amps * 1000000 * 2.0;
|
|
||||||
|
|
||||||
lastMeasurement = millis();
|
|
||||||
getLuminanceComplete = true;
|
|
||||||
return uint16_t(lux);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
// set pinmode
|
|
||||||
pinMode(PHOTORESISTOR_PIN, INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (disabled || strip.isUpdating())
|
|
||||||
return;
|
|
||||||
|
|
||||||
unsigned long now = millis();
|
|
||||||
|
|
||||||
// check to see if we are due for taking a measurement
|
|
||||||
// lastMeasurement will not be updated until the conversion
|
|
||||||
// is complete the the reading is finished
|
|
||||||
if (now - lastMeasurement < readingInterval)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t currentLDRValue = getLuminance();
|
|
||||||
if (checkBoundSensor(currentLDRValue, lastLDRValue, offset))
|
|
||||||
{
|
|
||||||
lastLDRValue = currentLDRValue;
|
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MQTT
|
#ifndef WLED_DISABLE_MQTT
|
||||||
if (WLED_MQTT_CONNECTED)
|
if (WLED_MQTT_CONNECTED)
|
||||||
{
|
|
||||||
char subuf[45];
|
|
||||||
strcpy(subuf, mqttDeviceTopic);
|
|
||||||
strcat_P(subuf, PSTR("/luminance"));
|
|
||||||
mqtt->publish(subuf, 0, true, String(lastLDRValue).c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getLastLDRValue()
|
|
||||||
{
|
|
||||||
return lastLDRValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToJsonInfo(JsonObject &root)
|
|
||||||
{
|
|
||||||
JsonObject user = root[F("u")];
|
|
||||||
if (user.isNull())
|
|
||||||
user = root.createNestedObject(F("u"));
|
|
||||||
|
|
||||||
JsonArray lux = user.createNestedArray(F("Luminance"));
|
|
||||||
|
|
||||||
if (!getLuminanceComplete)
|
|
||||||
{
|
{
|
||||||
// if we haven't read the sensor yet, let the user know
|
char subuf[45];
|
||||||
// that we are still waiting for the first measurement
|
strcpy(subuf, mqttDeviceTopic);
|
||||||
lux.add((USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
strcat_P(subuf, PSTR("/luminance"));
|
||||||
lux.add(F(" sec until read"));
|
mqtt->publish(subuf, 0, true, String(lastLDRValue).c_str());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
lux.add(lastLDRValue);
|
{
|
||||||
lux.add(F(" lux"));
|
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t getId()
|
|
||||||
{
|
|
||||||
return USERMOD_ID_SN_PHOTORESISTOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
|
||||||
*/
|
|
||||||
void addToConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
// we add JSON object.
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
|
||||||
top[FPSTR(_enabled)] = !disabled;
|
|
||||||
top[FPSTR(_readInterval)] = readingInterval / 1000;
|
|
||||||
top[FPSTR(_referenceVoltage)] = referenceVoltage;
|
|
||||||
top[FPSTR(_resistorValue)] = resistorValue;
|
|
||||||
top[FPSTR(_adcPrecision)] = adcPrecision;
|
|
||||||
top[FPSTR(_offset)] = offset;
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Photoresistor config saved."));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
|
||||||
*/
|
|
||||||
bool readFromConfig(JsonObject &root)
|
|
||||||
{
|
|
||||||
// we look for JSON object.
|
|
||||||
JsonObject top = root[FPSTR(_name)];
|
|
||||||
if (top.isNull()) {
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
disabled = !(top[FPSTR(_enabled)] | !disabled);
|
|
||||||
readingInterval = (top[FPSTR(_readInterval)] | readingInterval/1000) * 1000; // convert to ms
|
void Usermod_SN_Photoresistor::addToJsonInfo(JsonObject &root)
|
||||||
referenceVoltage = top[FPSTR(_referenceVoltage)] | referenceVoltage;
|
{
|
||||||
resistorValue = top[FPSTR(_resistorValue)] | resistorValue;
|
JsonObject user = root[F("u")];
|
||||||
adcPrecision = top[FPSTR(_adcPrecision)] | adcPrecision;
|
if (user.isNull())
|
||||||
offset = top[FPSTR(_offset)] | offset;
|
user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
JsonArray lux = user.createNestedArray(F("Luminance"));
|
||||||
|
|
||||||
|
if (!getLuminanceComplete)
|
||||||
|
{
|
||||||
|
// if we haven't read the sensor yet, let the user know
|
||||||
|
// that we are still waiting for the first measurement
|
||||||
|
lux.add((USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
||||||
|
lux.add(F(" sec until read"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lux.add(lastLDRValue);
|
||||||
|
lux.add(F(" lux"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
||||||
|
*/
|
||||||
|
void Usermod_SN_Photoresistor::addToConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
// we add JSON object.
|
||||||
|
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||||
|
top[FPSTR(_enabled)] = !disabled;
|
||||||
|
top[FPSTR(_readInterval)] = readingInterval / 1000;
|
||||||
|
top[FPSTR(_referenceVoltage)] = referenceVoltage;
|
||||||
|
top[FPSTR(_resistorValue)] = resistorValue;
|
||||||
|
top[FPSTR(_adcPrecision)] = adcPrecision;
|
||||||
|
top[FPSTR(_offset)] = offset;
|
||||||
|
|
||||||
|
DEBUG_PRINTLN(F("Photoresistor config saved."));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
||||||
|
*/
|
||||||
|
bool Usermod_SN_Photoresistor::readFromConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
// we look for JSON object.
|
||||||
|
JsonObject top = root[FPSTR(_name)];
|
||||||
|
if (top.isNull()) {
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||||
|
return false;
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
disabled = !(top[FPSTR(_enabled)] | !disabled);
|
||||||
|
readingInterval = (top[FPSTR(_readInterval)] | readingInterval/1000) * 1000; // convert to ms
|
||||||
|
referenceVoltage = top[FPSTR(_referenceVoltage)] | referenceVoltage;
|
||||||
|
resistorValue = top[FPSTR(_resistorValue)] | resistorValue;
|
||||||
|
adcPrecision = top[FPSTR(_adcPrecision)] | adcPrecision;
|
||||||
|
offset = top[FPSTR(_offset)] | offset;
|
||||||
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
|
|
||||||
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
const char Usermod_SN_Photoresistor::_name[] PROGMEM = "Photoresistor";
|
const char Usermod_SN_Photoresistor::_name[] PROGMEM = "Photoresistor";
|
||||||
@ -209,6 +142,5 @@ const char Usermod_SN_Photoresistor::_resistorValue[] PROGMEM = "resistor-value"
|
|||||||
const char Usermod_SN_Photoresistor::_adcPrecision[] PROGMEM = "adc-precision";
|
const char Usermod_SN_Photoresistor::_adcPrecision[] PROGMEM = "adc-precision";
|
||||||
const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset";
|
const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset";
|
||||||
|
|
||||||
|
|
||||||
static Usermod_SN_Photoresistor sn_photoresistor;
|
static Usermod_SN_Photoresistor sn_photoresistor;
|
||||||
REGISTER_USERMOD(sn_photoresistor);
|
REGISTER_USERMOD(sn_photoresistor);
|
90
usermods/SN_Photoresistor/SN_Photoresistor.h
Normal file
90
usermods/SN_Photoresistor/SN_Photoresistor.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "wled.h"
|
||||||
|
|
||||||
|
// the frequency to check photoresistor, 10 seconds
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// how many seconds after boot to take first measurement, 10 seconds
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// supplied voltage
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 10 bits
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_ADC_PRECISION
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_ADC_PRECISION 1024.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// resistor size 10K hms
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// only report if difference grater than offset value
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Usermod_SN_Photoresistor : public Usermod
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float referenceVoltage = USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE;
|
||||||
|
float resistorValue = USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE;
|
||||||
|
float adcPrecision = USERMOD_SN_PHOTORESISTOR_ADC_PRECISION;
|
||||||
|
int8_t offset = USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE;
|
||||||
|
|
||||||
|
unsigned long readingInterval = USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL;
|
||||||
|
// set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||||
|
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT);
|
||||||
|
// flag to indicate we have finished the first getTemperature call
|
||||||
|
// allows this library to report to the user how long until the first
|
||||||
|
// measurement
|
||||||
|
bool getLuminanceComplete = false;
|
||||||
|
uint16_t lastLDRValue = 65535;
|
||||||
|
|
||||||
|
// flag set at startup
|
||||||
|
bool disabled = false;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _enabled[];
|
||||||
|
static const char _readInterval[];
|
||||||
|
static const char _referenceVoltage[];
|
||||||
|
static const char _resistorValue[];
|
||||||
|
static const char _adcPrecision[];
|
||||||
|
static const char _offset[];
|
||||||
|
|
||||||
|
uint16_t getLuminance();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup();
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
uint16_t getLastLDRValue()
|
||||||
|
{
|
||||||
|
return lastLDRValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToJsonInfo(JsonObject &root);
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_SN_PHOTORESISTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
||||||
|
*/
|
||||||
|
void addToConfig(JsonObject &root);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
||||||
|
*/
|
||||||
|
bool readFromConfig(JsonObject &root);
|
||||||
|
};
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "SN_Photoresistor"
|
"name": "SN_Photoresistor"
|
||||||
}
|
}
|
@ -1,14 +0,0 @@
|
|||||||
#include "wled.h"
|
|
||||||
/*
|
|
||||||
* Register your v2 usermods here!
|
|
||||||
*/
|
|
||||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
|
||||||
#include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void registerUsermods()
|
|
||||||
{
|
|
||||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
|
||||||
UsermodManager::add(new Usermod_SN_Photoresistor());
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "Si7021_MQTT_HA",
|
"name": "Si7021_MQTT_HA",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"finitespace/BME280":"3.0.0",
|
"finitespace/BME280":"3.0.0",
|
||||||
"adafruit/Adafruit Si7021 Library" : "1.5.3"
|
"adafruit/Adafruit Si7021 Library" : "1.5.3"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "Temperature",
|
"name": "Temperature",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"paulstoffregen/OneWire":"~2.3.8"
|
"paulstoffregen/OneWire":"~2.3.8"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "TetrisAI_v2"
|
"name": "TetrisAI_v2"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "VL53L0X_gestures",
|
"name": "VL53L0X_gestures",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pololu/VL53L0X" : "^1.3.0"
|
"pololu/VL53L0X" : "^1.3.0"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "boblight"
|
"name": "boblight"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "buzzer"
|
"name": "buzzer"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "deep_sleep"
|
"name": "deep_sleep"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "mpu6050_imu",
|
"name": "mpu6050_imu",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electroniccats/MPU6050":"1.0.1"
|
"electroniccats/MPU6050":"1.0.1"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "multi_relay"
|
"name": "multi_relay"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "pixels_dice_tray",
|
"name": "pixels_dice_tray",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"arduino-pixels-dice":"https://github.com/axlan/arduino-pixels-dice.git",
|
"arduino-pixels-dice":"https://github.com/axlan/arduino-pixels-dice.git",
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "pwm_outputs"
|
"name": "pwm_outputs"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "quinled-an-penta",
|
"name": "quinled-an-penta",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"olikraus/U8g2":"~2.28.8",
|
"olikraus/U8g2":"~2.28.8",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "rgb-rotary-encoder",
|
"name": "rgb-rotary-encoder",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lennarthennigs/ESP Rotary":"^2.1.1"
|
"lennarthennigs/ESP Rotary":"^2.1.1"
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "sd_card"
|
"name": "sd_card"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "sensors_to_mqtt",
|
"name": "sensors_to_mqtt",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adafruit/Adafruit BMP280 Library":"2.6.8",
|
"adafruit/Adafruit BMP280 Library":"2.6.8",
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "seven_segment_display"
|
"name": "seven_segment_display"
|
||||||
}
|
}
|
@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name:": "seven_segment_display_reloaded"
|
"name": "seven_segment_display_reloaded",
|
||||||
|
"build": {
|
||||||
|
"extraScript": "setup_deps.py"
|
||||||
|
}
|
||||||
}
|
}
|
9
usermods/seven_segment_display_reloaded/setup_deps.py
Normal file
9
usermods/seven_segment_display_reloaded/setup_deps.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Import('env')
|
||||||
|
|
||||||
|
|
||||||
|
usermods = env.GetProjectOption("custom_usermods","").split()
|
||||||
|
# Check for partner usermods
|
||||||
|
if "SN_Photoresistor" in usermods:
|
||||||
|
env.Append(CPPDEFINES=[("USERMOD_SN_PHOTORESISTOR")])
|
||||||
|
if any(mod in ("BH1750_v2", "BH1750") for mod in usermods):
|
||||||
|
env.Append(CPPDEFINES=[("USERMOD_BH1750")])
|
@ -1,4 +1,10 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||||
|
#include "SN_Photoresistor.h"
|
||||||
|
#endif
|
||||||
|
#ifdef USERMOD_BH1750
|
||||||
|
#include "BH1750_v2.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_DISABLE_MQTT
|
#ifdef WLED_DISABLE_MQTT
|
||||||
#error "This user mod requires MQTT to be enabled."
|
#error "This user mod requires MQTT to be enabled."
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "sht",
|
"name": "sht",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"robtillaart/SHT85": "~0.3.3"
|
"robtillaart/SHT85": "~0.3.3"
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "smartnest"
|
"name": "smartnest"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "stairway_wipe_basic"
|
"name": "stairway_wipe_basic"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_rotary_brightness_color"
|
"name": "usermod_rotary_brightness_color"
|
||||||
}
|
}
|
3
usermods/usermod_v2_HttpPullLightControl/library.json
Normal file
3
usermods/usermod_v2_HttpPullLightControl/library.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "usermod_v2_HttpPullLightControl"
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"name:": "usermod_v2_HttpPullLightControl"
|
|
||||||
}
|
|
@ -297,10 +297,10 @@ void HttpPullLightControl::handleResponse(String& responseStr) {
|
|||||||
// Check for valid JSON, otherwise we brick the program runtime
|
// Check for valid JSON, otherwise we brick the program runtime
|
||||||
if (jsonStr[0] == '{' || jsonStr[0] == '[') {
|
if (jsonStr[0] == '{' || jsonStr[0] == '[') {
|
||||||
// Attempt to deserialize the JSON response
|
// Attempt to deserialize the JSON response
|
||||||
DeserializationError error = deserializeJson(doc, jsonStr);
|
DeserializationError error = deserializeJson(*pDoc, jsonStr);
|
||||||
if (error == DeserializationError::Ok) {
|
if (error == DeserializationError::Ok) {
|
||||||
// Get JSON object from th doc
|
// Get JSON object from th doc
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = pDoc->as<JsonObject>();
|
||||||
// Parse the object throuhg deserializeState (use CALL_MODE_NO_NOTIFY or OR CALL_MODE_DIRECT_CHANGE)
|
// Parse the object throuhg deserializeState (use CALL_MODE_NO_NOTIFY or OR CALL_MODE_DIRECT_CHANGE)
|
||||||
deserializeState(obj, CALL_MODE_NO_NOTIFY);
|
deserializeState(obj, CALL_MODE_NO_NOTIFY);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_v2_RF433",
|
"name": "usermod_v2_RF433",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sui77/rc-switch":"2.6.4"
|
"sui77/rc-switch":"2.6.4"
|
||||||
}
|
}
|
||||||
|
3
usermods/usermod_v2_brightness_follow_sun/library.json
Normal file
3
usermods/usermod_v2_brightness_follow_sun/library.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "brightness_follow_sun"
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
//v2 usermod that allows to change brightness and color using a rotary encoder,
|
//v2 usermod that allows to change brightness and color using a rotary encoder,
|
||||||
@ -128,3 +126,6 @@ const char UsermodBrightnessFollowSun::_update_interval[] PROGMEM = "Update
|
|||||||
const char UsermodBrightnessFollowSun::_min_bri[] PROGMEM = "Min Brightness";
|
const char UsermodBrightnessFollowSun::_min_bri[] PROGMEM = "Min Brightness";
|
||||||
const char UsermodBrightnessFollowSun::_max_bri[] PROGMEM = "Max Brightness";
|
const char UsermodBrightnessFollowSun::_max_bri[] PROGMEM = "Max Brightness";
|
||||||
const char UsermodBrightnessFollowSun::_relax_hour[] PROGMEM = "Relax Hour";
|
const char UsermodBrightnessFollowSun::_relax_hour[] PROGMEM = "Relax Hour";
|
||||||
|
|
||||||
|
static UsermodBrightnessFollowSun usermod_brightness_follow_sun;
|
||||||
|
REGISTER_USERMOD(usermod_brightness_follow_sun);
|
@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
//WLED custom fonts, curtesy of @Benji (https://github.com/Proto-molecule)
|
//WLED custom fonts, curtesy of @Benji (https://github.com/Proto-molecule)
|
||||||
|
#pragma once
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Fontname: wled_logo_akemi_4x4
|
Fontname: wled_logo_akemi_4x4
|
7
usermods/usermod_v2_four_line_display_ALT/library.json
Normal file
7
usermods/usermod_v2_four_line_display_ALT/library.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "four_line_display_ALT",
|
||||||
|
"dependencies": {
|
||||||
|
"U8g2": "~2.34.4",
|
||||||
|
"Wire": ""
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"name:": "usermod_v2_four_line_display_ALT"
|
|
||||||
}
|
|
@ -1,18 +1,11 @@
|
|||||||
[platformio]
|
[platformio]
|
||||||
default_envs = esp32dev
|
default_envs = esp32dev_fld
|
||||||
|
|
||||||
[env:esp32dev]
|
[env:esp32dev_fld]
|
||||||
board = esp32dev
|
extends = env:esp32dev_V4
|
||||||
platform = ${esp32.platform}
|
custom_usermods = ${env:esp32dev_V4.custom_usermods} four_line_display_ALT
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${common.build_flags_esp32}
|
${env:esp32dev_V4.build_flags}
|
||||||
-D USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
-D FLD_TYPE=SH1106
|
-D FLD_TYPE=SH1106
|
||||||
-D I2CSCLPIN=27
|
-D I2CSCLPIN=27
|
||||||
-D I2CSDAPIN=26
|
-D I2CSDAPIN=26
|
||||||
|
|
||||||
lib_deps =
|
|
||||||
${esp32.lib_deps}
|
|
||||||
U8g2@~2.34.4
|
|
||||||
Wire
|
|
||||||
|
@ -0,0 +1,315 @@
|
|||||||
|
#include "wled.h"
|
||||||
|
#undef U8X8_NO_HW_I2C // borrowed from WLEDMM: we do want I2C hardware drivers - if possible
|
||||||
|
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FLD_ESP32_NO_THREADS
|
||||||
|
#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behaviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FLD_PIN_CS
|
||||||
|
#define FLD_PIN_CS 15
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#ifndef FLD_PIN_DC
|
||||||
|
#define FLD_PIN_DC 19
|
||||||
|
#endif
|
||||||
|
#ifndef FLD_PIN_RESET
|
||||||
|
#define FLD_PIN_RESET 26
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifndef FLD_PIN_DC
|
||||||
|
#define FLD_PIN_DC 12
|
||||||
|
#endif
|
||||||
|
#ifndef FLD_PIN_RESET
|
||||||
|
#define FLD_PIN_RESET 16
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FLD_TYPE
|
||||||
|
#ifndef FLD_SPI_DEFAULT
|
||||||
|
#define FLD_TYPE SSD1306
|
||||||
|
#else
|
||||||
|
#define FLD_TYPE SSD1306_SPI
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// When to time out to the clock or blank the screen
|
||||||
|
// if SLEEP_MODE_ENABLED.
|
||||||
|
#define SCREEN_TIMEOUT_MS 60*1000 // 1 min
|
||||||
|
|
||||||
|
// Minimum time between redrawing screen in ms
|
||||||
|
#define REFRESH_RATE_MS 1000
|
||||||
|
|
||||||
|
// Extra char (+1) for null
|
||||||
|
#define LINE_BUFFER_SIZE 16+1
|
||||||
|
#define MAX_JSON_CHARS 19+1
|
||||||
|
#define MAX_MODE_LINE_SPACE 13+1
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NONE = 0,
|
||||||
|
SSD1306, // U8X8_SSD1306_128X32_UNIVISION_HW_I2C
|
||||||
|
SH1106, // U8X8_SH1106_128X64_WINSTAR_HW_I2C
|
||||||
|
SSD1306_64, // U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||||
|
SSD1305, // U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C
|
||||||
|
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
|
||||||
|
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
|
||||||
|
SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI
|
||||||
|
SSD1309_SPI64, // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI
|
||||||
|
SSD1309_64 // U8X8_SSD1309_128X64_NONAME0_HW_I2C
|
||||||
|
} DisplayType;
|
||||||
|
|
||||||
|
class FourLineDisplayUsermod : public Usermod {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
||||||
|
public:
|
||||||
|
FourLineDisplayUsermod() { if (!instance) instance = this; }
|
||||||
|
static FourLineDisplayUsermod* getInstance(void) { return instance; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static FourLineDisplayUsermod *instance;
|
||||||
|
bool initDone = false;
|
||||||
|
volatile bool drawing = false;
|
||||||
|
volatile bool lockRedraw = false;
|
||||||
|
|
||||||
|
// HW interface & configuration
|
||||||
|
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
|
||||||
|
|
||||||
|
#ifndef FLD_SPI_DEFAULT
|
||||||
|
int8_t ioPin[3] = {-1, -1, -1}; // I2C pins: SCL, SDA
|
||||||
|
uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000)
|
||||||
|
#else
|
||||||
|
int8_t ioPin[3] = {FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET}; // custom SPI pins: CS, DC, RST
|
||||||
|
uint32_t ioFrequency = 1000000; // in Hz (minimum is 500kHz, baseline is 1MHz and maximum should be 20MHz)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DisplayType type = FLD_TYPE; // display type
|
||||||
|
bool flip = false; // flip display 180°
|
||||||
|
uint8_t contrast = 10; // screen contrast
|
||||||
|
uint8_t lineHeight = 1; // 1 row or 2 rows
|
||||||
|
uint16_t refreshRate = REFRESH_RATE_MS; // in ms
|
||||||
|
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
|
||||||
|
bool sleepMode = true; // allow screen sleep?
|
||||||
|
bool clockMode = false; // display clock
|
||||||
|
bool showSeconds = true; // display clock with seconds
|
||||||
|
bool enabled = true;
|
||||||
|
bool contrastFix = false;
|
||||||
|
|
||||||
|
// Next variables hold the previous known values to determine if redraw is
|
||||||
|
// required.
|
||||||
|
String knownSsid = apSSID;
|
||||||
|
IPAddress knownIp = IPAddress(4, 3, 2, 1);
|
||||||
|
uint8_t knownBrightness = 0;
|
||||||
|
uint8_t knownEffectSpeed = 0;
|
||||||
|
uint8_t knownEffectIntensity = 0;
|
||||||
|
uint8_t knownMode = 0;
|
||||||
|
uint8_t knownPalette = 0;
|
||||||
|
uint8_t knownMinute = 99;
|
||||||
|
uint8_t knownHour = 99;
|
||||||
|
byte brightness100;
|
||||||
|
byte fxspeed100;
|
||||||
|
byte fxintensity100;
|
||||||
|
bool knownnightlight = nightlightActive;
|
||||||
|
bool wificonnected = interfacesInited;
|
||||||
|
bool powerON = true;
|
||||||
|
|
||||||
|
bool displayTurnedOff = false;
|
||||||
|
unsigned long nextUpdate = 0;
|
||||||
|
unsigned long lastRedraw = 0;
|
||||||
|
unsigned long overlayUntil = 0;
|
||||||
|
|
||||||
|
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
|
||||||
|
byte markLineNum = 255;
|
||||||
|
byte markColNum = 255;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _enabled[];
|
||||||
|
static const char _contrast[];
|
||||||
|
static const char _refreshRate[];
|
||||||
|
static const char _screenTimeOut[];
|
||||||
|
static const char _flip[];
|
||||||
|
static const char _sleepMode[];
|
||||||
|
static const char _clockMode[];
|
||||||
|
static const char _showSeconds[];
|
||||||
|
static const char _busClkFrequency[];
|
||||||
|
static const char _contrastFix[];
|
||||||
|
|
||||||
|
// If display does not work or looks corrupted check the
|
||||||
|
// constructor reference:
|
||||||
|
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||||
|
// or check the gallery:
|
||||||
|
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||||
|
|
||||||
|
// some displays need this to properly apply contrast
|
||||||
|
void setVcomh(bool highContrast);
|
||||||
|
void startDisplay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrappers for screen drawing
|
||||||
|
*/
|
||||||
|
void setFlipMode(uint8_t mode);
|
||||||
|
void setContrast(uint8_t contrast);
|
||||||
|
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false);
|
||||||
|
void draw2x2String(uint8_t col, uint8_t row, const char *string);
|
||||||
|
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false);
|
||||||
|
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font);
|
||||||
|
void draw2x2GlyphIcons();
|
||||||
|
uint8_t getCols();
|
||||||
|
void clear();
|
||||||
|
void setPowerSave(uint8_t save);
|
||||||
|
void center(String &line, uint8_t width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the current date and time in large characters
|
||||||
|
* on the middle rows. Based 24 or 12 hour depending on
|
||||||
|
* the useAMPM configuration.
|
||||||
|
*/
|
||||||
|
void showTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable sleep (turn the display off) or clock mode.
|
||||||
|
*/
|
||||||
|
void sleepOrClock(bool enabled);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// gets called once at boot. Do all initialization that doesn't depend on
|
||||||
|
// network here
|
||||||
|
void setup() override;
|
||||||
|
|
||||||
|
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||||
|
// interfaces here
|
||||||
|
void connected() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Da loop.
|
||||||
|
*/
|
||||||
|
void loop() override;
|
||||||
|
|
||||||
|
//function to update lastredraw
|
||||||
|
inline void updateRedrawTime() { lastRedraw = millis(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redraw the screen (but only if things have changed
|
||||||
|
* or if forceRedraw).
|
||||||
|
*/
|
||||||
|
void redraw(bool forceRedraw);
|
||||||
|
|
||||||
|
void updateBrightness();
|
||||||
|
void updateSpeed();
|
||||||
|
void updateIntensity();
|
||||||
|
void drawStatusIcons();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* marks the position of the arrow showing
|
||||||
|
* the current setting being changed
|
||||||
|
* pass line and colum info
|
||||||
|
*/
|
||||||
|
void setMarkLine(byte newMarkLineNum, byte newMarkColNum);
|
||||||
|
|
||||||
|
//Draw the arrow for the current setting being changed
|
||||||
|
void drawArrow();
|
||||||
|
|
||||||
|
//Display the current effect or palette (desiredEntry)
|
||||||
|
// on the appropriate line (row).
|
||||||
|
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there screen is off or in clock is displayed,
|
||||||
|
* this will return true. This allows us to throw away
|
||||||
|
* the first input from the rotary encoder but
|
||||||
|
* to wake up the screen.
|
||||||
|
*/
|
||||||
|
bool wakeDisplay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to show one line and a glyph as overlay for a period of time.
|
||||||
|
* Clears the screen and prints.
|
||||||
|
* Used in Rotary Encoder usermod.
|
||||||
|
*/
|
||||||
|
void overlay(const char* line1, long showHowLong, byte glyphType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to show Akemi WLED logo overlay for a period of time.
|
||||||
|
* Clears the screen and prints.
|
||||||
|
*/
|
||||||
|
void overlayLogo(long showHowLong);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to show two lines as overlay for a period of time.
|
||||||
|
* Clears the screen and prints.
|
||||||
|
* Used in Auto Save usermod
|
||||||
|
*/
|
||||||
|
void overlay(const char* line1, const char* line2, long showHowLong);
|
||||||
|
|
||||||
|
void networkOverlay(const char* line1, long showHowLong);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handleButton() can be used to override default button behaviour. Returning true
|
||||||
|
* will prevent button working in a default way.
|
||||||
|
* Replicating button.cpp
|
||||||
|
*/
|
||||||
|
bool handleButton(uint8_t b);
|
||||||
|
|
||||||
|
void onUpdateBegin(bool init) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||||
|
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||||
|
* Below it is shown how this could be used for e.g. a light sensor
|
||||||
|
*/
|
||||||
|
//void addToJsonInfo(JsonObject& root) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||||
|
* Values in the state object may be modified by connected clients
|
||||||
|
*/
|
||||||
|
//void addToJsonState(JsonObject& root) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
||||||
|
* Values in the state object may be modified by connected clients
|
||||||
|
*/
|
||||||
|
//void readFromJsonState(JsonObject& root) override;
|
||||||
|
|
||||||
|
void appendConfigData() override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||||
|
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||||
|
* If you want to force saving the current state, use serializeConfig() in your loop().
|
||||||
|
*
|
||||||
|
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
||||||
|
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
||||||
|
* Use it sparingly and always in the loop, never in network callbacks!
|
||||||
|
*
|
||||||
|
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
||||||
|
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
||||||
|
*
|
||||||
|
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||||
|
*/
|
||||||
|
void addToConfig(JsonObject& root) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
||||||
|
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
||||||
|
*
|
||||||
|
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
||||||
|
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
||||||
|
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
||||||
|
*/
|
||||||
|
bool readFromConfig(JsonObject& root) override;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||||
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||||
|
*/
|
||||||
|
uint16_t getId() override {
|
||||||
|
return USERMOD_ID_FOUR_LINE_DISP;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,11 +1,5 @@
|
|||||||
#include "wled.h"
|
#include "usermod_v2_four_line_display.h"
|
||||||
#undef U8X8_NO_HW_I2C // borrowed from WLEDMM: we do want I2C hardware drivers - if possible
|
#include "4LD_wled_fonts.h"
|
||||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
|
||||||
#include "4LD_wled_fonts.c"
|
|
||||||
|
|
||||||
#ifndef FLD_ESP32_NO_THREADS
|
|
||||||
#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behaviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Inspired by the usermod_v2_four_line_display
|
// Inspired by the usermod_v2_four_line_display
|
||||||
@ -20,330 +14,18 @@
|
|||||||
//
|
//
|
||||||
// Make sure to enable NTP and set your time zone in WLED Config | Time.
|
// Make sure to enable NTP and set your time zone in WLED Config | Time.
|
||||||
//
|
//
|
||||||
// REQUIREMENT: You must add the following requirements to
|
|
||||||
// REQUIREMENT: "lib_deps" within platformio.ini / platformio_override.ini
|
|
||||||
// REQUIREMENT: * U8g2 (the version already in platformio.ini is fine)
|
|
||||||
// REQUIREMENT: * Wire
|
|
||||||
//
|
|
||||||
// If display does not work or looks corrupted check the
|
// If display does not work or looks corrupted check the
|
||||||
// constructor reference:
|
// constructor reference:
|
||||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||||
// or check the gallery:
|
// or check the gallery:
|
||||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||||
|
|
||||||
#ifndef FLD_PIN_CS
|
|
||||||
#define FLD_PIN_CS 15
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
#ifndef FLD_PIN_DC
|
|
||||||
#define FLD_PIN_DC 19
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_RESET
|
|
||||||
#define FLD_PIN_RESET 26
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifndef FLD_PIN_DC
|
|
||||||
#define FLD_PIN_DC 12
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_RESET
|
|
||||||
#define FLD_PIN_RESET 16
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FLD_TYPE
|
|
||||||
#ifndef FLD_SPI_DEFAULT
|
|
||||||
#define FLD_TYPE SSD1306
|
|
||||||
#else
|
|
||||||
#define FLD_TYPE SSD1306_SPI
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// When to time out to the clock or blank the screen
|
|
||||||
// if SLEEP_MODE_ENABLED.
|
|
||||||
#define SCREEN_TIMEOUT_MS 60*1000 // 1 min
|
|
||||||
|
|
||||||
// Minimum time between redrawing screen in ms
|
|
||||||
#define REFRESH_RATE_MS 1000
|
|
||||||
|
|
||||||
// Extra char (+1) for null
|
|
||||||
#define LINE_BUFFER_SIZE 16+1
|
|
||||||
#define MAX_JSON_CHARS 19+1
|
|
||||||
#define MAX_MODE_LINE_SPACE 13+1
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
static TaskHandle_t Display_Task = nullptr;
|
static TaskHandle_t Display_Task = nullptr;
|
||||||
void DisplayTaskCode(void * parameter);
|
void DisplayTaskCode(void * parameter);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NONE = 0,
|
|
||||||
SSD1306, // U8X8_SSD1306_128X32_UNIVISION_HW_I2C
|
|
||||||
SH1106, // U8X8_SH1106_128X64_WINSTAR_HW_I2C
|
|
||||||
SSD1306_64, // U8X8_SSD1306_128X64_NONAME_HW_I2C
|
|
||||||
SSD1305, // U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C
|
|
||||||
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
|
|
||||||
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
|
|
||||||
SSD1306_SPI64, // U8X8_SSD1306_128X64_NONAME_HW_SPI
|
|
||||||
SSD1309_SPI64, // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI
|
|
||||||
SSD1309_64 // U8X8_SSD1309_128X64_NONAME0_HW_I2C
|
|
||||||
} DisplayType;
|
|
||||||
|
|
||||||
|
|
||||||
class FourLineDisplayUsermod : public Usermod {
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
|
|
||||||
public:
|
|
||||||
FourLineDisplayUsermod() { if (!instance) instance = this; }
|
|
||||||
static FourLineDisplayUsermod* getInstance(void) { return instance; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static FourLineDisplayUsermod *instance;
|
|
||||||
bool initDone = false;
|
|
||||||
volatile bool drawing = false;
|
|
||||||
volatile bool lockRedraw = false;
|
|
||||||
|
|
||||||
// HW interface & configuration
|
|
||||||
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
|
|
||||||
|
|
||||||
#ifndef FLD_SPI_DEFAULT
|
|
||||||
int8_t ioPin[3] = {-1, -1, -1}; // I2C pins: SCL, SDA
|
|
||||||
uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000)
|
|
||||||
#else
|
|
||||||
int8_t ioPin[3] = {FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET}; // custom SPI pins: CS, DC, RST
|
|
||||||
uint32_t ioFrequency = 1000000; // in Hz (minimum is 500kHz, baseline is 1MHz and maximum should be 20MHz)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DisplayType type = FLD_TYPE; // display type
|
|
||||||
bool flip = false; // flip display 180°
|
|
||||||
uint8_t contrast = 10; // screen contrast
|
|
||||||
uint8_t lineHeight = 1; // 1 row or 2 rows
|
|
||||||
uint16_t refreshRate = REFRESH_RATE_MS; // in ms
|
|
||||||
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
|
|
||||||
bool sleepMode = true; // allow screen sleep?
|
|
||||||
bool clockMode = false; // display clock
|
|
||||||
bool showSeconds = true; // display clock with seconds
|
|
||||||
bool enabled = true;
|
|
||||||
bool contrastFix = false;
|
|
||||||
|
|
||||||
// Next variables hold the previous known values to determine if redraw is
|
|
||||||
// required.
|
|
||||||
String knownSsid = apSSID;
|
|
||||||
IPAddress knownIp = IPAddress(4, 3, 2, 1);
|
|
||||||
uint8_t knownBrightness = 0;
|
|
||||||
uint8_t knownEffectSpeed = 0;
|
|
||||||
uint8_t knownEffectIntensity = 0;
|
|
||||||
uint8_t knownMode = 0;
|
|
||||||
uint8_t knownPalette = 0;
|
|
||||||
uint8_t knownMinute = 99;
|
|
||||||
uint8_t knownHour = 99;
|
|
||||||
byte brightness100;
|
|
||||||
byte fxspeed100;
|
|
||||||
byte fxintensity100;
|
|
||||||
bool knownnightlight = nightlightActive;
|
|
||||||
bool wificonnected = interfacesInited;
|
|
||||||
bool powerON = true;
|
|
||||||
|
|
||||||
bool displayTurnedOff = false;
|
|
||||||
unsigned long nextUpdate = 0;
|
|
||||||
unsigned long lastRedraw = 0;
|
|
||||||
unsigned long overlayUntil = 0;
|
|
||||||
|
|
||||||
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
|
|
||||||
byte markLineNum = 255;
|
|
||||||
byte markColNum = 255;
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
|
||||||
static const char _name[];
|
|
||||||
static const char _enabled[];
|
|
||||||
static const char _contrast[];
|
|
||||||
static const char _refreshRate[];
|
|
||||||
static const char _screenTimeOut[];
|
|
||||||
static const char _flip[];
|
|
||||||
static const char _sleepMode[];
|
|
||||||
static const char _clockMode[];
|
|
||||||
static const char _showSeconds[];
|
|
||||||
static const char _busClkFrequency[];
|
|
||||||
static const char _contrastFix[];
|
|
||||||
|
|
||||||
// If display does not work or looks corrupted check the
|
|
||||||
// constructor reference:
|
|
||||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
|
||||||
// or check the gallery:
|
|
||||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
|
||||||
|
|
||||||
// some displays need this to properly apply contrast
|
|
||||||
void setVcomh(bool highContrast);
|
|
||||||
void startDisplay();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrappers for screen drawing
|
|
||||||
*/
|
|
||||||
void setFlipMode(uint8_t mode);
|
|
||||||
void setContrast(uint8_t contrast);
|
|
||||||
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false);
|
|
||||||
void draw2x2String(uint8_t col, uint8_t row, const char *string);
|
|
||||||
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false);
|
|
||||||
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font);
|
|
||||||
void draw2x2GlyphIcons();
|
|
||||||
uint8_t getCols();
|
|
||||||
void clear();
|
|
||||||
void setPowerSave(uint8_t save);
|
|
||||||
void center(String &line, uint8_t width);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the current date and time in large characters
|
|
||||||
* on the middle rows. Based 24 or 12 hour depending on
|
|
||||||
* the useAMPM configuration.
|
|
||||||
*/
|
|
||||||
void showTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable sleep (turn the display off) or clock mode.
|
|
||||||
*/
|
|
||||||
void sleepOrClock(bool enabled);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// gets called once at boot. Do all initialization that doesn't depend on
|
|
||||||
// network here
|
|
||||||
void setup() override;
|
|
||||||
|
|
||||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
|
||||||
// interfaces here
|
|
||||||
void connected() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Da loop.
|
|
||||||
*/
|
|
||||||
void loop() override;
|
|
||||||
|
|
||||||
//function to update lastredraw
|
|
||||||
inline void updateRedrawTime() { lastRedraw = millis(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redraw the screen (but only if things have changed
|
|
||||||
* or if forceRedraw).
|
|
||||||
*/
|
|
||||||
void redraw(bool forceRedraw);
|
|
||||||
|
|
||||||
void updateBrightness();
|
|
||||||
void updateSpeed();
|
|
||||||
void updateIntensity();
|
|
||||||
void drawStatusIcons();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* marks the position of the arrow showing
|
|
||||||
* the current setting being changed
|
|
||||||
* pass line and colum info
|
|
||||||
*/
|
|
||||||
void setMarkLine(byte newMarkLineNum, byte newMarkColNum);
|
|
||||||
|
|
||||||
//Draw the arrow for the current setting being changed
|
|
||||||
void drawArrow();
|
|
||||||
|
|
||||||
//Display the current effect or palette (desiredEntry)
|
|
||||||
// on the appropriate line (row).
|
|
||||||
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If there screen is off or in clock is displayed,
|
|
||||||
* this will return true. This allows us to throw away
|
|
||||||
* the first input from the rotary encoder but
|
|
||||||
* to wake up the screen.
|
|
||||||
*/
|
|
||||||
bool wakeDisplay();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to show one line and a glyph as overlay for a period of time.
|
|
||||||
* Clears the screen and prints.
|
|
||||||
* Used in Rotary Encoder usermod.
|
|
||||||
*/
|
|
||||||
void overlay(const char* line1, long showHowLong, byte glyphType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to show Akemi WLED logo overlay for a period of time.
|
|
||||||
* Clears the screen and prints.
|
|
||||||
*/
|
|
||||||
void overlayLogo(long showHowLong);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to show two lines as overlay for a period of time.
|
|
||||||
* Clears the screen and prints.
|
|
||||||
* Used in Auto Save usermod
|
|
||||||
*/
|
|
||||||
void overlay(const char* line1, const char* line2, long showHowLong);
|
|
||||||
|
|
||||||
void networkOverlay(const char* line1, long showHowLong);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handleButton() can be used to override default button behaviour. Returning true
|
|
||||||
* will prevent button working in a default way.
|
|
||||||
* Replicating button.cpp
|
|
||||||
*/
|
|
||||||
bool handleButton(uint8_t b);
|
|
||||||
|
|
||||||
void onUpdateBegin(bool init) override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
|
||||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
|
||||||
* Below it is shown how this could be used for e.g. a light sensor
|
|
||||||
*/
|
|
||||||
//void addToJsonInfo(JsonObject& root) override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
//void addToJsonState(JsonObject& root) override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
//void readFromJsonState(JsonObject& root) override;
|
|
||||||
|
|
||||||
void appendConfigData() override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
|
||||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
|
||||||
* If you want to force saving the current state, use serializeConfig() in your loop().
|
|
||||||
*
|
|
||||||
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
|
||||||
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
|
||||||
* Use it sparingly and always in the loop, never in network callbacks!
|
|
||||||
*
|
|
||||||
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
|
||||||
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
|
||||||
*
|
|
||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
|
||||||
*/
|
|
||||||
void addToConfig(JsonObject& root) override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
|
||||||
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
|
||||||
*
|
|
||||||
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
|
||||||
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
|
||||||
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
|
||||||
*/
|
|
||||||
bool readFromConfig(JsonObject& root) override;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
||||||
*/
|
|
||||||
uint16_t getId() override {
|
|
||||||
return USERMOD_ID_FOUR_LINE_DISP;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay";
|
const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay";
|
||||||
const char FourLineDisplayUsermod::_enabled[] PROGMEM = "enabled";
|
const char FourLineDisplayUsermod::_enabled[] PROGMEM = "enabled";
|
||||||
@ -1387,4 +1069,4 @@ bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
|
|||||||
|
|
||||||
|
|
||||||
static FourLineDisplayUsermod usermod_v2_four_line_display_alt;
|
static FourLineDisplayUsermod usermod_v2_four_line_display_alt;
|
||||||
REGISTER_USERMOD(usermod_v2_four_line_display_alt);
|
REGISTER_USERMOD(usermod_v2_four_line_display_alt);
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_v2_klipper_percentage"
|
"name": "usermod_v2_klipper_percentage"
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_v2_ping_pong_clock"
|
"name": "usermod_v2_ping_pong_clock"
|
||||||
}
|
}
|
@ -1,3 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_v2_rotary_encoder_ui_ALT"
|
"name": "rotary_encoder_ui_ALT",
|
||||||
|
"build": {
|
||||||
|
"extraScript": "setup_deps.py"
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,13 +1,11 @@
|
|||||||
[platformio]
|
[platformio]
|
||||||
default_envs = esp32dev
|
default_envs = esp32dev_re
|
||||||
|
|
||||||
[env:esp32dev]
|
[env:esp32dev_re]
|
||||||
board = esp32dev
|
extends = env:esp32dev_V4
|
||||||
platform = ${esp32.platform}
|
custom_usermods = ${env:esp32dev_V4.custom_usermods} rotary_encoder_ui_ALT
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${common.build_flags_esp32}
|
${env:esp32dev_V4.build_flags}
|
||||||
-D USERMOD_ROTARY_ENCODER_UI
|
|
||||||
-D USERMOD_ROTARY_ENCODER_GPIO=INPUT
|
-D USERMOD_ROTARY_ENCODER_GPIO=INPUT
|
||||||
-D ENCODER_DT_PIN=21
|
-D ENCODER_DT_PIN=21
|
||||||
-D ENCODER_CLK_PIN=23
|
-D ENCODER_CLK_PIN=23
|
||||||
|
@ -25,10 +25,6 @@ Copy the example `platformio_override.sample.ini` to the root directory of your
|
|||||||
|
|
||||||
### Define Your Options
|
### Define Your Options
|
||||||
|
|
||||||
* `USERMOD_ROTARY_ENCODER_UI` - define this to have this user mod included wled00\usermods_list.cpp
|
|
||||||
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp
|
|
||||||
also tells this usermod that the display is available
|
|
||||||
(see the Four Line Display usermod `readme.md` for more details)
|
|
||||||
* `ENCODER_DT_PIN` - defaults to 18
|
* `ENCODER_DT_PIN` - defaults to 18
|
||||||
* `ENCODER_CLK_PIN` - defaults to 5
|
* `ENCODER_CLK_PIN` - defaults to 5
|
||||||
* `ENCODER_SW_PIN` - defaults to 19
|
* `ENCODER_SW_PIN` - defaults to 19
|
||||||
|
8
usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py
Normal file
8
usermods/usermod_v2_rotary_encoder_ui_ALT/setup_deps.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Import('env')
|
||||||
|
|
||||||
|
|
||||||
|
usermods = env.GetProjectOption("custom_usermods","").split()
|
||||||
|
# Check for partner usermod
|
||||||
|
# Allow both "usermod_v2" and unqualified syntax
|
||||||
|
if any(mod in ("four_line_display_ALT", "usermod_v2_four_line_display_ALT") for mod in usermods):
|
||||||
|
env.Append(CPPDEFINES=[("USERMOD_FOUR_LINE_DISPLAY")])
|
@ -27,6 +27,10 @@
|
|||||||
// * display network (long press buttion)
|
// * display network (long press buttion)
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
|
#include "usermod_v2_four_line_display.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_MODE_SORT
|
#ifdef USERMOD_MODE_SORT
|
||||||
#error "Usermod Mode Sort is no longer required. Remove -D USERMOD_MODE_SORT from platformio.ini"
|
#error "Usermod Mode Sort is no longer required. Remove -D USERMOD_MODE_SORT from platformio.ini"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "usermod_v2_word_clock"
|
"name": "usermod_v2_word_clock"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name:": "wireguard",
|
"name": "wireguard",
|
||||||
"build": { "libArchive": false},
|
"build": { "libArchive": false},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"WireGuard-ESP32-Arduino":"https://github.com/kienvu58/WireGuard-ESP32-Arduino.git"
|
"WireGuard-ESP32-Arduino":"https://github.com/kienvu58/WireGuard-ESP32-Arduino.git"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"name:": "wizlights"
|
"name": "wizlights"
|
||||||
}
|
}
|
3
usermods/word-clock-matrix/library.json
Normal file
3
usermods/word-clock-matrix/library.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "word-clock-matrix"
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"name:": "word-clock-matrix"
|
|
||||||
}
|
|
@ -36,8 +36,8 @@ public:
|
|||||||
//other segments are text
|
//other segments are text
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
{
|
{
|
||||||
Segment &seg = strip.getSegment(i);
|
Segment &text_seg = strip.getSegment(i);
|
||||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
text_seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
||||||
strip.getSegment(i).setOption(0, true);
|
strip.getSegment(i).setOption(0, true);
|
||||||
strip.setBrightness(64);
|
strip.setBrightness(64);
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
//strip.resetSegments();
|
//strip.resetSegments();
|
||||||
selectWordSegments(true);
|
selectWordSegments(true);
|
||||||
colorUpdated(CALL_MODE_FX_CHANGED);
|
colorUpdated(CALL_MODE_FX_CHANGED);
|
||||||
savePreset(13, false);
|
savePreset(13);
|
||||||
selectWordSegments(false);
|
selectWordSegments(false);
|
||||||
//strip.getSegment(0).setOption(0, true);
|
//strip.getSegment(0).setOption(0, true);
|
||||||
strip.getSegment(0).setOption(2, true);
|
strip.getSegment(0).setOption(2, true);
|
||||||
@ -329,7 +329,7 @@ public:
|
|||||||
|
|
||||||
uint16_t getId()
|
uint16_t getId()
|
||||||
{
|
{
|
||||||
return USERMOD_ID_WORD_CLOCK_MATRIX;
|
return 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user