This commit is contained in:
Tester23
2025-12-21 00:15:00 +01:00
parent 00cb7f0e21
commit 1f01d59939
7 changed files with 107 additions and 44 deletions

View File

@@ -249,6 +249,7 @@
<ClCompile Include="src\driver\drv_deviceclock.c" />
<ClCompile Include="src\driver\drv_ds3231.c" />
<ClCompile Include="src\driver\drv_rc.cpp" />
<ClCompile Include="src\driver\drv_shutters.c" />
<ClCompile Include="src\libraries\obktime\obktime.c" />
<ClCompile Include="src\driver\drv_timed_events.c" />
<ClCompile Include="src\driver\drv_openWeatherMap.c" />

View File

@@ -426,6 +426,7 @@
<ClCompile Include="src\driver\drv_ds3231.c" />
<ClCompile Include="src\libraries\obktime\obktime.c" />
<ClCompile Include="src\driver\drv_rc.cpp" />
<ClCompile Include="src\driver\drv_shutters.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\base64\base64.h" />

View File

@@ -15,6 +15,10 @@ void DRV_DDP_RunFrame();
void DRV_DDP_Shutdown();
void DRV_DDP_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState);
void DRV_Shutters_RunQuickTick();
void DRV_Shutters_AddToHtmlPage(http_request_t *request, int bPreState);
void DRV_Shutters_Init();
void BMP280_Init();
void BMP280_OnEverySecond();
void BMP280_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState);

View File

@@ -806,6 +806,22 @@ static driver_t g_drivers[] = {
false, // loaded
},
#endif
#if ENABLE_DRIVER_SHUTTERS
//drvdetail:{"name":"Shutters",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"ShutterShutters",
//drvdetail:"requires":""}
{ "Shutters", // Driver Name
DRV_Shutters_Init, // Init
NULL, // onEverySecond
DRV_Shutters_AddToHtmlPage, // appendInformationToHTTPIndexPage
DRV_Shutters_RunQuickTick, // runQuickTick
NULL, // stopFunction
NULL, // onChannelChanged
NULL, // onHassDiscovery
false, // loaded
},
#endif
#if ENABLE_DRIVER_DDP
//drvdetail:{"name":"DDP",
//drvdetail:"title":"TODO",

View File

