dockerized

This commit is contained in:
2019-01-03 19:22:49 +01:00
parent 9821d412ec
commit 3c52ec4691
9 changed files with 31 additions and 561 deletions

25
Dockerfile Normal file
View File

@ -0,0 +1,25 @@
FROM node:10-jessie
MAINTAINER Wolfgang Hottgenroth <wolfgang.hottgenroth@icloud.com>
ARG APP_DIR="/opt/app"
EXPOSE 4200
RUN mkdir -p $APP_DIR
WORKDIR $APP_DIR
COPY files files/
COPY docroot docroot/
COPY src src/
COPY homepage.conf package.json package-lock.json tsconfig.json ./
RUN \
npm install && \
node_modules/typescript/bin/tsc -p ./
CMD [ "node", "dist/main.js" ]

5
build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
docker build --tag wollud1969/homepage:latest --tag wollud1969/homepage:1.0 .

View File

@ -1,38 +0,0 @@
define(`TITLE', `Three Phase Inverter')
define(`DATE', `2016-10-14')
define(`CONTENT', `
Already when I was still in school, about 30 years ago, I was curious to make an inverter using some MOSFETs. I actually was able to build a simple one phase inverter with rectangular signal shape (I used a NE555). Using this thing I drove a transformer to light a blub. However, all of these inverters I built passed by in fire.
Now, I tried it again, not longer using MOSFETs but IGBTs with free-wheeling diode. Moreover, I used some microcontrollers and sine values to feed a PWM to get a sine-alike signal shape. And immediately with three phases to drive an asynchronous motor.
<a href="https://a385e5.files.wordpress.com/2016/10/img_0053.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0053.jpg?w=730" alt="img_0053" width="730" height="973" class="alignnone size-large wp-image-740" /></a>
The signal shaping is done with four MSP430 controllers, three as PWMs to drive the bridge and one to coordinate and control the three PWMs. The PWM controller is decoupled from the IGBT driver (IR2184) using optic couplers.
<a href="https://a385e5.files.wordpress.com/2016/10/img_0054-e1476437702547.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0054-e1476437702547.jpg?w=730" alt="img_0054" width="730" height="548" class="alignnone size-large wp-image-741" /></a>
The bridge is a three phase IGBT module is a 6MB120F-060 I got for a few euros at ebay.
<a href="https://a385e5.files.wordpress.com/2016/10/img_0055-e1476437685461.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0055-e1476437685461.jpg?w=730" alt="img_0055" width="730" height="548" class="alignnone size-large wp-image-742" /></a>
To avoid high voltages in my setup I got a 24V async motor, also from ebay.
<a href="https://a385e5.files.wordpress.com/2016/10/img_0056.jpg"><img src="https://a385e5.files.wordpress.com/2016/10/img_0056.jpg?w=730" alt="img_0056" width="730" height="548" class="alignnone size-large wp-image-743" /></a>
The PWMs generate the signal from a sine table generated using Excel. Those we got this signal:
<a href="https://a385e5.files.wordpress.com/2016/10/inverter0_2016-09-23-4.png"><img src="https://a385e5.files.wordpress.com/2016/10/inverter0_2016-09-23-4.png" alt="inverter0_2016-09-23-4" width="640" height="520" class="alignnone size-full wp-image-759" /></a>
The main task of the coordinator is the start the PWMs with a phase shift of 120° (digital line 1, 2 and 3):
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_1.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_1.png" alt="2016-10-13_1" width="640" height="520" class="alignnone size-full wp-image-757" /></a>
Currently the PWMs start with random polarity. The interesting signals are the digital lines 4, 5 and 6.
Sometimes the motor runs:
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works.png" alt="2016-10-13_works" width="640" height="520" class="alignnone size-full wp-image-753" /></a>
But sometimes not:
<a href="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works_not.png"><img src="https://a385e5.files.wordpress.com/2016/10/2016-10-13_works_not.png" alt="2016-10-13_works_not" width="640" height="520" class="alignnone size-full wp-image-754" /></a>
The firmware is available on bitbucket, for the PWM controllers <a href="https://bitbucket.org/wollud1969/inverter0.git" target="_blank">here</a> and for the coordinator <a href="https://bitbucket.org/wollud1969/inverter0ctrl.git" target="_blank">here</a>.
')

View File

@ -1,47 +0,0 @@
define(`TITLE', `Something really useful: 433MHz Power-Outlet Control')
define(`DATE', `2016-11-02')
define(`CONTENT', `
We've lots of more or less cheap 433MHz Switchable Power-Outlets in the house, mostly for decorative lights. You get them for under 15€ in the Building Center, three at once with a remote control. Usually, you can control four switches with one remote, period. (A promising exceptions are the device from Intertechno.)
Now I was looking for a way to
<ol>
<li>Control the switches from different manufacturers with one remote.</li>
<li>Control them from really remote - from the office or from holiday.</li>
<li>Control them programmatically.</li>
</ol>
There are a couple of Arduino libraries out there which are working with this cheap 433MHz senders and receivers from China:
&nbsp;
<img class=" size-full wp-image-775 aligncenter" src="https://a385e5.files.wordpress.com/2016/11/sender_receiver.png" alt="sender_receiver" width="406" height="386" />I tried several ones, not all a really working, but finally I stopped at <a href="https://github.com/sui77/rc-switch" target="_blank">https://github.com/sui77/rc-switch</a>, which works really good.
<!--more-->
First challenge now is to get the codes out of the remotes. For this purposes the rc-switch library provides an example sketch for the Arduino. I extended it a bit and got this:
<a href="https://a385e5.files.wordpress.com/2016/11/img_01012-e1478087121580.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_01012-e1478087121580.jpg?w=730" alt="img_0101" width="730" height="548" class="alignnone size-large wp-image-791" /></a>
&nbsp;
<a href="https://a385e5.files.wordpress.com/2016/11/img_0105.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0105.jpg?w=730" alt="img_0105" width="730" height="548" class="alignnone size-large wp-image-784" /></a>
&nbsp;
Software for this thing can be found here <a href="https://gitlab.com/wolutator/433Receiver.git" target="_blank">https://gitlab.com/wolutator/433Receiver.git</a>.
This is how it works:
<a href="https://a385e5.files.wordpress.com/2016/11/img_0111-e1478087101747.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0111-e1478087101747.jpg?w=730" alt="img_0111" width="730" height="548" class="alignnone size-large wp-image-799" /></a>
&nbsp;
The second challenge is to send the codes out into air and let the power switches receive them. This is done with this thing:
<a href="https://a385e5.files.wordpress.com/2016/11/img_0100-e1478087375824.jpg"><img src="https://a385e5.files.wordpress.com/2016/11/img_0100-e1478087375824.jpg?w=730" alt="img_0100" width="730" height="548" class="alignnone size-large wp-image-803" /></a>
It is a Arduino Ethernet Board with a PoE-adapter and the 433MHz sender directly attached to it. I glued it under a table in the living room.
This thing received messages via MQTT and send them out via 433MHz.
The software is here https://gitlab.com/wolutator/Mqtt433Gateway.git
BTW: do not expect beautiful software, this has been made on Halloween evening and night when waiting for the kids to come home.
')

View File

@ -1,26 +0,0 @@
define(`TITLE', `Three Phase Inverter, Second Service')
define(`DATE', `2016-12-19')
define(`CONTENT', `
I wrote in October about my first try to build a simple three phase inverter, see here <a href="https://a385e5.wordpress.com/2016/10/14/three-phase-inverter/" target="_blank">https://a385e5.wordpress.com/2016/10/14/three-phase-inverter/</a>. In the first try I used four MSP430 microcontroller, one for the PWM of each phase and one to coordinate the phase shift of the three phases.
In this experiment I put everything on one STM32 microcontroller. Here I used the DMA feature to feed data into the PWM counter and I calculated the sine values at start-up time on the microcontroller. Additionally I put in the driver for a CAN interface, however, it is not yet supported in the firmware.
<img class="alignnone size-full wp-image-815" src="https://a385e5.files.wordpress.com/2016/12/img_0140.jpg" alt="img_0140" width="3024" height="4032" />
From top to bottom you see the CAN driver, the STM32 board, opto coupler to separate logic and power part and then from right to left in the bottom half the low-side/high-side MOSFET drivers and the MOSFETs.
<img class="alignnone size-full wp-image-820" src="https://a385e5.files.wordpress.com/2016/12/img_0144.jpg" alt="img_0144" width="3024" height="4032" />
The power supply consists of a traditional transformer and (top right) the rectifier and condensers for the power part, together with the 12V regulator for the drivers and (top left) the regulators for 3.3V and 5V for the logic part.
<img class="alignnone size-full wp-image-825" src="https://a385e5.files.wordpress.com/2016/12/img_0146.jpg" alt="img_0146" width="4032" height="3024" />
The motor is the same as in the earlier experiment - I don't have too much of them. And everything is put onto one board:
&nbsp;
&nbsp;
<a href="https://a385e5.files.wordpress.com/2016/12/img_0143-e1482141676335.jpg"><img src="https://a385e5.files.wordpress.com/2016/12/img_0143-e1482141676335.jpg?w=730" alt="img_0143" width="730" height="548" class="alignnone size-large wp-image-830" /></a>
(Some space reserved for a HMI unit to be connected via CAN ...)
')

View File

@ -1,277 +0,0 @@
define(`TITLE', `Configuration-Webserver for ESP8266 Projects')
define(`DATE', `2018-01-26')
define(`CONTENT', `
In my previous ESP8266 based weekend projects I always hardcoded configuration data. For the ESP8266 these are at least the WiFi credentials SSID and WPA key. Moving it into a different WiFi network requires re-flashing it. There must be a better way I thought and found that's a single line of code to run the ESP8266 as an accesspoint, which opens its own WiFi network.
So, I first hardcoded a web page with a form to enter configuration data, a data structure to hold it and some code to store it into the EEPROM or load it there.
It appears that this was an error-prone process with a lot of redudancy in the code.
For that reason I wrote an approach with a small template-based generator script:<!--more-->
[code language="python" title="configGen.py"]
#!/usr/bin/python
from Cheetah.Template import Template
configItems = [
{&quot;label&quot;:&quot;_&quot;, &quot;key&quot;:&quot;magic&quot;, &quot;type&quot;:&quot;I&quot;, &quot;default&quot;: &quot;&quot;},
{&quot;label&quot;:&quot;Wifi SSID&quot;, &quot;key&quot;:&quot;wifiSsid&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:32, &quot;default&quot;:&quot;test&quot;},
{&quot;label&quot;:&quot;Wifi Key&quot;, &quot;key&quot;:&quot;wifiKey&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:64, &quot;default&quot;:&quot;geheim&quot;},
{&quot;label&quot;:&quot;MQTT Broker&quot;, &quot;key&quot;:&quot;mqttBroker&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:64, &quot;default&quot;:&quot;broker.hottis.de&quot;},
{&quot;label&quot;:&quot;MQTT Username&quot;, &quot;key&quot;:&quot;mqttUser&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:32, &quot;default&quot;:&quot;esp1&quot;},
{&quot;label&quot;:&quot;MQTT Password&quot;, &quot;key&quot;:&quot;mqttPass&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:32, &quot;default&quot;:&quot;geheim&quot;},
{&quot;label&quot;:&quot;MQTT ClientId&quot;, &quot;key&quot;:&quot;mqttClientId&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:32, &quot;default&quot;:&quot;changeThis&quot;},
{&quot;label&quot;:&quot;MQTT Topic&quot;, &quot;key&quot;:&quot;mqttTopic&quot;, &quot;type&quot;:&quot;C&quot;, &quot;length&quot;:64, &quot;default&quot;:&quot;IoT/espThermometer2/location/measurement&quot;},
{&quot;label&quot;:&quot;MQTT Port&quot;, &quot;key&quot;:&quot;mqttPort&quot;, &quot;type&quot;:&quot;I&quot;, &quot;default&quot;:8883},
{&quot;label&quot;:&quot;Measure Period&quot;, &quot;key&quot;:&quot;measurePeriod&quot;, &quot;type&quot;:&quot;I&quot;, &quot;default&quot;:300}
]
h_file = Template(file=&quot;configuration_h.tmpl&quot;, searchList=[{&quot;configItems&quot;:configItems}])
open('configuration.h','w').write(str(h_file))
c_file = Template(file=&quot;configuration_c.tmpl&quot;, searchList=[{&quot;configItems&quot;:configItems}])
open('configuration.cpp','w').write(str(c_file))
[/code]
The two templates are:
[code language="C" title="configuration_h.tmpl"]
typedef struct {
#for $configItem in $configItems
#if $configItem.type == 'C'
char ${configItem.key}[$configItem.length];
#else if $configItem.type == 'I'
uint32_t $configItem.key;
#end if
#end for
} tConfigBlock;
extern const uint32_t MAGIC;
extern tConfigBlock configBlock;
void configServeIndex();
void configServeGetConfiguration();
void showConfiguration();
[/code]
And:
[code language="C" title="configuration_c.tmpl"]
#raw
#include &lt;Arduino.h&gt;
#include &lt;ESP8266WiFi.h&gt;
#include &lt;ESP8266WebServer.h&gt;
#include &lt;EEPROM.h&gt;
#include &quot;defines.h&quot;
#include &quot;configuration.h&quot;
#end raw
tConfigBlock configBlock;
const uint32_t MAGIC = 0xC0DE0001;
extern ESP8266WebServer webServer;
bool configSaved = false;
void configServeIndex() {
bool configValid = (configBlock.magic == MAGIC);
if (! configValid) {
#for $configItem in $configItems
#if $configItem.label != &quot;_&quot;
#if $configItem.type == &quot;C&quot;
strcpy(configBlock.$configItem.key, &quot;$configItem.default&quot;);
#else if $configItem.type == &quot;I&quot;
configBlock.$configItem.key = $configItem.default;
#end if
#end if
#end for
}
String buffer =
&quot;&lt;!doctype html&quot;
&quot;&lt;html lang=\&quot;en\&quot;&gt;&quot;
&quot; &lt;head&gt;&quot;
&quot; &lt;title&gt;ESP8266 Thermometer Configuration Page&lt;/title&gt;&quot;
&quot; &lt;/head&gt;&quot;
&quot; &lt;body&gt;&quot;
&quot; &lt;h1&gt;ESP8266 Configuration Page&lt;/h1&gt;&quot;;
if (configSaved) {
configSaved = false;
buffer += &quot;&lt;h2&gt;Configuration saved&lt;/h2&gt;&quot;;
}
buffer +=
&quot; &lt;form action=\&quot;/config\&quot; method=\&quot;GET\&quot;&gt;&quot;
&quot; &lt;table&gt;&quot;
#for $configItem in $configItems
#if $configItem.label != &quot;_&quot;
&quot; &lt;tr&gt;&quot;
&quot; &lt;td&gt;&quot;
&quot; &lt;label for\&quot;$configItem.key\&quot;&gt;$configItem.label&lt;/label&gt;&quot;
&quot; &lt;/td&gt;&lt;td&gt;&quot;
&quot; &lt;input type=\&quot;text\&quot; name=\&quot;$configItem.key\&quot; id=\&quot;$configItem.key\&quot; &quot;;
#if $configItem.type == &quot;C&quot;
buffer += &quot; size=\&quot;$configItem.length\&quot; &quot;;
buffer += &quot; value=\&quot;&quot;;
buffer += configBlock.$configItem.key;
buffer += &quot;\&quot;&quot;;
#else if $configItem.type == &quot;I&quot;
buffer += &quot; value=\&quot;&quot;;
buffer += configBlock.$configItem.key;
buffer += &quot;\&quot;&quot;;
#end if
buffer +=
&quot; /&gt;&quot;
&quot; &lt;/td&gt;&quot;
&quot; &lt;/tr&gt;&quot;
#end if
#end for
&quot; &lt;tr&gt;&quot;
&quot; &lt;td colspan=\&quot;2\&quot;&gt;&quot;
&quot; &lt;button type=\&quot;submit\&quot;&gt;Save&lt;/button&gt;&quot;
&quot; &lt;/td&gt;&quot;
&quot; &lt;/tr&gt;&quot;
&quot; &lt;/table&gt;&quot;
&quot; &lt;/form&gt;&quot;
&quot; &lt;/body&gt;&quot;
&quot;&lt;/html&gt;&quot;;
webServer.send(200, &quot;text/html&quot;, buffer);
#ifdef DEBUG
Serial.println(&quot;indexHtml request served&quot;);
#endif
}
void configServeGetConfiguration() {
String arg;
#for $configItem in $configItems
#if $configItem.label != &quot;_&quot;
arg = webServer.arg(&quot;$configItem.key&quot;);
#if $configItem.type == &quot;C&quot;
strcpy(configBlock.$configItem.key, arg.c_str());
#else if $configItem.type == &quot;I&quot;
configBlock.$configItem.key = atoi(arg.c_str());
#end if
#end if
#end for
configBlock.magic = MAGIC;
showConfiguration();
EEPROM.begin(512);
EEPROM.put(EEPROM_ADDR, configBlock);
EEPROM.commit();
Serial.println(&quot;EEPROM saved&quot;);
configSaved = true;
webServer.sendHeader(&quot;Location&quot;, String(&quot;/&quot;), true);
webServer.send(302, &quot;text/plain&quot;, &quot;&quot;);
//webServer.send(200, &quot;text/html&quot;, &quot;configuration saved&quot;);
}
void showConfiguration() {
Serial.println(&quot;Configuration is&quot;);
#for $configItem in $configItems
Serial.print(&quot;$configItem.key = &quot;);
Serial.println(configBlock.$configItem.key);
#end for
Serial.println(&quot;---&quot;);
}
[/code]
Besides these generated files I also needed a framework to distinguish between "configuration mode" and "production mode" and in configuration mode to start the WiFi accesspoint.
Since I'm programming the ESP8266 in an Eclipse-based Arduino-environment, this is all done in the <code>setup()</code> and <code>loop()</code> function:
[code language="C"]
void setup() {
startTime = millis();
#ifdef DEBUG
Serial.begin(115200);
Serial.println(&quot;Starting ...&quot;);
#endif
pinMode(CONFIG_SWITCH, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
EEPROM.begin(512);
EEPROM.get(EEPROM_ADDR, configBlock);
Serial.print(&quot;Magic: &quot;);
Serial.println(configBlock.magic);
configMode = ((LOW == digitalRead(CONFIG_SWITCH)) || (configBlock.magic != MAGIC));
if (configMode) {
#ifdef DEBUG
Serial.println(&quot;Configuration mode&quot;);
#endif
digitalWrite(LED_PIN, LOW);
setupConfiguration();
} else {
#ifdef DEBUG
Serial.println(&quot;Production mode&quot;);
Serial.println();
Serial.println();
showConfiguration();
#endif
digitalWrite(LED_PIN, HIGH);
setupProduction();
}
#ifdef DEBUG
Serial.println(&quot;Started.&quot;);
#endif
}
void loop() {
if (configMode) {
loopConfiguration();
} else {
loopProduction();
}
}
void setupConfiguration() {
WiFi.mode(WIFI_AP);
WiFi.softAP(CONFIG_SSID);
#ifdef DEBUG
Serial.println(&quot;AP started&quot;);
#endif
webServer.on(&quot;/&quot;, configServeIndex);
webServer.on(&quot;/config&quot;, configServeGetConfiguration);
webServer.onNotFound(configServeNotFound);
webServer.begin();
#ifdef DEBUG
Serial.println(&quot;Webserver started&quot;);
#endif
}
void loopConfiguration() {
webServer.handleClient();
}
[/code]
This code can be also found embedded into two of my projects. Find them at <a href="https://gitlab.com/wolutator/EspThermometer2" rel="noopener" target="_blank">https://gitlab.com/wolutator/EspThermometer2</a> and <a href="https://gitlab.com/wolutator/TouchSwitch" rel="noopener" target="_blank">https://gitlab.com/wolutator/TouchSwitch</a>.
')

View File

@ -1,29 +0,0 @@
define(`TITLE', `Home Automation Hub')
define(`DATE', `2018-02-22')
define(`CONTENT', `
My home automation hub. (Photos inside)
<img class="alignnone size-full wp-image-872" src="https://a385e5.files.wordpress.com/2018/02/img_0304.jpg" alt="IMG_0304" width="4032" height="3024" />
<img class=" size-medium wp-image-873 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0195.jpg?w=225" alt="IMG_0195" width="225" height="300" />
A Raspberry Pi runs <a href="https://homegear.eu" target="_blank" rel="noopener">Homegear</a> and <a href="https://github.com/hobbyquaker/homekit2mqtt" target="_blank" rel="noopener">homekit2mqtt</a>. It is equipped with two 866MHz radios for Homematic and MAX!.
Additionally an MQTT broker and the homegrown control software (<a href="https://gitlab.com/wolutator/dispatcher_ng" target="_blank" rel="noopener">https://gitlab.com/wolutator/dispatcher_ng</a>), which communicates with Homegear, homekit2mqtt, the MQTT433MHz bridge (see below) and other homegrown web clients via MQTT, resists on it.
<img class=" size-medium wp-image-876 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0307.jpg?w=225" alt="IMG_0307" width="225" height="300" />
There is also a DIY MQTT to 433MHz bridge to control Intertechno and other 433MHz plugs (<a href="https://gitlab.com/wolutator/Mqtt433Gateway" target="_blank" rel="noopener">https://gitlab.com/wolutator/Mqtt433Gateway</a>).
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<img class=" size-medium wp-image-881 alignleft" src="https://a385e5.files.wordpress.com/2018/02/img_0308.jpg?w=225" alt="IMG_0308" width="225" height="300" />
An finally a Philips Hue Bridge powered using a PoE adaptor for Philips and IKEA Tradfri bulbs, paired to Homegear.
')

View File

@ -1,143 +0,0 @@
define(`TITLE', `Yet Another Debouncing Method')
define(`DATE', `2018-04-30')
define(`CONTENT', `
You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
One common approach is to ignore events in an ISR when they come too fast:
[code language="C"]
void count() {
static uint32_t lastEvent = 0;
uint32_t currentEvent = micros();
if (currentEvent &gt; (lastEvent + configBlock.debounce)) {
lastEvent = currentEvent;
cnt++;
}
}
void setup() {
pinMode(REED_PIN, INPUT_PULLUP);
attachInterrupt(REED_PIN, count, FALLING);
}
[/code]
This works very good when only the tipping of a switch is relevant.
When also the time the button was pressed is relevant and when it is especially necessary to distinguish between a short and a long press this approach doesn't work anymore.
Since I couldn't remember the approaches I read about earlier I've sketched this state machine:
<!--more-->
<img src="https://a385e5.files.wordpress.com/2018/04/20180430110848869_0001.jpg" alt="20180430110848869_0001.jpg" width="2332" height="3307" class="alignnone size-full wp-image-901" />
(The double-lined states are action-states which send out the related information.)
At least for me, this approach is working very reliable so far, I'm quite happy with it.
[code language="C"]
enum tPressedState { psHIGH, psLOW, psACCEPTED_LOW, psLONG_START, psLONG_CONT, psLONG_CONT_SEND, psLONG_END, psSHORT, psINVALID };
typedef struct {
uint8_t index;
uint8_t buttonPin;
tPressedState pressedState;
tPressedState oldPressedState;
uint32_t lastStateChange;
} tButton;
tButton buttons[] = {
{ 1, SWITCH_1, psHIGH, psINVALID, 0 },
{ 2, SWITCH_2, psHIGH, psINVALID, 0 },
{ 3, SWITCH_3, psHIGH, psINVALID, 0 },
{ 0, 0, psINVALID, psINVALID, 0 } // END MARKER
};
static void buttonHandler(tButton *button) {
uint32_t currentMicros = micros();
uint8_t buttonState = digitalRead(button-&gt;buttonPin);
#ifdef DEBUG
if (button-&gt;oldPressedState != button-&gt;pressedState) {
Serial.print("Index ");
Serial.print(button-&gt;index);
Serial.print(", state changed from ");
Serial.print(button-&gt;oldPressedState);
Serial.print(" to ");
Serial.print(button-&gt;pressedState);
Serial.println();
button-&gt;oldPressedState = button-&gt;pressedState;
}
#endif
switch (button-&gt;pressedState) {
case psHIGH:
if (buttonState == LOW) {
button-&gt;pressedState = psLOW;
button-&gt;lastStateChange = currentMicros;
}
break;
case psLOW:
if (buttonState == HIGH) {
button-&gt;pressedState = psHIGH;
button-&gt;lastStateChange = currentMicros;
} else {
if (currentMicros &gt; (button-&gt;lastStateChange + configBlock.debounce)) {
button-&gt;pressedState = psACCEPTED_LOW;
button-&gt;lastStateChange = currentMicros;
}
}
break;
case psACCEPTED_LOW:
if (buttonState == HIGH) {
button-&gt;pressedState = psSHORT;
button-&gt;lastStateChange = currentMicros;
}
if (currentMicros &gt; (button-&gt;lastStateChange + (configBlock.longPress * 1000))) {
button-&gt;pressedState = psLONG_START;
button-&gt;lastStateChange = currentMicros;
}
break;
case psSHORT:
sendMsg(button-&gt;index, "PRESS_SHORT");
button-&gt;pressedState = psHIGH;
button-&gt;lastStateChange = currentMicros;
break;
case psLONG_START:
sendMsg(button-&gt;index, "PRESS_LONG_START");
button-&gt;pressedState = psLONG_CONT;
button-&gt;lastStateChange = currentMicros;
break;
case psLONG_CONT:
if (buttonState == HIGH) {
button-&gt;pressedState = psLONG_END;
button-&gt;lastStateChange = currentMicros;
}
if (currentMicros &gt; (button-&gt;lastStateChange + (configBlock.longPressRepeat * 1000))) {
button-&gt;pressedState = psLONG_CONT_SEND;
button-&gt;lastStateChange = currentMicros;
}
break;
case psLONG_CONT_SEND:
sendMsg(button-&gt;index, "PRESS_LONG_CONT");
button-&gt;pressedState = psLONG_CONT;
button-&gt;lastStateChange = currentMicros;
break;
case psLONG_END:
sendMsg(button-&gt;index, "PRESS_LONG_END");
button-&gt;pressedState = psHIGH;
button-&gt;lastStateChange = currentMicros;
break;
default:
button-&gt;pressedState = psHIGH;
button-&gt;lastStateChange = currentMicros;
}
}
[/code]
Find it embedded in the code of a small ESP8266-based switch thing I'm using in my home automation setup (home grown control code (https://gitlab.com/wolutator/dispatcher_ng), homegear (https://homegear.eu/) for device integration and openHAB (https://www.openhab.org/) as user interface) here: https://gitlab.com/wolutator/MySwitch.
')

View File

@ -5,7 +5,7 @@ import * as cmdargs from 'command-line-args'
const OPTION_DEFINITIONS = [
{ name: 'verbose', alias: 'v', type: Boolean },
{ name: 'config', alias: 'c', type: String, defaultValue: '~/homepage.conf' }
{ name: 'config', alias: 'c', type: String, defaultValue: './homepage.conf' }
];