Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WifiStatus usermod - indicate Wifi state with LED blinks #3574

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions usermods/WifiStatus/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Wifi Status on LED
v2 Usermod to indicate Wifi connection state on LED connected to a GPIO.

Three states are supported:

1. Wifi **disconnected** - indicated by fast blinks of LED
2. Wifi **connected** - LED on with very short off after 2 seconds
3. Wifi in **Access Point mode** - LED blink twice time and pause for 1 second

## Installation

Copy and update the example `platformio_override.ini.sample`
from the Rotary Encoder UI usermode folder to the root directory of your particular build.
This file should be placed in the same directory as `platformio.ini`.

### Define Your Options

* `USERMOD_WIFI_STATUS` - define this to have this usermod included wled00\usermods_list.cpp

Example to add in platformio_override:
-D USERMOD_WIFI_STATUS

You can also configure plugin parameters (like led pin and enablation) using Usermods settings page.

### PlatformIO requirements

No special requirements.

## Authors
Piotr Jóźwiak [@petrusvr](https://github.com/petrusvr)

## Change Log

2023-11
* First public release
210 changes: 210 additions & 0 deletions usermods/WifiStatus/wifi_status.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#pragma once

#include "wled.h"
#include <deque>

#ifndef USERMOD_WIFI_STATUS_LED_PIN
#ifdef ARDUINO_ARCH_ESP32
#define USERMOD_WIFI_STATUS_LED_PIN 2
#else //ESP8266 boards
#define USERMOD_WIFI_STATUS_LED_PIN 16
#endif
#endif

class WifiStatusUsermod : public Usermod {

private:
bool initDone = false;
bool enabled = true;
int8_t ledPin = USERMOD_WIFI_STATUS_LED_PIN; // LED PIN
std::deque<std::pair<uint8_t, unsigned int>> blinkSequence {};

int ledState = LOW;
unsigned long previousMillis = 0;
unsigned int interval = 1000;

// string that are used multiple time (this will save some flash memory)
static const char _name[];
static const char _enabled[];

void enable(bool enable) {
enabled = enable;
}

void reconfigure(int8_t oldPin, bool oldEnabled){
if(oldEnabled != enabled || oldPin != ledPin){
DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(" enabled or ledPin changed"));
if(isAllocatedPin(oldPin)){
deallocatePin(oldPin);
digitalWrite(oldPin, LOW);
}
}
configure();
}

void configure(){
if(enabled && pinManager.isPinOk(ledPin) && ledPin >= 0){
if(!isAllocatedPin(ledPin)){
if(allocatePin(ledPin)){
pinMode(ledPin, OUTPUT);
}else{
DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(" Can't allocate ledPin"));
enabled = false;
return;
}
} else pinMode(ledPin, OUTPUT);
}
}

bool isAllocatedPin(int8_t pin){
return pinManager.getPinOwner(pin) == PinOwner::UM_WIFI_STATUS;
}

void deallocatePin(int8_t pin){
pinManager.deallocatePin(pin, PinOwner::UM_WIFI_STATUS);
}

bool allocatePin(int8_t pin){
return pinManager.allocatePin(pin, true, PinOwner::UM_WIFI_STATUS);
}

void handleBlink(){
unsigned long currentMillis = millis();

if(blinkSequence.size() < 1) //nothing to blink
return;

if (currentMillis - previousMillis >= interval){
auto event = blinkSequence.front();
DEBUG_PRINTF("handleBlink() STATE=%d INTERVAL=%d \n", event.first, event.second);
blinkSequence.pop_front();
digitalWrite(ledPin, event.first);
interval = event.second;
previousMillis = millis();
}
}

void addSequenceConnected(){
blinkSequence.push_back({HIGH, 2000});
blinkSequence.push_back({LOW, 10});
}

void addSequenceDisconnected(){
blinkSequence.push_back({HIGH, 200});
blinkSequence.push_back({LOW, 100});
}