@@ -11,81 +11,107 @@
#include "drv_ntp.h"
#include "drv_deviceclock.h"
typedef enum shutterState_e {
typedef enum shutterState_t {
SHUTTER_OPEN,
SHUTTER_CLOSED,
SHUTTER_OPENING,
SHUTTER_CLOSING,
SHUTTER_UNKNOWN,
} shutterState_t;
typedef struct shutter_s {
int index;
int channel;
// current fraction
shutterState_t state;
float frac;
float targetFrac;
float openTimeSeconds;
float closeTimeSeconds;
struct shutter_s *next;
} shutter_t;
shutter_t *g_shutters = 0;
shutter_t *GetForIndex(int i) {
shutter_t *GetForChannel(int i) {
shutter_t *s = g_shutters;
while (s && i--) s = s->next;
while (s) {
if (i == s->channel) {
return s;
}
s = s->next;
}
return s;
}
// startDriver Shutters
void DRV_Shutters_AddToHtmlPage(http_request_t *request, int bPreState) {
if (bPreState)
if (bPreState) {
hprintf255(request, "<script>"
"function sendCmd(cmd) {"
" fetch('/cm?cmnd=' + encodeURIComponent(cmd));"
"}"
"</script>");
return;
}
shutter_t *s = g_shutters;
while (s) {
int percent = (s->frac < 0.0f) ? -1 : (int)(s->frac * 100.0f + 0.5f);
int currentPercent = (s->frac < 0.0f) ? -1 : (int)(s->frac * 100.0f + 0.5f);
int targetPercent = (int)(s->targetFrac * 100.0f + 0.5f);
hprintf255(request, "<hr>");
hprintf255(request, "<h5>Shutter %i</h5>", s->index);
hprintf255(request, "<h5>Shutter %i</h5>", s->channel);
if (percent >= 0)
hprintf255(request, "<div>Position: %i%%</div>", percent);
if (currentPercent >= 0)
hprintf255(request, "<div>Current Position: %i%%</div>", currentPercent);
else
hprintf255(request, "<div>Position: unknown</div>");
hprintf255(request, "<div>Current Position: unknown</div>");
hprintf255(request, "<div>Target Position: %i%%</div>", targetPercent);
hprintf255(request,
"<div>"
"<a class='btn' href='?cmd=ShutterMoveTo+%i+1'>Open</a> "
"<a class='btn' href='?cmd=ShutterMoveTo+%i+%.2f'>Stop</a> "
"<a class='btn' href='?cmd=ShutterMoveTo+%i+0'>Close</a>"
"<button class='btn' onclick='sendCmd(\"ShutterMoveTo %i 1\")'>Open</button> "
"<button class='btn' onclick='sendCmd(\"ShutterMoveTo %i %.2f\")'>Stop</button> "
"<button class='btn' onclick='sendCmd(\"ShutterMoveTo %i 0\")'>Close</button>"
"</div>",
s->index,
s->index, (s->frac >= 0.0f) ? s->frac : 0.0f,
s->index
s->channel,
s->channel, (s->frac >= 0.0f) ? s->frac : 0.0f,
s->channel
);
// Target slider (read/write)
hprintf255(request,
"<form method='get'>"
"<input type='hidden' name='cmd' value='ShutterMoveTo %i'>"
"<form onsubmit='return false;'>"
"<label>Set Target:</label>"
"<input type='range' min='0' max='100' value='%i' "
"onchange='this.form.cmd.value=\"ShutterMoveTo %i \" + (this.value/100); this.form.submit();'>"
"onchange='sendCmd(\"ShutterMoveTo %i \" + (this.value/100))'>"
"</form>",
s->index,
(percent >= 0) ? percent : 0,
s->index
targetPercent,
s->channel
);
// Current slider (read-only)
hprintf255(request,
"<form onsubmit='return false;'>"
"<label>Current Position:</label>"
"<input type='range' min='0' max='100' value='%i' disabled>"
"</form>",
(currentPercent >= 0) ? currentPercent : 0
);
s = s->next;
}
}
static void Shutter_SetPin(shutter_t *s, int role, int val) {
for (int i = 0; i < PLATFORM_GPIO_MAX; i++) {
if (g_cfg.pins.channels[i] == s->index
if (g_cfg.pins.channels[i] == s->channel
&& g_cfg.pins.roles[i] == role) {
HAL_PIN_SetOutputValue(i, val);
}
}
}
static void Shutter_SetPins(shutter_t *s, shutterState_e dir) {
static void Shutter_SetPins(shutter_t *s, shutterState_t dir) {
// turn all off
Shutter_SetPin(s, IOR_ShutterA, 0);
Shutter_SetPin(s, IOR_ShutterB, 0);
@@ -101,18 +127,9 @@ static void Shutter_SetPins(shutter_t *s, shutterState_e dir) {
break;
}
}
static void Shutter_Open(shutter_t *s) {
Shutter_SetPins(s, SHUTTER_OPENING);
s->state = SHUTTER_OPENING;
}
static void Shutter_Close(shutter_t *s) {
Shutter_SetPins(s, SHUTTER_CLOSING);
s->state = SHUTTER_CLOSING;
}
static void Shutter_Stop(shutter_t *s) {
Shutter_SetPins(s, SHUTTER_CLOSED);
if (s->frac <= 0.0f) {
s->frac = 0.0f;
s->state = SHUTTER_CLOSED;
@@ -124,6 +141,7 @@ static void Shutter_Stop(shutter_t *s) {
else {
s->state = SHUTTER_UNKNOWN;
}
Shutter_SetPins(s, s->state);
}
static commandResult_t CMD_Shutter_MoveTo(const void *context, const char *cmd, const char *args, int flags) {
Tokenizer_TokenizeString(args, 0);
@@ -134,7 +152,7 @@ static commandResult_t CMD_Shutter_MoveTo(const void *context, const char *cmd,
if (frac < 0.0f) frac = 0.0f;
if (frac > 1.0f) frac = 1.0f;
shutter_t *s = GetForIndex(index);
shutter_t *s = GetForChannel(index);
if (!s)
return CMD_RES_BAD_ARGUMENT;
@@ -143,10 +161,13 @@ static commandResult_t CMD_Shutter_MoveTo(const void *context, const char *cmd,
if (s->frac < 0.0f)
s->frac = 0.0f;
if (frac > s->frac)
Shutter_Open(s);
else if (frac < s->frac)
Shutter_Close(s);
if (frac > s->frac) {
s->state = SHUTTER_OPENING;
}
else if (frac < s->frac) {
s->state = SHUTTER_CLOSING;
}
Shutter_SetPins(s, s->state);
return CMD_RES_OK;
}
@@ -177,10 +198,29 @@ void DRV_Shutters_RunQuickTick() {
s = s->next;
}
}
static void RegisterShutterForChannel(int channel) {
shutter_t *s = GetForChannel(channel);
if (!s) {
s = malloc(sizeof(shutter_t));
memset(s, 0, sizeof(shutter_t));
s->channel = channel;
s->frac = 0.0f; // unknown position
s->state = SHUTTER_OPEN;
s->targetFrac = 0.0f;
s->openTimeSeconds = 10.0f; // default
s->closeTimeSeconds = 10.0f; // default
s->next = g_shutters;
g_shutters = s;
}
}
// backlog setPinRole 5 ShutterA; startDriver Shutters
void DRV_Shutters_Init() {
for (int i = 0; i < PLATFORM_GPIO_MAX; i++) {
int r = g_cfg.pins.roles[i];
if (r == IOR_ShutterA || r == IOR_ShutterB) {
RegisterShutterForChannel(g_cfg.pins.channels[i]);
}
}
CMD_RegisterCommand("ShutterMoveTo", CMD_Shutter_MoveTo, NULL);
}

View File

@@ -560,8 +560,8 @@ const char* htmlPinRoleNames[] = {
"HLW_8112_SCSN",
"RCRecv",
"RCRecv_nPup",
"error",
"error",
"ShutterA",
"ShutterB",
"error",
};

View File

@@ -135,6 +135,7 @@
#define ENABLE_LITTLEFS 1
#define ENABLE_NTP 1
#define ENABLE_TIME_DST 1
#define ENABLE_DRIVER_SHUTTERS 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_BL0942 1