Skip to content

Commit 795ffc1

Browse files
committed
wip - untested simple firmware version
1 parent 9997098 commit 795ffc1

File tree

4 files changed

+191
-1
lines changed

4 files changed

+191
-1
lines changed

src/FunctionBlocks.share.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
</ParameterType>
164164

165165
<ParameterType Id="%AID%_PT-FCBCountDownStartValue" Name="FCBCountDownStartValue">
166-
<TypeNumber SizeInBit="8" Type="unsignedInt" minInclusive="0" maxInclusive="255" />
166+
<TypeNumber SizeInBit="8" Type="unsignedInt" minInclusive="1" maxInclusive="255" />
167167
</ParameterType>
168168

169169
</ParameterTypes>

src/FunctionBlocks/CountDownBlock.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#include "CountDownBlock.h"
2+
#define FCB_CHStoppStart FCB_KoCHKO0
3+
#define FCB_CHPauseContinue FCB_KoCHKO1
4+
#define FCB_CHStartWithTime FCB_KoCHKO2
5+
6+
#define KoFCB_CHText KoFCB_CHKO6
7+
#define KoFCB_CHPauseActive KoFCB_CHKO7
8+
#define KoFCB_CHRemaining KoFCB_CHKO8
9+
#define KoFCB_CHRunning KoFCB_CHKO9
10+
11+
CountDownBlock::CountDownBlock(uint8_t channelIndex)
12+
: FunctionBlock(channelIndex, "CountDown")
13+
{
14+
// <Enumeration Id="%ENID%" Value="0" Text="Sekunden" />
15+
// <Enumeration Id="%ENID%" Value="1" Text="Minuten" />
16+
// <Enumeration Id="%ENID%" Value="2" Text="Stunden" />
17+
switch (ParamFCB_CHCountDownUnit)
18+
{
19+
case 0:
20+
_countValue = 1000;
21+
break;
22+
case 1:
23+
_countValue = 60 * 1000;
24+
break;
25+
case 2:
26+
_countValue = 60 * 60 * 1000;
27+
break;
28+
}
29+
KoFCB_CHRemaining.value(0ul, DPT_Value_1_Ucount);
30+
KoFCB_CHPauseActive.value(false, DPT_Switch);
31+
KoFCB_CHRunning.value(false, DPT_Switch);
32+
updateText(0);
33+
}
34+
35+
void CountDownBlock::handleKo(GroupObject &ko)
36+
{
37+
switch (ko.asap())
38+
{
39+
case FCB_CHStoppStart:
40+
if (ko.value(DPT_Switch))
41+
start(ParamFCB_CHFCBCountDownStartValue);
42+
else
43+
stop();
44+
break;
45+
case FCB_CHPauseContinue:
46+
pause(ko.value(DPT_Switch));
47+
break;
48+
case FCB_CHStartWithTime:
49+
start(ko.value(DPT_Value_1_Ucount));
50+
break;
51+
}
52+
}
53+
54+
void CountDownBlock::readInputKos()
55+
{
56+
}
57+
58+
void CountDownBlock::initMissingInputValues()
59+
{
60+
}
61+
62+
void CountDownBlock::start(uint64_t startValue)
63+
{
64+
if (startValue == 0)
65+
{
66+
stop();
67+
}
68+
else
69+
{
70+
_lastValueUpdate = max(1ul, millis());
71+
KoFCB_CHRemaining.value(startValue, DPT_Value_1_Ucount);
72+
KoFCB_CHRunning.value(true, DPT_Switch);
73+
updateText(startValue);
74+
}
75+
}
76+
77+
void CountDownBlock::pause(bool pause)
78+
{
79+
if (pause != _pause)
80+
{
81+
_pause = pause;
82+
KoFCB_CHPauseActive.value(pause, DPT_Switch);
83+
if (_lastValueUpdate > 0)
84+
{
85+
if (pause)
86+
{
87+
_lastValueUpdate = millis() - _lastValueUpdate; // Store already elapsed time
88+
}
89+
else
90+
{
91+
_lastValueUpdate = max(1ul, millis() + _lastValueUpdate); // Start from now - already elapsed time
92+
}
93+
uint64_t value = KoFCB_CHRemaining.value(DPT_Value_1_Ucount);
94+
updateText(value);
95+
}
96+
}
97+
}
98+
99+
void CountDownBlock::stop()
100+
{
101+
_lastValueUpdate = 0;
102+
KoFCB_CHRunning.value(false, DPT_Switch);
103+
KoFCB_CHText.value("Gestoppt", DPT_String_8859_1);
104+
}
105+
106+
void CountDownBlock::loop()
107+
{
108+
if (_lastValueUpdate > 0 && !_pause)
109+
{
110+
unsigned long now = millis();
111+
if (now - _lastValueUpdate >= _countValue)
112+
{
113+
auto toLateOffest = now - _lastValueUpdate;
114+
uint64_t value = KoFCB_CHRemaining.value(DPT_Value_1_Ucount);
115+
if (value > 0)
116+
value--;
117+
else
118+
value = 0;
119+
120+
if (value == 0)
121+
_lastValueUpdate = 0;
122+
else
123+
_lastValueUpdate = max(1ul, now - toLateOffest);
124+
125+
KoFCB_CHRemaining.value(value, DPT_Value_1_Ucount);
126+
if (_lastValueUpdate == 0)
127+
{
128+
KoFCB_CHRunning.value(false, DPT_Switch);
129+
KoFCB_CHText.value("Ende", DPT_String_8859_1);
130+
}
131+
else
132+
{
133+
updateText(value);
134+
}
135+
}
136+
}
137+
}
138+
139+
void CountDownBlock::updateText(uint64_t value)
140+
{
141+
if (_lastValueUpdate == 0)
142+
{
143+
KoFCB_CHText.value("Gestoppt", DPT_String_8859_1);
144+
return;
145+
}
146+
char buffer[15] = {0};
147+
const char *unit = "";
148+
switch (ParamFCB_CHCountDownUnit)
149+
{
150+
case 0:
151+
unit = "s";
152+
break;
153+
case 1:
154+
unit = "m";
155+
break;
156+
case 2:
157+
unit = "h";
158+
break;
159+
}
160+
const char* pauseText = "";
161+
if (_pause)
162+
pauseText = " Pause";
163+
snprintf(buffer, sizeof(buffer), "%lu %s%s", value, unit, pauseText);
164+
KoFCB_CHText.value(buffer, DPT_String_8859_1);
165+
}

