Implemented motion sensor settings
Moved all settings to JSON storage
This commit is contained in:
parent
f6808c4833
commit
981d6ac1bb
52
API.md
52
API.md
@ -10,6 +10,8 @@
|
||||
- [POST /api/steps](#post-apisteps)
|
||||
- [GET /api/triggers/time](#get-apitriggerstime)
|
||||
- [POST /api/triggers/time](#post-apitriggerstime)
|
||||
- [GET /api/triggers/motion](#get-apitriggersmotion)
|
||||
- [POST /api/triggers/motion](#post-apitriggersmotion)
|
||||
- [POST /api/firmware](#post-apifirmware)
|
||||
|
||||
## GET /api/version
|
||||
@ -203,6 +205,56 @@ enabled: whether or not this trigger is enabled
|
||||
|
||||
Changes the time trigger settings. Request body format is the same as is returned in the GET request.
|
||||
|
||||
|
||||
## GET /api/triggers/motion
|
||||
|
||||
Returns the current settings for the motion triggers.
|
||||
|
||||
delay: How long to keep the lights on after the last sensor stops detecting motion.
|
||||
|
||||
pin: GPIO pin to which the motion sensor is connected. High is assumed to be active.
|
||||
|
||||
direction:
|
||||
Enumeration determining from which side the sweep animation starts if transitionTime is set.
|
||||
|
||||
| value | description |
|
||||
| ----- | --- |
|
||||
| 1 | Non-directional. All steps change brightness at the same time. |
|
||||
| 2 | Top-down. Starts a sweeping fade from the top step. |
|
||||
| 3 | Bottom-up. Starts a sweeping fade from the bottom step. |
|
||||
|
||||
brightness: value from 0 to 255
|
||||
|
||||
enabled: whether or not this trigger is enabled
|
||||
|
||||
*Example response:*
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"enabledDuringTimeTrigger": true,
|
||||
"transitionTime": 1000,
|
||||
"delay": 30000,
|
||||
"triggers": [
|
||||
{
|
||||
"pin": 14,
|
||||
"brightness": 64,
|
||||
"direction": 2,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"pin": 15,
|
||||
"brightness": 64,
|
||||
"direction": 3,
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## POST /api/triggers/motion
|
||||
|
||||
Changes the motion trigger settings. Request body format is the same as is returned in the GET request.
|
||||
|
||||
## POST /api/firmware
|
||||
|
||||
Uploads new firmware. The bin file should be posted as a multipart/form-data file attachment. Name is not relevant.
|
@ -45,7 +45,7 @@
|
||||
#include <StreamString.h>
|
||||
#include <base64.h>
|
||||
|
||||
#include "ESP8266HTTPClient-h4xx0red.h"
|
||||
#include "./ESP8266HTTPClient-h4xx0red.h"
|
||||
|
||||
class TransportTraits
|
||||
{
|
||||
|
@ -4,10 +4,10 @@
|
||||
const uint8_t VersionMajor = 2;
|
||||
const uint8_t VersionMinor = 0;
|
||||
const uint8_t VersionPatch = 0;
|
||||
const uint8_t VersionMetadata = 17;
|
||||
const uint8_t VersionMetadata = 18;
|
||||
const char VersionBranch[] = "release/2.0";
|
||||
const char VersionSemVer[] = "2.0.0-beta.1";
|
||||
const char VersionFullSemVer[] = "2.0.0-beta.1+17";
|
||||
const char VersionFullSemVer[] = "2.0.0-beta.1+18";
|
||||
const char VersionCommitDate[] = "2018-01-14";
|
||||
|
||||
#endif
|
||||
|
@ -4,12 +4,12 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "charproperties.h"
|
||||
#include "./charproperties.h"
|
||||
#include <cstddef>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "./debug.h"
|
||||
|
||||
void CharProperties::assignChar(char** field, const char* newValue)
|
||||
void assignChar(char** field, const char* newValue)
|
||||
{
|
||||
if (*field != nullptr)
|
||||
delete *field;
|
||||
|
@ -9,10 +9,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class CharProperties
|
||||
{
|
||||
protected:
|
||||
void assignChar(char** field, const char* newValue);
|
||||
};
|
||||
void assignChar(char** field, const char* newValue);
|
||||
|
||||
#endif
|
@ -3,7 +3,7 @@
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "PCA9685.h"
|
||||
#include "./PCA9685.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
@ -14,8 +14,9 @@ static const uint32_t SerialDebugStartupDelay = 2000;
|
||||
|
||||
static const char* ConnectionSettingsFile = "/connection.json";
|
||||
static const char* SystemSettingsFile = "/system.json";
|
||||
static const char* StepSettingsFile = "/stepsettings.dat";
|
||||
static const char* TimeTriggerSettingsFile = "/timetriggersettings.dat";
|
||||
static const char* StepsSettingsFile = "/steps.json";
|
||||
static const char* TimeTriggerSettingsFile = "/timetriggers.json";
|
||||
static const char* MotionTriggerSettingsFile = "/motiontriggers.json";
|
||||
|
||||
|
||||
static const char* DefaultAPSSIDPrefix = "Stairs-";
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "debug.h"
|
||||
#include "./debug.h"
|
||||
|
||||
|
||||
void _dinit()
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef __serialdebug
|
||||
#define __serialdebug
|
||||
|
||||
#include "config.h"
|
||||
#include "./config.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
void _dinit();
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "./global.h"
|
||||
|
||||
ConnectionSettings* connectionSettings = new ConnectionSettings();
|
||||
bool connectionSettingsChanged = false;
|
||||
@ -18,6 +18,9 @@ bool stepsSettingsChanged = false;
|
||||
TimeTriggerSettings* timeTriggerSettings = new TimeTriggerSettings();
|
||||
bool timeTriggerSettingsChanged = false;
|
||||
|
||||
MotionTriggerSettings* motionTriggerSettings = new MotionTriggerSettings();
|
||||
bool motionTriggerSettingsChanged = false;
|
||||
|
||||
|
||||
Stairs* stairs;
|
||||
|
||||
|
14
src/global.h
14
src/global.h
@ -10,11 +10,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <IPAddress.h>
|
||||
#include "settings/connection.h"
|
||||
#include "settings/system.h"
|
||||
#include "settings/steps.h"
|
||||
#include "settings/triggers/time.h"
|
||||
#include "stairs.h"
|
||||
#include "./settings/connection.h"
|
||||
#include "./settings/system.h"
|
||||
#include "./settings/steps.h"
|
||||
#include "./settings/triggers/time.h"
|
||||
#include "./settings/triggers/motion.h"
|
||||
#include "./stairs.h"
|
||||
|
||||
extern ConnectionSettings* connectionSettings;
|
||||
extern bool connectionSettingsChanged;
|
||||
@ -28,6 +29,9 @@ extern bool stepsSettingsChanged;
|
||||
extern TimeTriggerSettings* timeTriggerSettings;
|
||||
extern bool timeTriggerSettingsChanged;
|
||||
|
||||
extern MotionTriggerSettings* motionTriggerSettings;
|
||||
extern bool motionTriggerSettingsChanged;
|
||||
|
||||
|
||||
extern Stairs* stairs;
|
||||
|
||||
|
153
src/main.cpp
153
src/main.cpp
@ -16,29 +16,28 @@ extern "C" {
|
||||
#include <user_interface.h>
|
||||
}
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "global.h"
|
||||
#include "components/PCA9685.h"
|
||||
#include "settings/connection.h"
|
||||
#include "server/static.h"
|
||||
#include "server/settings.h"
|
||||
#include "server/firmware.h"
|
||||
#include "server/api.h"
|
||||
#include "./config.h"
|
||||
#include "./debug.h"
|
||||
#include "./global.h"
|
||||
#include "./components/PCA9685.h"
|
||||
#include "./settings/connection.h"
|
||||
#include "./server/static.h"
|
||||
#include "./server/settings.h"
|
||||
#include "./server/firmware.h"
|
||||
#include "./server/api.h"
|
||||
|
||||
|
||||
ADC_MODE(ADC_VCC);
|
||||
|
||||
// Forward declarations
|
||||
void initWiFi();
|
||||
void initMotionPins();
|
||||
#ifdef SerialDebug
|
||||
void wifiEvent(WiFiEvent_t event);
|
||||
void updateDebugStatus();
|
||||
#endif
|
||||
void updateLED();
|
||||
void updateNTPClient();
|
||||
|
||||
void updateTimeTrigger();
|
||||
void checkTriggers();
|
||||
|
||||
void handleNotFound(AsyncWebServerRequest* request);
|
||||
@ -73,10 +72,12 @@ void setup()
|
||||
systemSettings->read();
|
||||
stepsSettings->read();
|
||||
timeTriggerSettings->read();
|
||||
motionTriggerSettings->read();
|
||||
|
||||
pinMode(systemSettings->pinAPButton(), INPUT_PULLUP);
|
||||
pinMode(systemSettings->pinLEDAP(), OUTPUT);
|
||||
pinMode(systemSettings->pinLEDSTA(), OUTPUT);
|
||||
initMotionPins();
|
||||
|
||||
|
||||
_dln("Setup :: initializing PCA9685");
|
||||
@ -142,6 +143,12 @@ void loop()
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
if (motionTriggerSettingsChanged)
|
||||
{
|
||||
initMotionPins();
|
||||
motionTriggerSettingsChanged = false;
|
||||
}
|
||||
|
||||
currentTime = millis();
|
||||
|
||||
|
||||
@ -191,12 +198,7 @@ void loop()
|
||||
|
||||
updateLED();
|
||||
updateNTPClient();
|
||||
|
||||
if (timeTriggerSettings->enabled() /*|| motionTriggerEnabled*/)
|
||||
{
|
||||
updateTimeTrigger();
|
||||
checkTriggers();
|
||||
}
|
||||
checkTriggers();
|
||||
|
||||
stairs->tick();
|
||||
}
|
||||
@ -253,6 +255,20 @@ void initWiFi()
|
||||
}
|
||||
|
||||
|
||||
void initMotionPins()
|
||||
{
|
||||
if (!motionTriggerSettings->enabled())
|
||||
return;
|
||||
|
||||
for (uint8_t i = 0; i < motionTriggerSettings->triggerCount(); i++)
|
||||
{
|
||||
MotionTrigger* trigger = motionTriggerSettings->trigger(i);
|
||||
if (trigger->enabled)
|
||||
pinMode(trigger->pin, INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef SerialDebug
|
||||
void wifiEvent(WiFiEvent_t event)
|
||||
{
|
||||
@ -403,10 +419,20 @@ TimeTrigger* activeTimeTrigger = nullptr;
|
||||
void updateTimeTrigger()
|
||||
{
|
||||
if (ntpClient == nullptr || !timeTriggerSettings->enabled())
|
||||
{
|
||||
activeTimeTrigger = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeTriggerSettingsChanged)
|
||||
{
|
||||
// Time trigger settings changed, activeTimeTrigger pointer is considered
|
||||
// invalid, force recheck
|
||||
timeTriggerSettingsChanged = false;
|
||||
}
|
||||
else if (currentTime - lastTimeTriggerChecked < 10000)
|
||||
return;
|
||||
|
||||
if (currentTime - lastTimeTriggerChecked < 10000)
|
||||
return;
|
||||
|
||||
lastTimeTriggerChecked = currentTime;
|
||||
_dln("Triggers:: updating time trigger");
|
||||
@ -414,11 +440,12 @@ void updateTimeTrigger()
|
||||
uint32_t epochTime = ntpClient->getEpochTime();
|
||||
if (epochTime == 0)
|
||||
{
|
||||
activeTimeTrigger = nullptr;
|
||||
_dln("Triggers:: time not synchronised yet");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO compensate for UTC
|
||||
// TODO apply timezone offset
|
||||
|
||||
tmElements_t time;
|
||||
breakTime(epochTime, time);
|
||||
@ -435,21 +462,59 @@ void updateTimeTrigger()
|
||||
}
|
||||
|
||||
|
||||
uint32_t activeMotionStart = 0;
|
||||
uint16_t activeMotionBrightness = 0;
|
||||
MotionDirection activeMotionDirection = Nondirectional;
|
||||
bool lastMotion = false;
|
||||
|
||||
|
||||
void updateMotionTrigger()
|
||||
{
|
||||
if (!motionTriggerSettings->enabled() || !motionTriggerSettings->triggerCount())
|
||||
{
|
||||
activeMotionStart = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < motionTriggerSettings->triggerCount(); i++)
|
||||
{
|
||||
MotionTrigger* trigger = motionTriggerSettings->trigger(i);
|
||||
|
||||
if (trigger->enabled && digitalRead(trigger->pin) == HIGH)
|
||||
{
|
||||
if (activeMotionStart == 0)
|
||||
{
|
||||
activeMotionDirection = trigger->direction;
|
||||
activeMotionBrightness = trigger->brightness;
|
||||
}
|
||||
|
||||
activeMotionStart = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTime - activeMotionStart >= motionTriggerSettings->delay())
|
||||
activeMotionStart = 0;
|
||||
}
|
||||
|
||||
|
||||
void checkTriggers()
|
||||
{
|
||||
if (!timeTriggerSettings->enabled() && activeTimeTrigger == nullptr &&
|
||||
!motionTriggerSettings->enabled() && activeMotionStart == 0)
|
||||
return;
|
||||
|
||||
updateTimeTrigger();
|
||||
updateMotionTrigger();
|
||||
|
||||
bool inTimeTrigger = timeTriggerSettings->enabled() &&
|
||||
activeTimeTrigger != nullptr &&
|
||||
activeTimeTrigger->brightness;
|
||||
bool timeTriggerChanged = activeTimeTrigger != lastTimeTrigger;
|
||||
lastTimeTrigger = activeTimeTrigger;
|
||||
|
||||
// TODO motion sensor settings
|
||||
bool inMotionTrigger = false; // && (alsoDuringTimeTrigger || !inTimeTrigger)
|
||||
bool motionChanged = false;
|
||||
|
||||
// TODO dummies, replace these with motionSettings-> values later on
|
||||
uint16_t motionBrightness = 0;
|
||||
uint16_t motionTransitionTime = 0;
|
||||
bool inMotionTrigger = (activeMotionStart > 0) && (!inTimeTrigger || motionTriggerSettings->enabledDuringTimeTrigger());
|
||||
bool motionChanged = (activeMotionStart > 0) != lastMotion;
|
||||
lastMotion = (activeMotionStart > 0);
|
||||
|
||||
|
||||
if (!motionChanged && !timeTriggerChanged)
|
||||
@ -462,20 +527,26 @@ void checkTriggers()
|
||||
{
|
||||
_dln("Triggers :: start motion trigger");
|
||||
|
||||
// Start sweep
|
||||
bool sweepDown = true;
|
||||
uint8_t stepsCount = stepsSettings->count();
|
||||
uint16_t offset = sweepDown ? 0 : motionTransitionTime;
|
||||
uint16_t offsetIncrement = stepsCount > 0 ? motionTransitionTime / stepsCount : 0;
|
||||
|
||||
for (uint8_t step = 0; step < stepsCount; step++)
|
||||
if (activeMotionDirection == Nondirectional || motionTriggerSettings->transitionTime() == 0)
|
||||
{
|
||||
stairs->set(step, motionBrightness, motionTransitionTime, offset);
|
||||
stairs->setAll(activeMotionBrightness, motionTriggerSettings->transitionTime(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start sweep
|
||||
uint8_t stepsCount = stepsSettings->count();
|
||||
uint16_t offsetIncrement = stepsCount > 0 ? (motionTriggerSettings->transitionTime() / stepsCount) * 1.5 : 0;
|
||||
uint16_t offset = activeMotionDirection == TopDown ? 0 : (stepsCount - 1) * offsetIncrement;
|
||||
|
||||
if (sweepDown)
|
||||
offset += offsetIncrement;
|
||||
else
|
||||
offset -= offsetIncrement;
|
||||
for (uint8_t step = 0; step < stepsCount; step++)
|
||||
{
|
||||
stairs->set(step, activeMotionBrightness, motionTriggerSettings->transitionTime(), offset);
|
||||
|
||||
if (activeMotionDirection == TopDown)
|
||||
offset += offsetIncrement;
|
||||
else
|
||||
offset -= offsetIncrement;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -485,14 +556,14 @@ void checkTriggers()
|
||||
_dln("Triggers :: motion stopped, falling back to time trigger");
|
||||
|
||||
// Fall back to time trigger value
|
||||
stairs->setAll(activeTimeTrigger->brightness, motionTransitionTime, 0);
|
||||
stairs->setAll(activeTimeTrigger->brightness, motionTriggerSettings->transitionTime(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dln("Triggers :: motion stopped, turning off");
|
||||
|
||||
// No more motion, no active time trigger, turn off
|
||||
stairs->setAll(0, motionTransitionTime, 0);
|
||||
stairs->setAll(0, motionTriggerSettings->transitionTime(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* This code was ported over from Domoticz' SunRiseSet.cpp
|
||||
* https://github.com/domoticz/domoticz/
|
||||
*/
|
||||
#include "praisethesun.h"
|
||||
#include "./praisethesun.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "api.h"
|
||||
#include "./api.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <IPAddress.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "shared.h"
|
||||
#include "./shared.h"
|
||||
#include "../assets/version.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
@ -69,30 +69,8 @@ void handleGetTimeTriggers(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: get time triggers");
|
||||
|
||||
uint8_t count = timeTriggerSettings->triggerCount();
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(count) + JSON_OBJECT_SIZE(3) + count*JSON_OBJECT_SIZE(5));
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["enabled"] = timeTriggerSettings->enabled();
|
||||
root["transitionTime"] = timeTriggerSettings->transitionTime();
|
||||
|
||||
JsonArray& jsonTriggers = root.createNestedArray("triggers");
|
||||
|
||||
for (uint8_t i = 0; i < count; i++)
|
||||
{
|
||||
TimeTrigger* trigger = timeTriggerSettings->trigger(i);
|
||||
|
||||
JsonObject& jsonTrigger = jsonTriggers.createNestedObject();
|
||||
jsonTrigger["time"] = trigger->time;
|
||||
jsonTrigger["daysOfWeek"] = trigger->daysOfWeek;
|
||||
jsonTrigger["brightness"] = trigger->brightness;
|
||||
jsonTrigger["triggerType"] = (uint8_t)trigger->triggerType;
|
||||
jsonTrigger["enabled"] = trigger->enabled;
|
||||
}
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
root.printTo(*response);
|
||||
|
||||
timeTriggerSettings->toJson(*response);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
@ -101,44 +79,47 @@ void handlePostTimeTriggers(AsyncWebServerRequest *request, uint8_t *data, size_
|
||||
{
|
||||
_dln("API :: post time triggers");
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(10) + JSON_OBJECT_SIZE(3) + 10*JSON_OBJECT_SIZE(5) + 510);
|
||||
JsonObject& root = jsonBuffer.parseObject((char*)data);
|
||||
if (!root.success())
|
||||
bool changed;
|
||||
if (timeTriggerSettings->fromJson((char*)data, &changed))
|
||||
{
|
||||
timeTriggerSettings->write();
|
||||
|
||||
if (changed)
|
||||
timeTriggerSettingsChanged = true;
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
else
|
||||
request->send(400);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JsonArray& jsonTriggers = root["triggers"];
|
||||
if (jsonTriggers.size() > 255)
|
||||
|
||||
void handleGetMotionTriggers(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: get motion triggers");
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
motionTriggerSettings->toJson(*response);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handlePostMotionTriggers(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
|
||||
{
|
||||
_dln("API :: post motion triggers");
|
||||
|
||||
bool changed;
|
||||
if (motionTriggerSettings->fromJson((char*)data, &changed))
|
||||
{
|
||||
motionTriggerSettings->write();
|
||||
|
||||
if (changed)
|
||||
motionTriggerSettingsChanged = true;
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
else
|
||||
request->send(400);
|
||||
return;
|
||||
}
|
||||
|
||||
timeTriggerSettings->enabled(root["enabled"]);
|
||||
timeTriggerSettings->transitionTime(root["transitionTime"]);
|
||||
timeTriggerSettings->beginSetTriggers(jsonTriggers.size());
|
||||
|
||||
TimeTrigger trigger;
|
||||
for (uint8_t i = 0; i < jsonTriggers.size(); i++)
|
||||
{
|
||||
JsonObject& jsonTrigger = jsonTriggers[i];
|
||||
|
||||
trigger.time = jsonTrigger["time"];
|
||||
trigger.daysOfWeek = jsonTrigger["daysOfWeek"];
|
||||
trigger.brightness = jsonTrigger["brightness"];
|
||||
trigger.triggerType = (TimeTriggerType)(uint8_t)jsonTrigger["triggerType"];
|
||||
trigger.enabled = jsonTrigger["enabled"];
|
||||
|
||||
timeTriggerSettings->setTrigger(i, &trigger);
|
||||
}
|
||||
|
||||
timeTriggerSettings->endSetTriggers();
|
||||
timeTriggerSettings->write();
|
||||
timeTriggerSettingsChanged = true;
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
|
||||
@ -149,4 +130,7 @@ void registerAPIRoutes(AsyncWebServer* server)
|
||||
|
||||
server->on("/api/triggers/time", HTTP_GET, handleGetTimeTriggers);
|
||||
server->on("/api/triggers/time", HTTP_POST, devNullRequest, devNullFileUpload, handlePostTimeTriggers);
|
||||
|
||||
server->on("/api/triggers/motion", HTTP_GET, handleGetMotionTriggers);
|
||||
server->on("/api/triggers/motion", HTTP_POST, devNullRequest, devNullFileUpload, handlePostMotionTriggers);
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "firmware.h"
|
||||
#include "./firmware.h"
|
||||
#include "../config.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
|
@ -4,11 +4,11 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "settings.h"
|
||||
#include "./settings.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <IPAddress.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "shared.h"
|
||||
#include "./shared.h"
|
||||
#include "../assets/version.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "shared.h"
|
||||
#include "./shared.h"
|
||||
|
||||
void devNullRequest(AsyncWebServerRequest *request) {}
|
||||
void devNullFileUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "static.h"
|
||||
#include "./static.h"
|
||||
#include "../debug.h"
|
||||
#include "../assets/html.h"
|
||||
#include "../assets/js.h"
|
||||
|
70
src/settings/abstractjson.cpp
Normal file
70
src/settings/abstractjson.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "./abstractjson.h"
|
||||
#include <FS.h>
|
||||
|
||||
|
||||
void AbstractJsonSettings::read()
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: opening file");
|
||||
File settingsFile = SPIFFS.open(getFilename(), "r");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: failed to open file");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size = settingsFile.size();
|
||||
if (size > 1024)
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: file size is too large");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: zero size file");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
settingsFile.readBytes(buf.get(), size);
|
||||
|
||||
_dln(buf.get());
|
||||
|
||||
if (fromJson(buf.get()))
|
||||
{
|
||||
_d(getDebugPrefix());
|
||||
_dln(" :: read from file");
|
||||
}
|
||||
else
|
||||
{
|
||||
_d(getDebugPrefix());
|
||||
_dln(" :: failed to parse file");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AbstractJsonSettings::write()
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: opening file for writing");
|
||||
File settingsFile = SPIFFS.open(getFilename(), "w");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_d(getDebugPrefix()); _dln(" :: failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
toJson(settingsFile);
|
||||
_d(getDebugPrefix()); _dln(" :: written to file");
|
||||
}
|
||||
|
||||
|
||||
bool AbstractJsonSettings::fromJson(char* data)
|
||||
{
|
||||
return fromJson(data, nullptr);
|
||||
}
|
28
src/settings/abstractjson.h
Normal file
28
src/settings/abstractjson.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#ifndef __settingsjson
|
||||
#define __settingsjson
|
||||
|
||||
#include "../debug.h"
|
||||
|
||||
class AbstractJsonSettings
|
||||
{
|
||||
protected:
|
||||
virtual const char* getFilename() = 0;
|
||||
virtual const char* getDebugPrefix() = 0;
|
||||
|
||||
public:
|
||||
void read();
|
||||
void write();
|
||||
|
||||
virtual void toJson(Print &print) = 0;
|
||||
virtual bool fromJson(char* data, bool* changed) = 0;
|
||||
|
||||
bool fromJson(char* data);
|
||||
};
|
||||
|
||||
#endif
|
@ -4,65 +4,15 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "connection.h"
|
||||
#include "./connection.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <FS.h>
|
||||
#include "./abstractjson.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
#include "../config.h"
|
||||
#include "../global.h"
|
||||
|
||||
|
||||
|
||||
void ConnectionSettings::read()
|
||||
{
|
||||
_dln("ConnectionSettings :: opening file");
|
||||
File settingsFile = SPIFFS.open(ConnectionSettingsFile, "r");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_dln("ConnectionSettings :: failed to open file");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size = settingsFile.size();
|
||||
if (size > 1024)
|
||||
{
|
||||
_dln("ConnectionSettings :: file size is too large");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_dln("ConnectionSettings :: zero size file");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
settingsFile.readBytes(buf.get(), size);
|
||||
|
||||
_dln(buf.get());
|
||||
|
||||
if (fromJson(buf.get()))
|
||||
_dln("ConnectionSettings :: read from file");
|
||||
else
|
||||
_dln("ConnectionSettings :: failed to parse file");
|
||||
}
|
||||
|
||||
|
||||
void ConnectionSettings::write()
|
||||
{
|
||||
_dln("ConnectionSettings :: opening file for writing");
|
||||
File settingsFile = SPIFFS.open(ConnectionSettingsFile, "w");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_dln("ConnectionSettings:: failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
toJson(settingsFile);
|
||||
_dln("ConnectionSettings:: written to file");
|
||||
}
|
||||
|
||||
|
||||
void ConnectionSettings::toJson(Print &print)
|
||||
{
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(9));
|
||||
@ -82,12 +32,6 @@ void ConnectionSettings::toJson(Print &print)
|
||||
}
|
||||
|
||||
|
||||
bool ConnectionSettings::fromJson(char* data)
|
||||
{
|
||||
return fromJson(data, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool ConnectionSettings::fromJson(char* data, bool* changed)
|
||||
{
|
||||
if (changed != nullptr)
|
||||
|
@ -10,7 +10,9 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <IPAddress.h>
|
||||
#include "./abstractjson.h"
|
||||
#include "../charproperties.h"
|
||||
#include "../config.h"
|
||||
|
||||
|
||||
enum ConnectionSettingsFlags
|
||||
@ -21,7 +23,7 @@ enum ConnectionSettingsFlags
|
||||
};
|
||||
|
||||
|
||||
class ConnectionSettings : CharProperties
|
||||
class ConnectionSettings : public AbstractJsonSettings
|
||||
{
|
||||
private:
|
||||
char* mHostname = nullptr;
|
||||
@ -32,13 +34,12 @@ class ConnectionSettings : CharProperties
|
||||
IPAddress mSubnetMask = (uint32_t)0;
|
||||
IPAddress mGateway = (uint32_t)0;
|
||||
|
||||
protected:
|
||||
virtual const char* getFilename() { return ConnectionSettingsFile; };
|
||||
virtual const char* getDebugPrefix() { return "ConnectionSettings"; };
|
||||
|
||||
public:
|
||||
void read();
|
||||
void write();
|
||||
|
||||
|
||||
void toJson(Print &print);
|
||||
bool fromJson(char* data);
|
||||
bool fromJson(char* data, bool* changed);
|
||||
|
||||
|
||||
|
@ -4,20 +4,11 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "steps.h"
|
||||
#include <FS.h>
|
||||
#include "./steps.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include "../debug.h"
|
||||
|
||||
|
||||
struct Header
|
||||
{
|
||||
uint8_t version;
|
||||
uint8_t stepCount;
|
||||
bool useCurve;
|
||||
};
|
||||
|
||||
|
||||
|
||||
StepsSettings::StepsSettings()
|
||||
{
|
||||
for (uint8_t i = 0; i < MaxStepCount; i++)
|
||||
@ -25,41 +16,63 @@ StepsSettings::StepsSettings()
|
||||
}
|
||||
|
||||
|
||||
void StepsSettings::read()
|
||||
void StepsSettings::toJson(Print &print)
|
||||
{
|
||||
_dln("StepsSettings :: Loading step settings");
|
||||
File f = SPIFFS.open(StepSettingsFile, "r");
|
||||
if (!f)
|
||||
return;
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(16) + JSON_OBJECT_SIZE(3));
|
||||
|
||||
if (!f.available())
|
||||
return;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["count"] = count();
|
||||
root["useCurve"] = useCurve();
|
||||
|
||||
Header header;
|
||||
f.readBytes((char*)&header, sizeof(Header));
|
||||
JsonArray& jsonCurveShift = root.createNestedArray("curveShift");
|
||||
for (uint8_t step = 0; step < MaxStepCount; step++)
|
||||
jsonCurveShift.add(curveShift(step));
|
||||
|
||||
if (header.version != 1)
|
||||
return;
|
||||
|
||||
mUseCurve = (header.useCurve == 1);
|
||||
f.readBytes((char*)&mCurveShift, header.stepCount * sizeof(uint16_t));
|
||||
f.close();
|
||||
root.printTo(print);
|
||||
}
|
||||
|
||||
|
||||
void StepsSettings::write()
|
||||
bool StepsSettings::fromJson(char* data, bool* changed)
|
||||
{
|
||||
_dln("StepsSettings :: Saving step settings");
|
||||
File f = SPIFFS.open(StepSettingsFile, "w");
|
||||
if (!f)
|
||||
return;
|
||||
if (changed != nullptr)
|
||||
*changed = false;
|
||||
|
||||
Header header;
|
||||
header.version = 1;
|
||||
header.useCurve = mUseCurve;
|
||||
header.stepCount = mCount;
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(16) + JSON_OBJECT_SIZE(3) + 80);
|
||||
JsonObject& root = jsonBuffer.parseObject(data);
|
||||
|
||||
f.write((uint8_t*)&header, sizeof(Header));
|
||||
f.write((uint8_t*)&mCurveShift, header.stepCount * sizeof(uint16_t));
|
||||
f.close();
|
||||
if (!root.success())
|
||||
return false;
|
||||
|
||||
uint8_t jsonCount = root["count"];
|
||||
bool jsonUseCurve = root["useCurve"];
|
||||
|
||||
if (jsonCount != count() ||
|
||||
jsonUseCurve != useCurve())
|
||||
{
|
||||
count(jsonCount);
|
||||
useCurve(jsonUseCurve);
|
||||
|
||||
if (changed != nullptr)
|
||||
*changed = true;
|
||||
}
|
||||
|
||||
|
||||
JsonArray& jsonCurveShift = root["curveShift"];
|
||||
uint8_t stepCount = jsonCurveShift.size();
|
||||
if (stepCount >= MaxStepCount)
|
||||
stepCount = MaxStepCount - 1;
|
||||
|
||||
for (uint8_t step = 0; step < stepCount; step++)
|
||||
{
|
||||
uint16_t value = jsonCurveShift[step];
|
||||
|
||||
if (value != curveShift(step))
|
||||
{
|
||||
curveShift(step, value);
|
||||
if (changed != nullptr)
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -8,22 +8,29 @@
|
||||
#define __settingssteps
|
||||
|
||||
#include <stdint.h>
|
||||
#include "./abstractjson.h"
|
||||
#include "../config.h"
|
||||
|
||||
#define MaxStepCount 16
|
||||
|
||||
|
||||
class StepsSettings
|
||||
class StepsSettings : public AbstractJsonSettings
|
||||
{
|
||||
private:
|
||||
uint8_t mCount = 16;
|
||||
uint8_t mCount = MaxStepCount;
|
||||
bool mUseCurve = true;
|
||||
uint16_t mCurveShift[MaxStepCount];
|
||||
|
||||
protected:
|
||||
virtual const char* getFilename() { return StepsSettingsFile; };
|
||||
virtual const char* getDebugPrefix() { return "StepsSettings"; };
|
||||
|
||||
public:
|
||||
StepsSettings();
|
||||
|
||||
void read();
|
||||
void write();
|
||||
void toJson(Print &print);
|
||||
bool fromJson(char* data, bool* changed);
|
||||
|
||||
|
||||
uint8_t count() { return mCount; }
|
||||
void count(uint8_t value) { mCount = value; }
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "system.h"
|
||||
#include "./system.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <FS.h>
|
||||
#include "../debug.h"
|
||||
@ -13,56 +13,6 @@
|
||||
|
||||
|
||||
|
||||
void SystemSettings::read()
|
||||
{
|
||||
_dln("SystemSettings :: opening file");
|
||||
File settingsFile = SPIFFS.open(SystemSettingsFile, "r");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_dln("SystemSettings :: failed to open file");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size = settingsFile.size();
|
||||
if (size > 1024)
|
||||
{
|
||||
_dln("SystemSettings :: file size is too large");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_dln("SystemSettings :: zero size file");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
settingsFile.readBytes(buf.get(), size);
|
||||
|
||||
_dln(buf.get());
|
||||
|
||||
if (fromJson(buf.get()))
|
||||
_dln("SystemSettings :: read from file");
|
||||
else
|
||||
_dln("SystemSettings :: failed to parse file");
|
||||
}
|
||||
|
||||
|
||||
void SystemSettings::write()
|
||||
{
|
||||
_dln("SystemSettings :: opening file for writing");
|
||||
File settingsFile = SPIFFS.open(SystemSettingsFile, "w");
|
||||
if (!settingsFile)
|
||||
{
|
||||
_dln("SystemSettings:: failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
toJson(settingsFile);
|
||||
_dln("SystemSettings:: written to file");
|
||||
}
|
||||
|
||||
|
||||
void SystemSettings::toJson(Print &print)
|
||||
{
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(5));
|
||||
@ -87,11 +37,6 @@ void SystemSettings::toJson(Print &print)
|
||||
}
|
||||
|
||||
|
||||
bool SystemSettings::fromJson(char* data)
|
||||
{
|
||||
return fromJson(data, nullptr);
|
||||
}
|
||||
|
||||
bool SystemSettings::fromJson(char* data, bool* changed)
|
||||
{
|
||||
if (changed != nullptr)
|
||||
|
@ -11,9 +11,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../charproperties.h"
|
||||
#include "./abstractjson.h"
|
||||
|
||||
|
||||
class SystemSettings : CharProperties
|
||||
class SystemSettings : public AbstractJsonSettings
|
||||
{
|
||||
private:
|
||||
double mLatitude = 0;
|
||||
@ -34,13 +35,12 @@ class SystemSettings : CharProperties
|
||||
// TODO loginUsername
|
||||
// TODO loginPassword
|
||||
|
||||
protected:
|
||||
virtual const char* getFilename() { return SystemSettingsFile; };
|
||||
virtual const char* getDebugPrefix() { return "SystemSettings"; };
|
||||
|
||||
public:
|
||||
void read();
|
||||
void write();
|
||||
|
||||
|
||||
void toJson(Print &print);
|
||||
bool fromJson(char* data);
|
||||
bool fromJson(char* data, bool* changed);
|
||||
|
||||
|
||||
|
81
src/settings/triggers/motion.cpp
Normal file
81
src/settings/triggers/motion.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "./motion.h"
|
||||
#include <string.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "../../debug.h"
|
||||
#include "../../global.h"
|
||||
|
||||
|
||||
void MotionTriggerSettings::toJson(Print &print)
|
||||
{
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(2) + 2*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["enabled"] = enabled();
|
||||
root["enabledDuringTimeTrigger"] = enabledDuringTimeTrigger();
|
||||
root["transitionTime"] = transitionTime();
|
||||
root["delay"] = delay();
|
||||
|
||||
JsonArray& jsonTriggers = root.createNestedArray("triggers");
|
||||
|
||||
for (uint8_t i = 0; i < triggerCount(); i++)
|
||||
{
|
||||
MotionTrigger* triggerItem = trigger(i);
|
||||
|
||||
JsonObject& jsonTrigger = jsonTriggers.createNestedObject();
|
||||
jsonTrigger["pin"] = triggerItem->pin;
|
||||
jsonTrigger["brightness"] = triggerItem->brightness;
|
||||
jsonTrigger["direction"] = (uint8_t)triggerItem->direction;
|
||||
jsonTrigger["enabled"] = triggerItem->enabled;
|
||||
}
|
||||
|
||||
root.printTo(print);
|
||||
}
|
||||
|
||||
|
||||
bool MotionTriggerSettings::fromJson(char* data, bool* changed)
|
||||
{
|
||||
if (changed != nullptr)
|
||||
*changed = false;
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(2) + 2*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 200);
|
||||
JsonObject& root = jsonBuffer.parseObject(data);
|
||||
|
||||
if (!root.success())
|
||||
return false;
|
||||
|
||||
|
||||
enabled(root["enabled"]);
|
||||
enabledDuringTimeTrigger(root["enabledDuringTimeTrigger"]);
|
||||
transitionTime(root["transitionTime"]);
|
||||
delay(root["delay"]);
|
||||
|
||||
JsonArray& jsonTriggers = root["triggers"];
|
||||
if (mTriggers != nullptr)
|
||||
delete [] mTriggers;
|
||||
|
||||
mTriggerCount = jsonTriggers.size();
|
||||
mTriggers = new MotionTrigger[mTriggerCount];
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < mTriggerCount; i++)
|
||||
{
|
||||
JsonObject& jsonTrigger = jsonTriggers[i];
|
||||
MotionTrigger* trigger = &mTriggers[i];
|
||||
|
||||
trigger->pin = jsonTrigger["pin"];
|
||||
trigger->brightness = jsonTrigger["brightness"];
|
||||
trigger->direction = (MotionDirection)(uint8_t)jsonTrigger["direction"];
|
||||
trigger->enabled = jsonTrigger["enabled"];
|
||||
}
|
||||
|
||||
if (changed != nullptr)
|
||||
*changed = true;
|
||||
|
||||
return true;
|
||||
}
|
67
src/settings/triggers/motion.h
Normal file
67
src/settings/triggers/motion.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#ifndef __settingstriggersmotion
|
||||
#define __settingstriggersmotion
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../../config.h"
|
||||
#include "../abstractjson.h"
|
||||
|
||||
|
||||
enum MotionDirection
|
||||
{
|
||||
Nondirectional = 1,
|
||||
TopDown = 2,
|
||||
BottomUp = 3
|
||||
};
|
||||
|
||||
|
||||
struct MotionTrigger
|
||||
{
|
||||
uint8_t pin;
|
||||
uint8_t brightness;
|
||||
MotionDirection direction;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
|
||||
class MotionTriggerSettings : public AbstractJsonSettings
|
||||
{
|
||||
private:
|
||||
bool mEnabled = false;
|
||||
bool mEnabledDuringTimeTrigger = false;
|
||||
uint16_t mTransitionTime = 0;
|
||||
uint32_t mDelay = 0;
|
||||
uint8_t mTriggerCount = 0;
|
||||
MotionTrigger* mTriggers = nullptr;
|
||||
|
||||
protected:
|
||||
virtual const char* getFilename() { return MotionTriggerSettingsFile; };
|
||||
virtual const char* getDebugPrefix() { return "MotionTriggerSettings"; };
|
||||
|
||||
public:
|
||||
void toJson(Print &print);
|
||||
bool fromJson(char* data, bool* changed);
|
||||
|
||||
|
||||
bool enabled() { return mEnabled; }
|
||||
void enabled(bool value) { mEnabled = value; }
|
||||
|
||||
bool enabledDuringTimeTrigger() { return mEnabledDuringTimeTrigger; }
|
||||
void enabledDuringTimeTrigger(bool value) { mEnabledDuringTimeTrigger = value; }
|
||||
|
||||
uint16_t transitionTime() { return mTransitionTime; }
|
||||
void transitionTime(uint16_t value) { mTransitionTime = value; }
|
||||
|
||||
uint32_t delay() { return mDelay; }
|
||||
void delay(uint32_t value) { mDelay = value; }
|
||||
|
||||
uint8_t triggerCount() { return mTriggerCount; }
|
||||
MotionTrigger* trigger(uint8_t index) { return &mTriggers[index]; }
|
||||
};
|
||||
|
||||
#endif
|
@ -4,9 +4,9 @@
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "time.h"
|
||||
#include "./time.h"
|
||||
#include <string.h>
|
||||
#include <FS.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "../../debug.h"
|
||||
#include "../../global.h"
|
||||
#include "../../praisethesun.h"
|
||||
@ -46,63 +46,77 @@ DayOfWeek toDayOfWeek(timeDayOfWeek_t timeDay)
|
||||
}
|
||||
|
||||
|
||||
struct Header
|
||||
|
||||
|
||||
void TimeTriggerSettings::toJson(Print &print)
|
||||
{
|
||||
uint8_t version;
|
||||
uint8_t triggerCount;
|
||||
uint16_t transitionTime;
|
||||
bool enabled;
|
||||
};
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(10) + JSON_OBJECT_SIZE(3) + 10*JSON_OBJECT_SIZE(5));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["enabled"] = enabled();
|
||||
root["transitionTime"] = transitionTime();
|
||||
|
||||
void TimeTriggerSettings::read()
|
||||
{
|
||||
_dln("TimeTriggerSettings :: Loading time triggers");
|
||||
File f = SPIFFS.open(TimeTriggerSettingsFile, "r");
|
||||
if (!f)
|
||||
return;
|
||||
JsonArray& jsonTriggers = root.createNestedArray("triggers");
|
||||
|
||||
if (!f.available())
|
||||
return;
|
||||
for (uint8_t i = 0; i < triggerCount(); i++)
|
||||
{
|
||||
TimeTrigger* triggerItem = trigger(i);
|
||||
|
||||
Header header;
|
||||
f.readBytes((char*)&header, sizeof(Header));
|
||||
JsonObject& jsonTrigger = jsonTriggers.createNestedObject();
|
||||
jsonTrigger["time"] = triggerItem->time;
|
||||
jsonTrigger["daysOfWeek"] = triggerItem->daysOfWeek;
|
||||
jsonTrigger["brightness"] = triggerItem->brightness;
|
||||
jsonTrigger["triggerType"] = (uint8_t)triggerItem->triggerType;
|
||||
jsonTrigger["enabled"] = triggerItem->enabled;
|
||||
}
|
||||
|
||||
if (header.version != 1)
|
||||
return;
|
||||
|
||||
mEnabled = header.enabled;
|
||||
mTransitionTime = header.transitionTime;
|
||||
beginSetTriggers(header.triggerCount);
|
||||
|
||||
if (header.triggerCount > 0)
|
||||
f.readBytes((char*)&mTriggers, header.triggerCount * sizeof(TimeTrigger));
|
||||
|
||||
endSetTriggers();
|
||||
|
||||
f.close();
|
||||
root.printTo(print);
|
||||
}
|
||||
|
||||
|
||||
void TimeTriggerSettings::write()
|
||||
bool TimeTriggerSettings::fromJson(char* data, bool* changed)
|
||||
{
|
||||
_dln("TimeTriggerSettings :: Saving time triggers");
|
||||
File f = SPIFFS.open(TimeTriggerSettingsFile, "w");
|
||||
if (!f)
|
||||
return;
|
||||
if (changed != nullptr)
|
||||
*changed = false;
|
||||
|
||||
Header header;
|
||||
header.version = 1;
|
||||
header.enabled = mEnabled;
|
||||
header.transitionTime = mTransitionTime;
|
||||
header.triggerCount = mTriggerCount;
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(10) + JSON_OBJECT_SIZE(3) + 10*JSON_OBJECT_SIZE(5) + 270);
|
||||
JsonObject& root = jsonBuffer.parseObject(data);
|
||||
|
||||
f.write((uint8_t*)&header, sizeof(Header));
|
||||
f.write((uint8_t*)&mTriggers, header.triggerCount * sizeof(TimeTrigger));
|
||||
f.close();
|
||||
if (!root.success())
|
||||
return false;
|
||||
|
||||
|
||||
enabled(root["enabled"]);
|
||||
transitionTime(root["transitionTime"]);
|
||||
|
||||
JsonArray& jsonTriggers = root["triggers"];
|
||||
if (mTriggers != nullptr)
|
||||
delete [] mTriggers;
|
||||
|
||||
mTriggerCount = jsonTriggers.size();
|
||||
mTriggers = new TimeTrigger[mTriggerCount];
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < mTriggerCount; i++)
|
||||
{
|
||||
JsonObject& jsonTrigger = jsonTriggers[i];
|
||||
TimeTrigger* trigger = &mTriggers[i];
|
||||
|
||||
trigger->time = jsonTrigger["time"];
|
||||
trigger->daysOfWeek = jsonTrigger["daysOfWeek"];
|
||||
trigger->brightness = jsonTrigger["brightness"];
|
||||
trigger->triggerType = (TimeTriggerType)(uint8_t)jsonTrigger["triggerType"];
|
||||
trigger->enabled = jsonTrigger["enabled"];
|
||||
}
|
||||
|
||||
if (changed != nullptr)
|
||||
*changed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TimeTrigger* TimeTriggerSettings::getActiveTrigger(tmElements_t &time)
|
||||
{
|
||||
if (mTriggerCount == 0)
|
||||
@ -176,55 +190,3 @@ TimeTrigger* TimeTriggerSettings::getActiveTrigger(tmElements_t &time)
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void TimeTriggerSettings::beginSetTriggers(uint8_t count)
|
||||
{
|
||||
if (mTriggers != nullptr)
|
||||
delete [] mTriggers;
|
||||
|
||||
mTriggers = new TimeTrigger[count];
|
||||
mTriggerCount = count;
|
||||
}
|
||||
|
||||
|
||||
void TimeTriggerSettings::setTrigger(uint8_t index, TimeTrigger* value)
|
||||
{
|
||||
memcpy(&mTriggers[index], value, sizeof(TimeTrigger));
|
||||
}
|
||||
|
||||
|
||||
void TimeTriggerSettings::endSetTriggers()
|
||||
{
|
||||
/* No need to sort, sunrise / sunset triggers already mess things up anyways
|
||||
// Sort triggers by time of day
|
||||
// Based on the Comb sort implementation by Rob Tillaart
|
||||
// http://forum.arduino.cc/index.php?topic=280486.0
|
||||
uint8_t i, j;
|
||||
uint8_t gap;
|
||||
bool swapped = true;
|
||||
TimeTrigger temp;
|
||||
|
||||
gap = mTriggerCount;
|
||||
while (gap > 1 || swapped)
|
||||
{
|
||||
if (gap > 1)
|
||||
{
|
||||
gap = gap * 10/13;
|
||||
if (gap == 9 || gap == 10) gap = 11;
|
||||
}
|
||||
|
||||
swapped = false;
|
||||
for (i = 0, j = gap; j < mTriggerCount; i++, j++)
|
||||
{
|
||||
if (mTriggers[i].time > mTriggers[j].time)
|
||||
{
|
||||
temp = mTriggers[i];
|
||||
mTriggers[i] = mTriggers[j];
|
||||
mTriggers[j] = temp;
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <TimeLib.h>
|
||||
#include "../../config.h"
|
||||
#include "../abstractjson.h"
|
||||
|
||||
enum DayOfWeek
|
||||
{
|
||||
@ -44,7 +46,7 @@ struct TimeTrigger
|
||||
};
|
||||
|
||||
|
||||
class TimeTriggerSettings
|
||||
class TimeTriggerSettings : public AbstractJsonSettings
|
||||
{
|
||||
private:
|
||||
bool mEnabled = false;
|
||||
@ -52,9 +54,13 @@ class TimeTriggerSettings
|
||||
uint8_t mTriggerCount = 0;
|
||||
TimeTrigger* mTriggers = nullptr;
|
||||
|
||||
protected:
|
||||
virtual const char* getFilename() { return ConnectionSettingsFile; };
|
||||
virtual const char* getDebugPrefix() { return "ConnectionSettings"; };
|
||||
|
||||
public:
|
||||
void read();
|
||||
void write();
|
||||
void toJson(Print &print);
|
||||
bool fromJson(char* data, bool* changed);
|
||||
|
||||
|
||||
TimeTrigger* getActiveTrigger(tmElements_t &time);
|
||||
@ -68,10 +74,6 @@ class TimeTriggerSettings
|
||||
|
||||
uint8_t triggerCount() { return mTriggerCount; }
|
||||
TimeTrigger* trigger(uint8_t index) { return &mTriggers[index]; }
|
||||
|
||||
void beginSetTriggers(uint8_t count);
|
||||
void setTrigger(uint8_t index, TimeTrigger* value);
|
||||
void endSetTriggers();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
#include "stairs.h"
|
||||
#include "./stairs.h"
|
||||
#include <Math.h>
|
||||
#include <FS.h>
|
||||
#include "debug.h"
|
||||
#include "global.h"
|
||||
#include "./debug.h"
|
||||
#include "./global.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef __Stairs
|
||||
#define __Stairs
|
||||
|
||||
#include "components/PCA9685.h"
|
||||
#include "config.h"
|
||||
#include "settings/steps.h"
|
||||
#include "./components/PCA9685.h"
|
||||
#include "./config.h"
|
||||
#include "./settings/steps.h"
|
||||
|
||||
struct Step
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user