kopia lustrzana https://github.com/Aircoookie/WLED
184 wiersze
5.0 KiB
C++
184 wiersze
5.0 KiB
C++
#include "wled.h"
|
|
#include "Arduino.h"
|
|
#include <RCSwitch.h>
|
|
|
|
#define RF433_BUSWAIT_TIMEOUT 24
|
|
|
|
class RF433Usermod : public Usermod
|
|
{
|
|
private:
|
|
RCSwitch mySwitch = RCSwitch();
|
|
unsigned long lastCommand = 0;
|
|
unsigned long lastTime = 0;
|
|
|
|
bool modEnabled = true;
|
|
int8_t receivePin = -1;
|
|
|
|
static const char _modName[];
|
|
static const char _modEnabled[];
|
|
static const char _receivePin[];
|
|
|
|
bool initDone = false;
|
|
|
|
public:
|
|
|
|
void setup()
|
|
{
|
|
mySwitch.disableReceive();
|
|
if (modEnabled)
|
|
{
|
|
mySwitch.enableReceive(receivePin);
|
|
}
|
|
initDone = true;
|
|
}
|
|
|
|
/*
|
|
* connected() is called every time the WiFi is (re)connected
|
|
* Use it to initialize network interfaces
|
|
*/
|
|
void connected()
|
|
{
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
if (!modEnabled || strip.isUpdating())
|
|
return;
|
|
|
|
if (mySwitch.available())
|
|
{
|
|
unsigned long receivedCommand = mySwitch.getReceivedValue();
|
|
mySwitch.resetAvailable();
|
|
|
|
// Discard duplicates, limit long press repeat
|
|
if (lastCommand == receivedCommand && millis() - lastTime < 800)
|
|
return;
|
|
|
|
lastCommand = receivedCommand;
|
|
lastTime = millis();
|
|
|
|
DEBUG_PRINT(F("RF433 Receive: "));
|
|
DEBUG_PRINTLN(receivedCommand);
|
|
|
|
if(!remoteJson433(receivedCommand))
|
|
DEBUG_PRINTLN(F("RF433: unknown button"));
|
|
}
|
|
}
|
|
|
|
// Add last received button to info pane
|
|
void addToJsonInfo(JsonObject &root)
|
|
{
|
|
if (!initDone)
|
|
return; // prevent crash on boot applyPreset()
|
|
JsonObject user = root["u"];
|
|
if (user.isNull())
|
|
user = root.createNestedObject("u");
|
|
|
|
JsonArray switchArr = user.createNestedArray("RF433 Last Received"); // name
|
|
switchArr.add(lastCommand);
|
|
}
|
|
|
|
void addToConfig(JsonObject &root)
|
|
{
|
|
JsonObject top = root.createNestedObject(FPSTR(_modName)); // usermodname
|
|
top[FPSTR(_modEnabled)] = modEnabled;
|
|
JsonArray pinArray = top.createNestedArray("pin");
|
|
pinArray.add(receivePin);
|
|
|
|
DEBUG_PRINTLN(F(" config saved."));
|
|
}
|
|
|
|
bool readFromConfig(JsonObject &root)
|
|
{
|
|
JsonObject top = root[FPSTR(_modName)];
|
|
if (top.isNull())
|
|
{
|
|
DEBUG_PRINT(FPSTR(_modName));
|
|
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
|
return false;
|
|
}
|
|
getJsonValue(top[FPSTR(_modEnabled)], modEnabled);
|
|
getJsonValue(top["pin"][0], receivePin);
|
|
|
|
DEBUG_PRINTLN(F("config (re)loaded."));
|
|
|
|
// Redo init on update
|
|
if(initDone)
|
|
setup();
|
|
|
|
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_RF433;
|
|
}
|
|
|
|
// this function follows the same principle as decodeIRJson() / remoteJson()
|
|
bool remoteJson433(int button)
|
|
{
|
|
char objKey[14];
|
|
bool parsed = false;
|
|
|
|
if (!requestJSONBufferLock(22)) return false;
|
|
|
|
sprintf_P(objKey, PSTR("\"%d\":"), button);
|
|
|
|
unsigned long start = millis();
|
|
while (strip.isUpdating() && millis()-start < RF433_BUSWAIT_TIMEOUT) yield(); // wait for strip to finish updating, accessing FS during sendout causes glitches
|
|
|
|
// attempt to read command from remote.json
|
|
readObjectFromFile(PSTR("/remote433.json"), objKey, pDoc);
|
|
JsonObject fdo = pDoc->as<JsonObject>();
|
|
if (fdo.isNull()) {
|
|
// the received button does not exist
|
|
releaseJSONBufferLock();
|
|
return parsed;
|
|
}
|
|
|
|
String cmdStr = fdo["cmd"].as<String>();
|
|
JsonObject jsonCmdObj = fdo["cmd"]; //object
|
|
|
|
if (jsonCmdObj.isNull()) // we could also use: fdo["cmd"].is<String>()
|
|
{
|
|
// HTTP API command
|
|
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
|
if (!cmdStr.startsWith(apireq)) cmdStr = apireq + cmdStr; // if no "win&" prefix
|
|
if (!irApplyToAllSelected && cmdStr.indexOf(F("SS="))<0) {
|
|
char tmp[10];
|
|
sprintf_P(tmp, PSTR("&SS=%d"), strip.getMainSegmentId());
|
|
cmdStr += tmp;
|
|
}
|
|
fdo.clear(); // clear JSON buffer (it is no longer needed)
|
|
handleSet(nullptr, cmdStr, false); // no stateUpdated() call here
|
|
stateUpdated(CALL_MODE_BUTTON);
|
|
parsed = true;
|
|
} else {
|
|
// command is JSON object
|
|
if (jsonCmdObj[F("psave")].isNull())
|
|
deserializeState(jsonCmdObj, CALL_MODE_BUTTON_PRESET);
|
|
else {
|
|
uint8_t psave = jsonCmdObj[F("psave")].as<int>();
|
|
char pname[33];
|
|
sprintf_P(pname, PSTR("IR Preset %d"), psave);
|
|
fdo.clear();
|
|
if (psave > 0 && psave < 251) savePreset(psave, pname, fdo);
|
|
}
|
|
parsed = true;
|
|
}
|
|
releaseJSONBufferLock();
|
|
return parsed;
|
|
}
|
|
};
|
|
|
|
const char RF433Usermod::_modName[] PROGMEM = "RF433 Remote";
|
|
const char RF433Usermod::_modEnabled[] PROGMEM = "Enabled";
|
|
const char RF433Usermod::_receivePin[] PROGMEM = "RX Pin";
|
|
|
|
static RF433Usermod usermod_v2_RF433;
|
|
REGISTER_USERMOD(usermod_v2_RF433);
|