src/FunctionBlocks/CountDownBlock.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include "FunctionBlock.h"
3+
4+
class CountDownBlock : public FunctionBlock
5+
{
6+
private:
7+
unsigned long _countValue = 1000;
8+
unsigned long _lastValueUpdate = 0;
9+
bool _pause = false;
10+
public:
11+
CountDownBlock(uint8_t channelIndex);
12+
void readInputKos() override;
13+
void initMissingInputValues() override;
14+
void handleKo(GroupObject &ko) override;
15+
void start(uint64_t startValue);
16+
void pause(bool pause);
17+
void stop();
18+
void loop() override;
19+
void updateText(uint64_t value);
20+
21+
};

src/FunctionBlocksModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "FunctionBlocks/LogicFunctionBlock.h"
44
#include "FunctionBlocks/PrioritySwitchFunctionBlock.h"
55
#include "FunctionBlocks/SimpleAggregationBlock.h"
6+
#include "FunctionBlocks/CountDownBlock.h"
67

78
FunctionBlocksModule::FunctionBlocksModule()
89
{
@@ -56,6 +57,7 @@ OpenKNX::Channel* FunctionBlocksModule::createChannel(uint8_t _channelIndex)
5657
// <Enumeration Id="%ENID%" Value="3" Text="Prioritätsschalter" />
5758
// <Enumeration Id="%ENID%" Value="4" Text="Anzahl" />
5859
// <Enumeration Id="%ENID%" Value="5" Text="Statistische Aggregation" />
60+
// <Enumeration Id="%ENID%" Value="6" Text="Count Down Zeitgeber" />
5961
switch (ParamFCB_CHChannelType)
6062
{
6163
case 0:
@@ -71,6 +73,8 @@ OpenKNX::Channel* FunctionBlocksModule::createChannel(uint8_t _channelIndex)
7173
return new PrioritySwitchFunctionBlock(_channelIndex);
7274
case 5:
7375
return new SimpleAggregationBlock(_channelIndex, static_cast<SimpleAggregationBlockType>(ParamFCB_CHAggType));
76+
case 6:
77+
return new CountDownBlock(_channelIndex);
7478
default:
7579
logErrorP("Unknown channel type %d", ParamFCB_CHChannelType);
7680
return nullptr;

0 commit comments

Comments
 (0)