Reintroduced PCA9685 and Stairs classes
Compiles, but lacks the tick implementation
This commit is contained in:
parent
0aca40c71e
commit
42647f0db7
@ -55,3 +55,7 @@ To rebuild all the assets and compile or upload the source in one go, two tasks
|
||||
|
||||
1. ```gulp build``` first runs all the tasks run by a regular ```gulp```, then builds the source code using ```platformio run```
|
||||
1. ```gulp upload``` is similar, but executes ```platformio run -t upload``` to directly upload the newly compiled source to the ESP8266
|
||||
|
||||
### version.h
|
||||
|
||||
The version.h file is generated based on the current GitVersion, which means it changes if you build again right after committing, which causes a change that needs to be committed... [did you mean: recursion?](https://www.google.nl/search?q=recursion) The best way I found to deal with this is commit your changes, build, then [amend the commit](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) with the updated version.h before pushing the changes. This ensures the version.h is in sync when cloning the repository.
|
@ -4,11 +4,11 @@
|
||||
const uint8_t VersionMajor = 2;
|
||||
const uint8_t VersionMinor = 0;
|
||||
const uint8_t VersionPatch = 0;
|
||||
const uint8_t VersionMetadata = 3;
|
||||
const uint8_t VersionMetadata = 4;
|
||||
const char VersionBranch[] = "release/2.0";
|
||||
const char VersionSha[] = "61d544f6f347c875e64b1e79985eeabd52ee1c9f";
|
||||
const char VersionSha[] = "176fa2a7bae0e9604a70c69da27b68819b479b73";
|
||||
const char VersionSemVer[] = "2.0.0-beta.1";
|
||||
const char VersionFullSemVer[] = "2.0.0-beta.1+3";
|
||||
const char VersionCommitDate[] = "2018-01-03";
|
||||
const char VersionFullSemVer[] = "2.0.0-beta.1+4";
|
||||
const char VersionCommitDate[] = "2018-01-04";
|
||||
|
||||
#endif
|
||||
|
@ -18,7 +18,7 @@ void PCA9685::setAddress(uint8_t address, uint8_t pinSDA, uint8_t pinSCL)
|
||||
|
||||
void PCA9685::setAddress(uint8_t address)
|
||||
{
|
||||
this->address = address;
|
||||
this->mAddress = address;
|
||||
}
|
||||
|
||||
|
||||
@ -26,11 +26,11 @@ uint8_t PCA9685::read(uint8_t registerAddress)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
Wire.beginTransmission(this->address);
|
||||
Wire.beginTransmission(this->mAddress);
|
||||
Wire.write(registerAddress);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(this->address, (uint8_t)1);
|
||||
Wire.requestFrom(this->mAddress, (uint8_t)1);
|
||||
if (Wire.available())
|
||||
result = Wire.read();
|
||||
|
||||
@ -40,7 +40,7 @@ uint8_t PCA9685::read(uint8_t registerAddress)
|
||||
|
||||
void PCA9685::write(uint8_t registerAddress, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(this->address);
|
||||
Wire.beginTransmission(this->mAddress);
|
||||
Wire.write(registerAddress);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
@ -97,7 +97,7 @@ void PCA9685::setPWM(uint8_t pin, uint16_t value)
|
||||
|
||||
void PCA9685::setPWM(uint8_t pin, uint16_t on, uint16_t off)
|
||||
{
|
||||
Wire.beginTransmission(this->address);
|
||||
Wire.beginTransmission(this->mAddress);
|
||||
this->write(PCA9685::RegisterLED0OnL + (4 * pin));
|
||||
this->write(on);
|
||||
this->write(on >> 8);
|
||||
@ -124,7 +124,7 @@ void PCA9685::setAll(uint16_t value)
|
||||
|
||||
void PCA9685::setAll(uint16_t on, uint16_t off)
|
||||
{
|
||||
Wire.beginTransmission(this->address);
|
||||
Wire.beginTransmission(this->mAddress);
|
||||
this->write(PCA9685::RegisterAllLEDOnL);
|
||||
this->write(on);
|
||||
this->write(on >> 8);
|
||||
|
@ -11,7 +11,7 @@
|
||||
class PCA9685
|
||||
{
|
||||
private:
|
||||
uint8_t address;
|
||||
uint8_t mAddress;
|
||||
|
||||
protected:
|
||||
uint8_t read(uint8_t registerAddress);
|
||||
|
@ -14,7 +14,9 @@ static const char* DefaultAPSSIDPrefix = "Stairs-";
|
||||
static const uint32_t StationModeTimeout = 30000;
|
||||
|
||||
|
||||
/*
|
||||
static const char* StepSettingsFile = "/stepsettings";
|
||||
|
||||
|
||||
// Pins for the I2C bus
|
||||
static const uint8_t PinSDA = 13;
|
||||
static const uint8_t PinSCL = 12;
|
||||
@ -23,6 +25,6 @@ static const uint8_t PinSCL = 12;
|
||||
// I2C address and PWM frequency of the PCA9685 board
|
||||
static const uint8_t PWMDriverAddress = 0x40;
|
||||
static const uint16_t PWMDriverPWMFrequency = 1600;
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
@ -9,6 +9,12 @@
|
||||
ConnectionSettings* connectionSettings = new ConnectionSettings();
|
||||
bool connectionSettingsChanged = false;
|
||||
|
||||
StepsSettings* stepsSettings = new StepsSettings();
|
||||
bool stepsSettingsChanged = false;
|
||||
|
||||
|
||||
Stairs* stairs;
|
||||
|
||||
bool shouldReboot = false;
|
||||
|
||||
uint32_t currentTime;
|
||||
|
@ -11,10 +11,17 @@
|
||||
#include <stdbool.h>
|
||||
#include <IPAddress.h>
|
||||
#include "settings/connection.h"
|
||||
#include "settings/steps.h"
|
||||
#include "stairs.h"
|
||||
|
||||
extern ConnectionSettings* connectionSettings;
|
||||
extern bool connectionSettingsChanged;
|
||||
|
||||
extern StepsSettings* stepsSettings;
|
||||
extern bool stepsSettingsChanged;
|
||||
|
||||
extern Stairs* stairs;
|
||||
|
||||
extern bool shouldReboot;
|
||||
|
||||
extern uint32_t currentTime;
|
||||
|
386
src/main.cpp
386
src/main.cpp
@ -15,11 +15,13 @@ extern "C" {
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "settings/connection.h"
|
||||
#include "global.h"
|
||||
#include "components/PCA9685.h"
|
||||
#include "settings/connection.h"
|
||||
#include "server/static.h"
|
||||
#include "server/api.h"
|
||||
#include "server/settings.h"
|
||||
#include "server/firmware.h"
|
||||
#include "server/api.h"
|
||||
|
||||
|
||||
ADC_MODE(ADC_VCC);
|
||||
@ -37,6 +39,8 @@ void handleNotFound(AsyncWebServerRequest* request);
|
||||
|
||||
|
||||
AsyncWebServer server(80);
|
||||
PCA9685* pwmDriver;
|
||||
|
||||
bool accessPoint = false;
|
||||
bool stationMode = false;
|
||||
bool forceAccessPoint = false;
|
||||
@ -58,6 +62,34 @@ void setup()
|
||||
_dln("Setup :: failed to mount file system");
|
||||
|
||||
connectionSettings->read();
|
||||
stepsSettings->read();
|
||||
|
||||
|
||||
_dln("Setup :: initializing PCA9685");
|
||||
pwmDriver = new PCA9685();
|
||||
pwmDriver->setAddress(PWMDriverAddress, PinSDA, PinSCL);
|
||||
pwmDriver->setPWMFrequency(PWMDriverPWMFrequency);
|
||||
|
||||
_dln("Setup :: initializing Stairs");
|
||||
stairs = new Stairs();
|
||||
stairs->init(pwmDriver);
|
||||
|
||||
|
||||
_dln("Setup :: starting initialization sequence");
|
||||
stairs->setAll(0);
|
||||
|
||||
stairs->set(0, 255);
|
||||
delay(300);
|
||||
|
||||
uint8_t stepCount = stepsSettings->count();
|
||||
for (int step = 1; step < stepCount; step++)
|
||||
{
|
||||
stairs->set(step - 1, 0);
|
||||
stairs->set(step, 255);
|
||||
delay(300);
|
||||
}
|
||||
|
||||
stairs->set(stepCount - 1, 0);
|
||||
|
||||
_dln("Setup :: initializing WiFi");
|
||||
WiFi.persistent(false);
|
||||
@ -75,8 +107,9 @@ void setup()
|
||||
|
||||
_dln("Setup :: registering routes");
|
||||
registerStaticRoutes(&server);
|
||||
registerAPIRoutes(&server);
|
||||
registerSettingsRoutes(&server);
|
||||
registerFirmwareRoutes(&server);
|
||||
registerAPIRoutes(&server);
|
||||
|
||||
_dln("Setup :: starting HTTP server");
|
||||
server.onNotFound(handleNotFound);
|
||||
@ -88,7 +121,7 @@ void loop()
|
||||
{
|
||||
if (shouldReboot)
|
||||
{
|
||||
_dln("Reboot requested, bye bye!");
|
||||
_dln("Loop :: reboot requested, so long and thanks for all the fish!");
|
||||
delay(100);
|
||||
ESP.restart();
|
||||
}
|
||||
@ -144,6 +177,7 @@ void loop()
|
||||
}
|
||||
|
||||
updateLED();
|
||||
stairs->tick();
|
||||
}
|
||||
|
||||
|
||||
@ -229,80 +263,7 @@ void wifiEvent(WiFiEvent_t event)
|
||||
|
||||
void updateLED()
|
||||
{
|
||||
//while (WiFi.status() != WL_CONNECTED)
|
||||
//{
|
||||
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
void handleNotFound(AsyncWebServerRequest *request)
|
||||
{
|
||||
_d("HTTP :: not found: "); _dln(request->url());
|
||||
request->send(404);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
uint8_t currentModeIdentifier;
|
||||
IMode* currentMode;
|
||||
|
||||
|
||||
// Forward declarations
|
||||
void checkRequest();
|
||||
void handleRequest(uint8_t* packet);
|
||||
IMode* createMode(uint8_t identifier);
|
||||
void setCurrentMode(IMode *mode, uint8_t identifier);
|
||||
void handleCurrentMode();
|
||||
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
#ifdef SerialDebug
|
||||
Serial.begin(115200);
|
||||
delay(5000);
|
||||
#endif
|
||||
|
||||
|
||||
_dln("Initializing PCA9685");
|
||||
_d("Version: ");
|
||||
_dln(FirmwareVersion);
|
||||
|
||||
pwmDriver = new PCA9685();
|
||||
pwmDriver->setAddress(PWMDriverAddress, PinSDA, PinSCL);
|
||||
pwmDriver->setPWMFrequency(PWMDriverPWMFrequency);
|
||||
|
||||
_dln("Initializing Stairs");
|
||||
|
||||
stairs = new Stairs();
|
||||
stairs->init(pwmDriver);
|
||||
|
||||
_dln("Initializing WiFi");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.hostname(WiFiHostname);
|
||||
WiFi.begin(WiFiSSID, WiFiPassword);
|
||||
|
||||
|
||||
_dln("Starting initialization sequence");
|
||||
stairs->setAll(IStairs::Off);
|
||||
stairs->set(0, IStairs::On);
|
||||
delay(300);
|
||||
|
||||
for (int step = 1; step < StepCount; step++)
|
||||
{
|
||||
stairs->set(step - 1, IStairs::Off);
|
||||
stairs->set(step, IStairs::On);
|
||||
delay(300);
|
||||
}
|
||||
|
||||
stairs->set(StepCount - 1, IStairs::Off);
|
||||
|
||||
|
||||
_dln("Waiting for WiFi");
|
||||
|
||||
/*
|
||||
// Pulsate the bottom step while WiFi is connecting
|
||||
uint16_t brightness = 0;
|
||||
uint16_t speed = 16;
|
||||
@ -316,273 +277,12 @@ void setup()
|
||||
stairs->set(0, brightness);
|
||||
delay(16);
|
||||
}
|
||||
|
||||
setCurrentMode(new StaticMode(), Mode::Static);
|
||||
|
||||
|
||||
_d("IP address: ");
|
||||
_dln(WiFi.localIP());
|
||||
|
||||
_dln("Starting UDP server");
|
||||
|
||||
// Start the UDP server
|
||||
udpServer.begin(UDPPort);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
uint32_t currentTime;
|
||||
|
||||
// Note: the packet size must at least be able to accomodate the
|
||||
// command with the largest parameter list, there is no overflow
|
||||
// checking in the mode classes!
|
||||
const uint8_t maxPacketSize = 255;
|
||||
|
||||
uint8_t packet[maxPacketSize];
|
||||
uint8_t* packetRef;
|
||||
|
||||
void loop()
|
||||
void handleNotFound(AsyncWebServerRequest *request)
|
||||
{
|
||||
currentTime = millis();
|
||||
|
||||
checkRequest();
|
||||
handleCurrentMode();
|
||||
_d("HTTP :: not found: "); _dln(request->url());
|
||||
request->send(404);
|
||||
}
|
||||
|
||||
|
||||
void checkRequest()
|
||||
{
|
||||
int packetSize = udpServer.parsePacket();
|
||||
if (packetSize)
|
||||
{
|
||||
_dln("Handling incoming packet");
|
||||
|
||||
memset(packet, 0, sizeof(packet));
|
||||
int length = udpServer.read(packet, maxPacketSize - 1);
|
||||
if (length && packet[0])
|
||||
{
|
||||
packetRef = packet;
|
||||
handleRequest(packetRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handlePing(uint8_t* packet)
|
||||
{
|
||||
_dln("Handling Ping");
|
||||
|
||||
udpServer.write(Command::Ping);
|
||||
udpServer.write(StepCount);
|
||||
}
|
||||
|
||||
|
||||
void handleGetMode(uint8_t* packet)
|
||||
{
|
||||
_dln("Handling GetMode");
|
||||
|
||||
udpServer.write(Command::GetMode);
|
||||
udpServer.write(currentModeIdentifier);
|
||||
currentMode->write(&udpServer);
|
||||
}
|
||||
|
||||
|
||||
void handleSetMode(uint8_t* packet)
|
||||
{
|
||||
_dln("Handling SetMode");
|
||||
uint8_t newIdentifier = *packet;
|
||||
packet++;
|
||||
|
||||
IMode* newMode = createMode(newIdentifier);
|
||||
|
||||
if (newMode != NULL)
|
||||
{
|
||||
newMode->read(packet);
|
||||
|
||||
udpServer.write(Command::SetMode);
|
||||
udpServer.write(newIdentifier);
|
||||
newMode->write(&udpServer);
|
||||
|
||||
_dln("Updating current mode");
|
||||
setCurrentMode(newMode, newIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
udpServer.write(Command::Error);
|
||||
udpServer.write(Command::SetMode);
|
||||
udpServer.write(newIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleGetRange(uint8_t* packet)
|
||||
{
|
||||
udpServer.write(Command::GetRange);
|
||||
stairs->getRange(&udpServer);
|
||||
}
|
||||
|
||||
|
||||
void handleSetRange(uint8_t* packet)
|
||||
{
|
||||
stairs->setRange(packet);
|
||||
|
||||
udpServer.write(Command::SetRange);
|
||||
stairs->getRange(&udpServer);
|
||||
|
||||
currentMode->init(stairs, currentTime);
|
||||
}
|
||||
|
||||
|
||||
uint32_t lastUpdateCheck = 0;
|
||||
|
||||
void handleUpdateFirmware(uint8_t* packet)
|
||||
{
|
||||
_dln("Handling UpdateFirmware");
|
||||
|
||||
HTTPUpdateResult result;
|
||||
|
||||
if (currentTime - lastUpdateCheck <= OTAUpdateThrottle)
|
||||
{
|
||||
udpServer.write(Command::Error);
|
||||
udpServer.write(Command::UpdateFirmware);
|
||||
udpServer.write((uint8_t)2);
|
||||
return;
|
||||
}
|
||||
|
||||
lastUpdateCheck = currentTime;
|
||||
|
||||
switch (OTAUpdateEnabled)
|
||||
{
|
||||
case 1:
|
||||
_dln("Checking for update (fixed)");
|
||||
result = ESPhttpUpdate.update(OTAUpdateFixedHost, OTAUpdateFixedPort, OTAUpdateFixedPath, FirmwareVersion);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
_dln("Checking for update (client defined)");
|
||||
|
||||
uint16_t port;
|
||||
memcpy(&port, packet, sizeof(port));
|
||||
packet += sizeof(port);
|
||||
|
||||
_d("Port: ");
|
||||
_dln(port);
|
||||
|
||||
char host[255];
|
||||
char path[255];
|
||||
|
||||
strcpy(host, (char*)packet);
|
||||
packet += strlen(host) + 1;
|
||||
|
||||
strcpy(path, (char*)packet);
|
||||
|
||||
_d("Host: ");
|
||||
_dln(host);
|
||||
_d("Path: ");
|
||||
_dln(path);
|
||||
|
||||
result = ESPhttpUpdate.update(host, port, path, FirmwareVersion);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
udpServer.write(Command::Error);
|
||||
udpServer.write(Command::UpdateFirmware);
|
||||
udpServer.write((uint8_t)0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
_dln("No updates");
|
||||
udpServer.write(Command::UpdateFirmware);
|
||||
udpServer.write((uint8_t)0);
|
||||
break;
|
||||
|
||||
case HTTP_UPDATE_OK:
|
||||
_dln("Update OK");
|
||||
udpServer.write(Command::UpdateFirmware);
|
||||
udpServer.write((uint8_t)1);
|
||||
break;
|
||||
|
||||
default:
|
||||
_d("Error while updating: ");
|
||||
_dln(ESPhttpUpdate.getLastError());
|
||||
_dln(ESPhttpUpdate.getLastErrorString().c_str());
|
||||
|
||||
udpServer.write(Command::Error);
|
||||
udpServer.write(Command::UpdateFirmware);
|
||||
udpServer.write((uint8_t)2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleRequest(uint8_t* packet)
|
||||
{
|
||||
_d("Handling request: ");
|
||||
_dln(*packet);
|
||||
|
||||
|
||||
// Every request will result in a reply, either containing the
|
||||
// requested data or a copy of the input parameters for verification.
|
||||
//
|
||||
// Apparantly this also makes the ESP8266 more stable, as reports
|
||||
// have been made that UDP communication can stall if no replies are sent.
|
||||
udpServer.beginPacket(udpServer.remoteIP(), udpServer.remotePort());
|
||||
udpServer.write(Command::Reply);
|
||||
|
||||
uint8_t command = *packet;
|
||||
packet++;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case Command::Ping: handlePing(packet); break;
|
||||
case Command::GetMode: handleGetMode(packet); break;
|
||||
case Command::SetMode: handleSetMode(packet); break;
|
||||
case Command::GetRange: handleGetRange(packet); break;
|
||||
case Command::SetRange: handleSetRange(packet); break;
|
||||
case Command::UpdateFirmware: handleUpdateFirmware(packet); break;
|
||||
|
||||
default:
|
||||
udpServer.write(Command::Error);
|
||||
udpServer.write(command);
|
||||
break;
|
||||
}
|
||||
|
||||
udpServer.endPacket();
|
||||
}
|
||||
|
||||
|
||||
IMode* createMode(uint8_t identifier)
|
||||
{
|
||||
if (identifier == currentModeIdentifier)
|
||||
return currentMode;
|
||||
|
||||
switch (identifier)
|
||||
{
|
||||
case Mode::Static: return new StaticMode();
|
||||
case Mode::Custom: return new CustomMode();
|
||||
case Mode::Alternate: return new AlternateMode();
|
||||
//case Mode::Slide: return new SlideMode();
|
||||
//case Mode::ADC: return new ADCInputMode();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void setCurrentMode(IMode* mode, uint8_t identifier)
|
||||
{
|
||||
currentModeIdentifier = identifier;
|
||||
currentMode = mode;
|
||||
currentMode->init(stairs, currentTime);
|
||||
}
|
||||
|
||||
|
||||
void handleCurrentMode()
|
||||
{
|
||||
currentMode->tick(stairs, currentTime);
|
||||
}
|
||||
*/
|
29
src/mode.h
29
src/mode.h
@ -1,29 +0,0 @@
|
||||
#ifndef __Mode
|
||||
#define __Mode
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Stream.h>
|
||||
|
||||
|
||||
class IStairs
|
||||
{
|
||||
public:
|
||||
static const uint16_t Off = 0;
|
||||
static const uint16_t On = 4095;
|
||||
|
||||
virtual uint8_t getCount() = 0;
|
||||
virtual void set(uint8_t step, uint16_t value) = 0;
|
||||
virtual void setAll(uint16_t value) = 0;
|
||||
};
|
||||
|
||||
class IMode
|
||||
{
|
||||
public:
|
||||
virtual void read(uint8_t* data) = 0;
|
||||
virtual void write(Stream* stream) = 0;
|
||||
|
||||
virtual void init(IStairs* stairs, uint32_t currentTime) = 0;
|
||||
virtual void tick(IStairs* stairs, uint32_t currentTime) = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,31 +0,0 @@
|
||||
#ifndef __Protocol
|
||||
#define __Protocol
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
static const uint8_t Error = 0x00;
|
||||
|
||||
static const uint8_t Ping = 0x01;
|
||||
static const uint8_t Reply = 0x02;
|
||||
static const uint8_t GetMode = 0x03;
|
||||
static const uint8_t SetMode = 0x04;
|
||||
static const uint8_t GetRange = 0x05;
|
||||
static const uint8_t SetRange = 0x06;
|
||||
static const uint8_t UpdateFirmware = 0xFF;
|
||||
};
|
||||
|
||||
|
||||
class Mode
|
||||
{
|
||||
public:
|
||||
static const uint8_t Static = 0x01;
|
||||
static const uint8_t Custom = 0x02;
|
||||
static const uint8_t Alternate = 0x03;
|
||||
static const uint8_t Slide = 0x04;
|
||||
//static const uint8_t ADC = 0x05;
|
||||
};
|
||||
|
||||
#endif
|
@ -8,21 +8,22 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <IPAddress.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "shared.h"
|
||||
#include "../assets/version.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
#include "../settings/connection.h"
|
||||
|
||||
|
||||
void handleVersion(AsyncWebServerRequest *request)
|
||||
void handleGetSteps(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: version");
|
||||
_dln("API :: get steps");
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(2));
|
||||
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(17));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["systemID"] = String(ESP.getChipId(), HEX);
|
||||
root["version"] = String(VersionFullSemVer) + " sha." + String(VersionSha);
|
||||
JsonArray& root = jsonBuffer.createArray();
|
||||
for (uint8_t step = 0; step < stepsSettings->count(); step++)
|
||||
root.add(stairs->get(step));
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
root.printTo(*response);
|
||||
@ -31,71 +32,38 @@ void handleVersion(AsyncWebServerRequest *request)
|
||||
}
|
||||
|
||||
|
||||
void handleConnectionStatus(AsyncWebServerRequest *request)
|
||||
void handlePostSteps(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
|
||||
{
|
||||
_dln("API :: connection status");
|
||||
_dln("API :: post steps");
|
||||
|
||||
WiFiMode_t mode = WiFi.getMode();
|
||||
|
||||
|
||||
DynamicJsonBuffer jsonBuffer((2 * JSON_OBJECT_SIZE(2)) + JSON_OBJECT_SIZE(3));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonObject& ap = root.createNestedObject("ap");
|
||||
ap["enabled"] = (mode == WIFI_AP || mode == WIFI_AP_STA);
|
||||
ap["ip"] = WiFi.softAPIP().toString();
|
||||
|
||||
JsonObject& station = root.createNestedObject("station");
|
||||
station["enabled"] = (mode == WIFI_STA || mode == WIFI_AP_STA);
|
||||
station["status"] = (uint8_t)WiFi.status();
|
||||
station["ip"] = WiFi.localIP().toString();
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
root.printTo(*response);
|
||||
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handleGetConnection(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: get connection");
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
connectionSettings->toJson(*response);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handlePostConnection(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
|
||||
{
|
||||
_dln("API :: post connection");
|
||||
|
||||
bool changed;
|
||||
if (connectionSettings->fromJson((char*)data, &changed))
|
||||
DynamicJsonBuffer jsonBuffer(2*JSON_ARRAY_SIZE(17) + JSON_OBJECT_SIZE(3) + 130);
|
||||
JsonObject& root = jsonBuffer.parseObject((char*)data);
|
||||
if (!root.success())
|
||||
{
|
||||
connectionSettings->write();
|
||||
request->send(400);
|
||||
return;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
connectionSettingsChanged = true;
|
||||
uint16_t transitionTime = root["transitionTime"];
|
||||
JsonArray& values = root["values"];
|
||||
|
||||
JsonArray& startTime = root["startTime"];
|
||||
size_t startTimeCount = startTime.size();
|
||||
|
||||
size_t valueCount = values.size();
|
||||
if (valueCount > stepsSettings->count())
|
||||
valueCount = stepsSettings->count();
|
||||
|
||||
|
||||
for (uint8_t step = 0; step < valueCount; step++)
|
||||
stairs->set(step, values[step], transitionTime, step < startTimeCount ? 1 : 0);
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
else
|
||||
request->send(400);
|
||||
}
|
||||
|
||||
|
||||
void devNullRequest(AsyncWebServerRequest *request) { }
|
||||
void devNullFileUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { }
|
||||
|
||||
|
||||
void registerAPIRoutes(AsyncWebServer* server)
|
||||
{
|
||||
server->on("/api/version", HTTP_GET, handleVersion);
|
||||
|
||||
server->on("/api/connection/status", HTTP_GET, handleConnectionStatus);
|
||||
|
||||
server->on("/api/connection", HTTP_GET, handleGetConnection);
|
||||
server->on("/api/connection", HTTP_POST, devNullRequest, devNullFileUpload, handlePostConnection);
|
||||
server->on("/api/steps", HTTP_GET, handleGetSteps);
|
||||
server->on("/api/steps", HTTP_POST, devNullRequest, devNullFileUpload, handlePostSteps);
|
||||
}
|
98
src/server/settings.cpp
Normal file
98
src/server/settings.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "settings.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <IPAddress.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "shared.h"
|
||||
#include "../assets/version.h"
|
||||
#include "../debug.h"
|
||||
#include "../global.h"
|
||||
#include "../settings/connection.h"
|
||||
|
||||
|
||||
void handleVersion(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: version");
|
||||
|
||||
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(2));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["systemID"] = String(ESP.getChipId(), HEX);
|
||||
root["version"] = String(VersionFullSemVer) + " sha." + String(VersionSha);
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
root.printTo(*response);
|
||||
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handleConnectionStatus(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: connection status");
|
||||
|
||||
WiFiMode_t mode = WiFi.getMode();
|
||||
|
||||
|
||||
DynamicJsonBuffer jsonBuffer((2 * JSON_OBJECT_SIZE(2)) + JSON_OBJECT_SIZE(3));
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonObject& ap = root.createNestedObject("ap");
|
||||
ap["enabled"] = (mode == WIFI_AP || mode == WIFI_AP_STA);
|
||||
ap["ip"] = WiFi.softAPIP().toString();
|
||||
|
||||
JsonObject& station = root.createNestedObject("station");
|
||||
station["enabled"] = (mode == WIFI_STA || mode == WIFI_AP_STA);
|
||||
station["status"] = (uint8_t)WiFi.status();
|
||||
station["ip"] = WiFi.localIP().toString();
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
root.printTo(*response);
|
||||
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handleGetConnection(AsyncWebServerRequest *request)
|
||||
{
|
||||
_dln("API :: get connection");
|
||||
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
connectionSettings->toJson(*response);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
void handlePostConnection(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
|
||||
{
|
||||
_dln("API :: post connection");
|
||||
|
||||
bool changed;
|
||||
if (connectionSettings->fromJson((char*)data, &changed))
|
||||
{
|
||||
connectionSettings->write();
|
||||
|
||||
if (changed)
|
||||
connectionSettingsChanged = true;
|
||||
|
||||
request->send(200);
|
||||
}
|
||||
else
|
||||
request->send(400);
|
||||
}
|
||||
|
||||
|
||||
void registerSettingsRoutes(AsyncWebServer* server)
|
||||
{
|
||||
server->on("/api/version", HTTP_GET, handleVersion);
|
||||
|
||||
server->on("/api/connection/status", HTTP_GET, handleConnectionStatus);
|
||||
|
||||
server->on("/api/connection", HTTP_GET, handleGetConnection);
|
||||
server->on("/api/connection", HTTP_POST, devNullRequest, devNullFileUpload, handlePostConnection);
|
||||
}
|
13
src/server/settings.h
Normal file
13
src/server/settings.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#ifndef __server_settings
|
||||
#define __server_settings
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
void registerSettingsRoutes(AsyncWebServer* server);
|
||||
|
||||
#endif
|
10
src/server/shared.cpp
Normal file
10
src/server/shared.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#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) {}
|
15
src/server/shared.h
Normal file
15
src/server/shared.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#ifndef __server_shared
|
||||
#define __server_shared
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
void devNullRequest(AsyncWebServerRequest *request);
|
||||
void devNullFileUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final);
|
||||
|
||||
#endif
|
65
src/settings/steps.cpp
Normal file
65
src/settings/steps.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#include "steps.h"
|
||||
#include <FS.h>
|
||||
#include "../debug.h"
|
||||
|
||||
|
||||
struct Header
|
||||
{
|
||||
uint8_t version;
|
||||
uint8_t stepCount;
|
||||
bool useCurve;
|
||||
};
|
||||
|
||||
|
||||
|
||||
StepsSettings::StepsSettings()
|
||||
{
|
||||
for (uint8_t i = 0; i < MaxStepCount; i++)
|
||||
mCurveShift[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
void StepsSettings::read()
|
||||
{
|
||||
_dln("StepsSettings :: Loading step settings");
|
||||
File f = SPIFFS.open(StepSettingsFile, "r");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
if (!f.available())
|
||||
return;
|
||||
|
||||
Header header;
|
||||
f.readBytes((char*)&header, sizeof(Header));
|
||||
|
||||
if (header.version != 1)
|
||||
return;
|
||||
|
||||
mUseCurve = (header.useCurve == 1);
|
||||
f.readBytes((char*)&mCurveShift, header.stepCount * sizeof(uint16_t));
|
||||
f.close();
|
||||
}
|
||||
|
||||
|
||||
void StepsSettings::write()
|
||||
{
|
||||
_dln("StepsSettings :: Saving step settings");
|
||||
File f = SPIFFS.open(StepSettingsFile, "w");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
Header header;
|
||||
header.version = 1;
|
||||
header.useCurve = mUseCurve;
|
||||
header.stepCount = mCount;
|
||||
|
||||
f.write((uint8_t*)&header, sizeof(Header));
|
||||
f.write((uint8_t*)&mCurveShift, header.stepCount * sizeof(uint16_t));
|
||||
f.close();
|
||||
}
|
38
src/settings/steps.h
Normal file
38
src/settings/steps.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Stairs
|
||||
* Copyright 2017 (c) Mark van Renswoude
|
||||
*
|
||||
* https://git.x2software.net/pub/Stairs
|
||||
*/
|
||||
#ifndef __settingssteps
|
||||
#define __settingssteps
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MaxStepCount 16
|
||||
|
||||
|
||||
class StepsSettings
|
||||
{
|
||||
private:
|
||||
uint8_t mCount = 16;
|
||||
bool mUseCurve = true;
|
||||
uint16_t mCurveShift[MaxStepCount];
|
||||
|
||||
public:
|
||||
StepsSettings();
|
||||
|
||||
void read();
|
||||
void write();
|
||||
|
||||
uint8_t count() { return mCount; }
|
||||
void count(uint8_t value) { mCount = value; }
|
||||
|
||||
bool useCurve() { return mUseCurve; }
|
||||
void useCurve(bool value) { mUseCurve = value; }
|
||||
|
||||
uint16_t curveShift(uint8_t step) { return step < MaxStepCount ? mCurveShift[step] : 0; }
|
||||
uint16_t curveShift(uint8_t step, uint16_t value) { if (step < MaxStepCount) mCurveShift[step] = value; }
|
||||
};
|
||||
|
||||
#endif
|
256
src/stairs.cpp
256
src/stairs.cpp
@ -2,153 +2,159 @@
|
||||
#include <Math.h>
|
||||
#include <FS.h>
|
||||
#include "debug.h"
|
||||
#include "global.h"
|
||||
|
||||
|
||||
|
||||
const static float factorBase = log10(2) / log10(PCA9685::On);
|
||||
|
||||
|
||||
struct Header
|
||||
const uint16_t PWMCurve[] =
|
||||
{
|
||||
uint8_t version;
|
||||
uint8_t rangeCount;
|
||||
bool useScaling;
|
||||
0, 10, 11, 12, 12, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26, 27, 29, 30, 32, 33, 35, 36, 38, 40, 42, 44,
|
||||
46, 48, 51, 53, 56, 58, 61, 64, 67, 70, 74, 77, 81, 85, 89, 93,
|
||||
97, 102, 107, 112, 117, 123, 129, 135, 141, 148, 155, 162, 169, 177, 186, 194,
|
||||
203, 213, 222, 233, 243, 254, 266, 278, 291, 304, 318, 332, 347, 362, 378, 395,
|
||||
412, 430, 449, 468, 488, 509, 531, 553, 576, 600, 625, 651, 677, 704, 733, 762,
|
||||
792, 823, 854, 887, 920, 955, 990, 1026, 1063, 1101, 1140, 1180, 1220, 1261, 1303, 1346,
|
||||
1389, 1433, 1478, 1523, 1569, 1615, 1662, 1709, 1757, 1805, 1853, 1901, 1950, 1999, 2048, 2096,
|
||||
2145, 2194, 2242, 2290, 2338, 2386, 2433, 2480, 2526, 2572, 2617, 2662, 2706, 2749, 2792, 2834,
|
||||
2875, 2915, 2955, 2994, 3032, 3069, 3105, 3140, 3175, 3208, 3241, 3272, 3303, 3333, 3362, 3391,
|
||||
3418, 3444, 3470, 3495, 3519, 3542, 3564, 3586, 3607, 3627, 3646, 3665, 3683, 3700, 3717, 3733,
|
||||
3748, 3763, 3777, 3791, 3804, 3817, 3829, 3841, 3852, 3862, 3873, 3882, 3892, 3901, 3909, 3918,
|
||||
3926, 3933, 3940, 3947, 3954, 3960, 3966, 3972, 3978, 3983, 3988, 3993, 3998, 4002, 4006, 4010,
|
||||
4014, 4018, 4021, 4025, 4028, 4031, 4034, 4037, 4039, 4042, 4044, 4047, 4049, 4051, 4053, 4055,
|
||||
4057, 4059, 4060, 4062, 4063, 4065, 4066, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076,
|
||||
4077, 4078, 4079, 4079, 4080, 4081, 4082, 4082, 4083, 4083, 4084, 4084, 4085, 4085, 4090, 4095
|
||||
};
|
||||
|
||||
const float LinearFactor = 4095.0f / 255.0f;
|
||||
|
||||
|
||||
void Stairs::init(PCA9685* pwmDriver)
|
||||
{
|
||||
this->useScaling = false;
|
||||
mPWMDriver = pwmDriver;
|
||||
|
||||
memset(&mStep[0], 0, sizeof(mStep));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
for (uint8_t i = 0; i < StepCount; i++)
|
||||
struct Step
|
||||
{
|
||||
uint16_t currentValue;
|
||||
uint16_t startValue;
|
||||
uint16_t targetValue;
|
||||
uint16_t startTime;
|
||||
uint16_t endTime;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void Stairs::tick()
|
||||
{
|
||||
if (!mTick) return;
|
||||
mTick = false;
|
||||
|
||||
uint32_t elapsedTime = mTransitionStart != 0 ? currentTime - mTransitionStart : 0;
|
||||
|
||||
for (uint8_t step = 0; step < stepsSettings->count(); step++)
|
||||
{
|
||||
this->ranges[i].start = IStairs::Off;
|
||||
this->ranges[i].end = IStairs::On;
|
||||
}
|
||||
*/
|
||||
|
||||
this->pwmDriver = pwmDriver;
|
||||
|
||||
_dln("Loading range configuration");
|
||||
SPIFFS.begin();
|
||||
this->readRange();
|
||||
}
|
||||
|
||||
|
||||
uint8_t Stairs::getCount()
|
||||
{
|
||||
return 0;//StepCount;
|
||||
}
|
||||
|
||||
|
||||
void Stairs::set(uint8_t step, uint16_t brightness)
|
||||
{
|
||||
pwmDriver->setPWM(step, this->getPWMValue(step, brightness));
|
||||
}
|
||||
|
||||
|
||||
void Stairs::setAll(uint16_t brightness)
|
||||
{
|
||||
//pwmDriver->setAll(this->getPWMValue(brightness));
|
||||
|
||||
/*
|
||||
for (uint8_t step = 0; step < StepCount; step++)
|
||||
pwmDriver->setPWM(step, this->getPWMValue(step, brightness));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
uint16_t Stairs::getPWMValue(uint8_t step, uint16_t brightness)
|
||||
{
|
||||
_d("Getting PWM value for step "); _d(step); _d(", brightness "); _dln(brightness);
|
||||
if (brightness == IStairs::Off || brightness == IStairs::On)
|
||||
if (mStep[step].currentValue != mStep[step].targetValue)
|
||||
{
|
||||
_dln("Full on/off, returning input");
|
||||
return brightness;
|
||||
// TODO more maths!
|
||||
|
||||
/*
|
||||
uint32_t diff = this->easeState == Up ? this->parameters.brightness - this->easeStartBrightness : this->easeStartBrightness - this->parameters.brightness;
|
||||
uint32_t delta = (diff * elapsedTime) / this->parameters.easeTime;
|
||||
|
||||
this->currentBrightness = this->easeState == Up ? this->easeStartBrightness + delta : this->easeStartBrightness - delta;
|
||||
|
||||
|
||||
if (elapsedTime >= this->parameters.easeTime)
|
||||
{
|
||||
this->currentBrightness = this->parameters.brightness;
|
||||
this->easeState = None;
|
||||
}
|
||||
|
||||
if (step < 0 || step >= getCount())
|
||||
{
|
||||
_dln("Step out of bounds, returning input");
|
||||
return brightness;
|
||||
|
||||
|
||||
|
||||
t /= d/2;
|
||||
if (t < 1) return c/2*t*t + b;
|
||||
t--;
|
||||
return -c/2 * (t*(t-2) - 1) + b;
|
||||
};
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
Range* range = &this->ranges[step];
|
||||
_d("Start: "); _dln(range->start);
|
||||
_d("End: "); _dln(range->end);
|
||||
// TODO
|
||||
// mPWMDriver->setPWM(step, this->getPWMValue(step, brightness));
|
||||
|
||||
if (this->useScaling)
|
||||
}
|
||||
|
||||
|
||||
uint8_t Stairs::get(uint8_t step, bool target)
|
||||
{
|
||||
if (step >= MaxStepCount) return 0;
|
||||
return target ? mStep[step].targetValue : mStep[step].currentValue;
|
||||
}
|
||||
|
||||
|
||||
void Stairs::set(uint8_t step, uint8_t brightness, uint16_t transitionTime, uint16_t startTime)
|
||||
{
|
||||
if (step >= MaxStepCount) return;
|
||||
if (mStep[step].currentValue == brightness)
|
||||
return;
|
||||
|
||||
// TODO continue transition if one is already going on
|
||||
|
||||
mTick = true;
|
||||
mStep[step].targetValue = brightness;
|
||||
|
||||
if (transitionTime > 0)
|
||||
{
|
||||
_dln("Using scaling");
|
||||
float factor = ((range->end - range->start) + 1) * factorBase;
|
||||
brightness = pow(2, (brightness / factor)) - 1 + range->start;
|
||||
mTransitionStart = currentTime;
|
||||
mStep[step].startValue = mStep[step].currentValue;
|
||||
mStep[step].startTime = startTime;
|
||||
mStep[step].endTime = transitionTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dln("Not using scaling");
|
||||
if (brightness < range->start) brightness = range->start;
|
||||
if (brightness > range->end) brightness = range->end;
|
||||
mTransitionStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Stairs::setAll(uint8_t brightness, uint16_t transitionTime, uint16_t startTime)
|
||||
{
|
||||
for (uint8_t step = 0; step < stepsSettings->count(); step++)
|
||||
set(step, brightness, transitionTime, startTime);
|
||||
}
|
||||
|
||||
|
||||
uint16_t Stairs::getPWMValue(uint8_t step, uint8_t brightness)
|
||||
{
|
||||
//_d("Stairs :: Getting PWM value for step "); _d(step); _d(", brightness "); _dln(brightness);
|
||||
if (brightness == 0 || brightness == 255)
|
||||
{
|
||||
//_dln("Stairs :: Full on/off, returning input");
|
||||
return brightness == 0 ? 0 : 4095;
|
||||
}
|
||||
|
||||
_d("Output: "); _dln(brightness);
|
||||
return brightness;
|
||||
}
|
||||
|
||||
|
||||
void Stairs::getRange(Stream* stream)
|
||||
{
|
||||
stream->write(this->useScaling ? 1 : 0);
|
||||
stream->write((uint8_t*)&this->ranges, sizeof(this->ranges));
|
||||
}
|
||||
|
||||
|
||||
void Stairs::setRange(uint8_t* data)
|
||||
{
|
||||
this->useScaling = *data;
|
||||
data++;
|
||||
|
||||
memcpy(this->ranges, data, sizeof(this->ranges));
|
||||
this->writeRange();
|
||||
}
|
||||
|
||||
|
||||
void Stairs::readRange()
|
||||
{
|
||||
File f = SPIFFS.open("/range", "r");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
if (!f.available())
|
||||
return;
|
||||
|
||||
Header header;
|
||||
f.readBytes((char*)&header, sizeof(Header));
|
||||
|
||||
if (header.version != 1)
|
||||
return;
|
||||
|
||||
this->useScaling = (header.useScaling == 1);
|
||||
f.readBytes((char*)&this->ranges, header.rangeCount * sizeof(Range));
|
||||
f.close();
|
||||
|
||||
_d("- useScaling: ");
|
||||
_dln(this->useScaling);
|
||||
}
|
||||
|
||||
|
||||
void Stairs::writeRange()
|
||||
{
|
||||
File f = SPIFFS.open("/range", "w");
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
Header header;
|
||||
header.version = 1;
|
||||
header.useScaling = this->useScaling;
|
||||
header.rangeCount = getCount();
|
||||
|
||||
f.write((uint8_t*)&header, sizeof(Header));
|
||||
f.write((uint8_t*)&this->ranges, sizeof(this->ranges));
|
||||
f.close();
|
||||
uint16_t pwmValue;
|
||||
if (stepsSettings->useCurve())
|
||||
{
|
||||
//_dln("Stairs :: Using curve");
|
||||
pwmValue = PWMCurve[brightness] + stepsSettings->curveShift(step);
|
||||
}
|
||||
else
|
||||
{
|
||||
//_dln("Stairs :: Not using curve");
|
||||
pwmValue = brightness * LinearFactor;
|
||||
}
|
||||
|
||||
//_d("Stairs :: Output: "); _dln(pwmValue);
|
||||
return pwmValue;
|
||||
}
|
36
src/stairs.h
36
src/stairs.h
@ -3,39 +3,37 @@
|
||||
|
||||
#include "components/PCA9685.h"
|
||||
#include "config.h"
|
||||
#include "mode.h"
|
||||
#include "settings/steps.h"
|
||||
|
||||
|
||||
struct Range
|
||||
struct Step
|
||||
{
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
uint16_t currentValue;
|
||||
uint16_t startValue;
|
||||
uint16_t targetValue;
|
||||
uint16_t startTime;
|
||||
uint16_t endTime;
|
||||
};
|
||||
|
||||
|
||||
class Stairs : public IStairs
|
||||
class Stairs
|
||||
{
|
||||
private:
|
||||
PCA9685* pwmDriver;
|
||||
PCA9685* mPWMDriver;
|
||||
Step mStep[MaxStepCount];
|
||||
|
||||
bool useScaling;
|
||||
Range ranges[16];
|
||||
uint32_t mTransitionStart;
|
||||
bool mTick = false;
|
||||
|
||||
protected:
|
||||
void readRange();
|
||||
void writeRange();
|
||||
|
||||
uint16_t getPWMValue(uint8_t step, uint16_t brightness);
|
||||
uint16_t getPWMValue(uint8_t step, uint8_t brightness);
|
||||
|
||||
public:
|
||||
void init(PCA9685* pwmDriver);
|
||||
void tick();
|
||||
|
||||
uint8_t getCount();
|
||||
void set(uint8_t step, uint16_t brightness);
|
||||
void setAll(uint16_t brightness);
|
||||
|
||||
void getRange(Stream* stream);
|
||||
void setRange(uint8_t* data);
|
||||
uint8_t get(uint8_t step, bool target = true);
|
||||
void set(uint8_t step, uint8_t brightness, uint16_t transitionTime = 0, uint16_t startTime = 0);
|
||||
void setAll(uint8_t brightness, uint16_t transitionTime = 0, uint16_t startTime = 0);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user