void addSequenceAPmode(){
// blinkSequence.push_back({LOW, 200});
blinkSequence.push_back({HIGH, 200});
blinkSequence.push_back({LOW, 200});
blinkSequence.push_back({HIGH, 200});
blinkSequence.push_back({LOW, 1000});
}

public:

// gets called once at boot. Do all initialization that doesn't depend on network here
void setup() {
DEBUG_PRINTLN(F("---Wifi Status Usermod: setup() start"));
initDone = true;
configure();
DEBUG_PRINTLN(F("---Wifi Status Usermod: setup() end"));
}

// gets called every time WiFi is (re-)connected. Initialize own network interfaces here
void connected() {
DEBUG_PRINTLN(F("---Wifi Status Usermod: connected()"));
}

/*
* Main Wifi Status loop()
*/
void loop() {
if (!enabled || strip.isUpdating())
return;

if(blinkSequence.size() <= 1){
if(WiFi.status() == WL_CONNECTED){
addSequenceConnected();
}else if(apActive){
addSequenceAPmode();
}else {
addSequenceDisconnected();
}
}

handleBlink();
}

/*
* 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) {
// we add JSON object: {"WifiStatus": {"enabled": true, "pin": 2}}
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
top[FPSTR(_enabled)] = enabled;
top["pin"] = ledPin;

DEBUG_PRINTLN(F("Autosave config saved."));
}

/*
* 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 :)
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject& root) {
// Looking for JSON object: {"WifiStatus": {"enabled": true, "pin": 2}}
JsonObject top = root[FPSTR(_name)];
if (top.isNull()) {
DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false;
}

bool oldEnabled = enabled;
int8_t oldLedPin = ledPin;

enabled = top[FPSTR(_enabled)] | enabled;
ledPin = top[FPSTR("pin")] | ledPin;

reconfigure(oldLedPin, oldEnabled);

DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(" config (re)loaded."));

// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return true;
}

/*
* 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() {
return USERMOD_ID_WIFI_STATUS;
}
};

// strings to reduce flash memory usage (used more than twice)
const char WifiStatusUsermod::_name[] PROGMEM = "WifiStatus";
const char WifiStatusUsermod::_enabled[] PROGMEM = "enabled";
1 change: 1 addition & 0 deletions wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
#define USERMOD_ID_KLIPPER 40 //Usermod Klipper percentage
#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h"
#define USERMOD_ID_INTERNAL_TEMPERATURE 42 //Usermod "usermod_internal_temperature.h"
#define USERMOD_ID_WIFI_STATUS 43 //Usermod "wifi_status.h"

//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
Expand Down
3 changes: 2 additions & 1 deletion wled00/pin_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ enum struct PinOwner : uint8_t {
UM_BME280 = USERMOD_ID_BME280, // 0x1E // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE, // 0x20 // Usermod "audio_reactive.h"
UM_SdCard = USERMOD_ID_SD_CARD, // 0x25 // Usermod "usermod_sd_card.h"
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS // 0x26 // Usermod "usermod_pwm_outputs.h"
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS, // 0x26 // Usermod "usermod_pwm_outputs.h"
UM_WIFI_STATUS = USERMOD_ID_WIFI_STATUS // 0x2B // Usermod "wifi_status.h"
};
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");

Expand Down
8 changes: 8 additions & 0 deletions wled00/usermods_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
#include "../usermods/usermod_v2_auto_save/usermod_v2_auto_save.h"
#endif

#ifdef USERMOD_WIFI_STATUS
#include "../usermods/WifiStatus/wifi_status.h"
#endif

#ifdef USERMOD_DHT
#include "../usermods/DHT/usermod_dht.h"
#endif
Expand Down Expand Up @@ -258,6 +262,10 @@ void registerUsermods()
usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
#endif

#ifdef USERMOD_WIFI_STATUS
usermods.add(new WifiStatusUsermod());
#endif

#ifdef USERMOD_DHT
usermods.add(new UsermodDHT());
#endif
Expand Down
Loading