Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
125d89d632
|
|||
670fb8f97b
|
|||
3aed319835 | |||
fce5ff4743 | |||
7742892afe | |||
74543f3b5f
|
|||
3a22172081
|
|||
5c31d78885
|
|||
975ffa4bfb
|
|||
82de380596
|
|||
4e567c86ec
|
|||
5bf51b58bb
|
|||
bfffd3b235
|
|||
a44eab1591
|
|||
48cb3e6972
|
|||
9a46c44d94
|
|||
24467c80ec
|
|||
98fc271eb7
|
|||
912c8e4d04
|
|||
3e6d42fed4
|
|||
ca9d6c19d4
|
|||
5f9136b74b
|
|||
bf5664b2af
|
|||
7e1127efcf
|
|||
b20acc86c2
|
|||
f20bfe2b30
|
|||
1911c34faa
|
|||
cf9c04e211
|
|||
953f92711c
|
|||
c03e25d647
|
|||
0b7b8392ed
|
|||
298e02349a
|
|||
1f68c5a8ea
|
|||
fccaeed07e
|
|||
77cff49e41
|
|||
3c52ec4691
|
|||
d43b935d13
|
|||
525b6313c2
|
|||
46057cac31
|
|||
29208faaec
|
|||
9a817b27c1
|
|||
ee2eca37dc
|
0
src/.gitignore → .gitignore
vendored
41
.gitlab-ci.yml
Normal file
@ -0,0 +1,41 @@
|
||||
image: docker:stable
|
||||
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
IMAGE_NAME: registry.hottis.de/wolutator/homepage
|
||||
|
||||
build:
|
||||
stage: build
|
||||
tags:
|
||||
- hottis
|
||||
- linux
|
||||
- docker
|
||||
script:
|
||||
- VERSION=`cat VERSION`
|
||||
- echo "Version is $VERSION"
|
||||
- docker build --tag ${IMAGE_NAME}:latest --tag ${IMAGE_NAME}:$VERSION .
|
||||
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
|
||||
- docker push ${IMAGE_NAME}:latest
|
||||
- docker push ${IMAGE_NAME}:$VERSION
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
tags:
|
||||
- hottis
|
||||
- linux
|
||||
- docker
|
||||
script:
|
||||
- VERSION=`cat VERSION`
|
||||
- echo "Version is $VERSION"
|
||||
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
|
||||
- docker stop homepage || echo "homepage not running, anyway okay"
|
||||
- docker rm homepage || echo "homepage not available, anyway okay"
|
||||
- docker pull ${IMAGE_NAME}:$VERSION
|
||||
- docker run -d --restart=always --name homepage --network ${PROD_NETWORK} --ip ${PROD_ADDRESS} ${IMAGE_NAME}:$VERSION
|
||||
environment:
|
||||
name: production
|
||||
url: https://home.hottis.de/wolutator/
|
||||
|
25
Dockerfile
Normal 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 ./
|
||||
COPY VERSION .
|
||||
|
||||
|
||||
RUN \
|
||||
npm install && \
|
||||
node_modules/typescript/bin/tsc -p ./
|
||||
|
||||
|
||||
CMD [ "node", "dist/main.js" ]
|
||||
|
2
dist/config.js
vendored
@ -4,7 +4,7 @@ const fs = require("fs");
|
||||
const cmdargs = require("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' }
|
||||
];
|
||||
function readConfig() {
|
||||
let options = cmdargs(OPTION_DEFINITIONS);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
<div class="footer">
|
||||
<a href="reload">Reload</a>
|
||||
<a rel="me" href="https://ruhr.social/@wolutator">Mastodon</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -7,9 +7,7 @@
|
||||
<h1>About</h1>
|
||||
|
||||
Wolfgang Hottgenroth<br/>
|
||||
Eupenstr. 20<br/>
|
||||
45259 Essen<br/>
|
||||
<address>woho@hottis.de</address><br/>
|
||||
<address>wolfgang.hottgenroth@icloud.com</address><br/>
|
||||
|
||||
|
||||
|
||||
@ -21,6 +19,7 @@ This is a hobby-only homepage without any advertising or other commercial intere
|
||||
<h1>My Profiles</h1>
|
||||
<ul>
|
||||
<li><a href="https://gitlab.com/wolutator">GitLab</a></li>
|
||||
<li><a href="https://home.hottis.de/gitlab/wolutator">GitLab</a></li>
|
||||
<li><a href="https://twitter.com/wollud1969">Twitter</a></li>
|
||||
<li><a href="https://keybase.io/wolutator/">Keybase</a></li>
|
||||
<li><a href="https://github.com/wollud1969">GitHub</a></li>
|
||||
@ -37,34 +36,14 @@ Although according to Art. 2 (2) c of DSGVO that regulation is completely irrele
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For this system I know exactly which data is collected here: There is the Apache httpd running on an old PowerPC MacMini with OpenBSD bastion host, which proxies requests to the homepage engine. For the Apache log the requesters IP has been stripped away:
|
||||
<p>
|
||||
<pre>
|
||||
<code language="Apache">
|
||||
CustomLog "logs/access_log" common
|
||||
#LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||
LogFormat "%l %u %t \"%r\" %>s %b" common
|
||||
</pre>
|
||||
</code>
|
||||
For this system I know exactly which data is collected here: There is the Apache httpd running on a Raspberry Pi with FreeBSD bastion host, which proxies
|
||||
requests to the homepage engine.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The logfile looks like this now:
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator HTTP/1.1" 302 76
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator/index HTTP/1.1" 304 -
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator/files/default.css HTTP/1.1" 304 -
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator/files/highlight/styles/default.css HTTP/1.1" 304 -
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator/files/highlight/highlight.pack.js HTTP/1.1" 304 -
|
||||
- - [25/May/2018:12:43:58 +0200] "GET /wolutator/files/cropped-img_2723.jpg HTTP/1.1" 304 -
|
||||
- - [25/May/2018:12:43:59 +0200] "GET /favicon.ico HTTP/1.1" 404 209
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The homepage engine is running on an old Intel MacMini with Debian. It just logs which post or page is accessed and served, nothing more. If you like to have a look: <a href="https://gitlab.com/wolutator/homepage" target="_blank">https://gitlab.com/wolutator/homepage</a>.
|
||||
The homepage engine is running in a Docker container on my small multi purpose server in the basement.
|
||||
It just logs which post or page is accessed and served, nothing more.
|
||||
If you like to have a look: <a href="https://home.hottis.de/gitlab/wolutator/homepage" target="_blank">https://home.hottis.de/gitlab/wolutator/homepage</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@ -97,3 +76,8 @@ wn@mac:/opt/services/homepage$ npm start -- -c homepage.conf
|
||||
<p>
|
||||
And since I'm quite bad in CSS, it currently looks so ugly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Furthermore, this homepage does not use any cookies.
|
||||
</p>
|
||||
|
||||
|
@ -3,122 +3,108 @@
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
<a href="files/75217C088B3EF6AE55F4D4C7B586EAFCDF2F65F4.key">for download</a><br/>
|
||||
<a href="files/9A0CD4EA597C9ABE371300816C1E5E531E0D5D7F.key">for download</a><br/>
|
||||
<pre>
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
UzZbs54AnA==
|
||||
=GSFz
|
||||
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
|
||||
JWjBNR9VP6VNX9nvxRC3f7u4gl6fSiZViYJ43a0nR24LbQKXudE88waxL+IV7563
|
||||
JJUicKI7X+PAiVwp3DsPA0/fxbcrkanNau9L75RCtHVIEK72QBIcCIBTMARktIQH
|
||||
bChNd/+1V+WxH1diUIeFRx9svQT3UX89R9qn6INy0qrUCzQ9ZtKrru+orngOlFLc
|
||||
93zKcICJYyoC82LSGZA4+ax8Cn6E/z2gjAw8aSEaOm/C9GUJ4cWpPTYp9LQlV29s
|
||||
ZmdhbmcgSG90dGdlbnJvdGggPHdvaG9AaG90dGlzLmRlPokCTgQTAQgAOBYhBJoM
|
||||
1OpZfJq+NxMAgWweXlMeDV1/BQJc+B2MAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4B
|
||||
AheAAAoJEGweXlMeDV1/b34P/A0ZLFKNZ7RXILqfAxW5aNURMNbRuc3Z1QJPmOQU
|
||||
1WRjQt71yYcD1SVNwjW5NKTbueMWqS+I/pVIdgCVDhBxHhwnAl8Xq131hZ7+84TR
|
||||
MGw/rsLx7dU3jmogpijqc8ghcMshuPXUDxEg6Qso0Bi4LrxdEvZaIDbXVaayhdrz
|
||||
bJe8JVs7cXngnrtfIwwUhpc+YkA1v4DShygXPVvKFQtDuEwzbtdMvlKJNi1iuK5v
|
||||
ssc6A3ANaQ532GsUlW/qtE/E2/QnbcBuV29gY+lezhDwU9IJY70lDxULL822APW5
|
||||
623KgqooqjWo2O4LKFvxGNqDwe/QQltQbNEfRMOm9ugAjDYr/mUu8sZ+lVNXIvQ5
|
||||
cp1IfzExG4htcuHwwQRcsHW5c/8VAbJZ2yoWS2klDDvqy3KxfZ6EsPd6/7yIWwrZ
|
||||
m+d4O+ujQn/6NRHONNYPA2YH8sfbL+C3m02FyTVQO6ZzpLdlHKs9h2wd5aEw7MjH
|
||||
JO05K/PyGaUn07J7z3pk8XcK8qf1FuCTooDSgQVqI0i3X7PWgtIhqKfvyJaspxxT
|
||||
U4X8NHt95o1ZhWp8NPQlfTDLmxwU5QUrK8VZ5FxTStcdZZg+9OucBVVbrVQLLL2Y
|
||||
Q80npcus3I90styh7tQwtzojkERr/WLwDfj3hahiCMFqLagLkg5nw10mwY0xY019
|
||||
EILbuQINBFz3xHoBEADJ1rOpvyKpOXtTzMEEsWAYTLAzEle7EeqTUJpJcnqz+r5J
|
||||
OBMhLxvuRmKRK2dU23gQicCHxmOQhNCd4b2d64G9QbngvJeyEv4IwgLxePNv5/LN
|
||||
00PTk6rUNkApGcVU663tHXs8Q8Ux+R1zYk7UY86LIoBzC8lA21q5WktXl1qaAw85
|
||||
a/fn9G/Vd+o+Gb8XS6OfCdmM9CGV1Gv3vnAJ+xytf+I5UIFXs+FExlWpWlcNGlYl
|
||||
RFHAiHB/f/rvNJVnHamyipmfn6T3N809A+k9XVqmbhC1ymav1eYPfHCOtCFwMXmv
|
||||
RgD7D2fNoJzu93cX8qPZLvyz0VOFuR1XVyshTKsxB4foXaqA6xhTtHBqn6F2Nz90
|
||||
gpvrd+mTxNxaCkhh2j2rQzfDGLcVCpoMLtFb9vcwWYOrsVjNAAhi91VSSc6xkILT
|
||||
bxeWEljyFYDYZQh+M/FimY2YGULgdwX1nlRfIrRRJ/E0gY6KzwbBQd6dL8LWx9bY
|
||||
Vl/hAMZeAuifFfBqSbL7V7Q3yrmU4PErVKhH/2Q/eCD47xvjK5mAqVPo52CSJ6RF
|
||||
iZNHUfA4i7EFznEM/4K3+GahqYcyu2fKu/AiHp9WlK5rO+KpliD84YQ8dmJ7h4/x
|
||||
j0plnxclJjAhhGEl3m+v6BINdfLNbZyib+T4swmf/OUA7+NYR1ZHWmWfMN2qnwAR
|
||||
AQABiQI2BBgBCAAgFiEEmgzU6ll8mr43EwCBbB5eUx4NXX8FAlz3xHoCGyAACgkQ
|
||||
bB5eUx4NXX+t8w/9HsyLi8nHw7QQGQWFdjVNdjybsz+IuMV2Kqwda5dLwlGAqGZO
|
||||
DGCANUBaYuL5tcF1oeB/pbnH1ZYSx+m97SjZI1xOl57B4ul1bWYwsO6+TUMlrMLH
|
||||
zSPEVqXqykMf+t/M992pQM+VVigkWCJRyS3VXF/EDAQjTnX5LrzvdzHlqi11JK8D
|
||||
n32GirBuZsPQK4FKRiq5kpMIX7tY68Ws19CLixm9+NTFAwYWqt2qri4IxXf+Qj3f
|
||||
x2FbP5yp4VlTD+43gy/4/ShbXoY9SQ/SvFB0U63xIbyg/ffxUF1wG6Tf7/5KK2tb
|
||||
f7tH8WmMsdbEe+qfZvIQ6gwSG724P3guSDF46+uRpvrjpGr5ywHl1iMZCZJg6J+X
|
||||
CHCabgr0APvkok6U9mRlN5SW8pz89iINSvzHOOluAOu1Ly6+igJdQAClcfA7eKa2
|
||||
NleRfw6myJvE7RWm4TqWuxNXyOzttnB+u3ZzrY3LzKBAsk+qVL+CTVa/j5KIBLp9
|
||||
LQz1Yg1dPrbQ2qWkqcmPoJzs4l7rq1dAqtMInv2d0qd7AWy+dWsdHvr6BzoFG+4U
|
||||
XlKFm9kpHVXuoZSkEzsE57ahbIXpWVsYwhC/0zGj3YpcBZ+hFjqwpCMj15JgSWyZ
|
||||
vpq31iyO4Ietk4vCHs/35igT6Sr06lfynI6Qg7w3pXXm5q0BEiTiqy/54WW5Ag0E
|
||||
XPfEegEQALBmWj7q9EH1Gf/78mbotXTBNtALbzW7HNpHkZPXiCStXKLVTfbhiTNA
|
||||
qK0Mfm85+RIIiJ5ad4rG1SjpEuuzQkIEy9iUFm+zmw7+PMxjeq/f6Rri2aFtT5wX
|
||||
encTqJnknK1zDcSeRifAni3cswhByYBTCLOqowKwyUo/mWxsfHarqmNEPQCu+87f
|
||||
ekVh1MRZcvnIvclNMU2NocNAiBL+/q+k66So+/hneq98l2YrEo568ME6ikUQ1q4K
|
||||
yWau4QYx6mIDbZlc1b9GVSA7N8x1HXvqj05vnD43KbGNQHJxfppg6SdBjsZZcjpZ
|
||||
E2r1f9VjDGcVA85Wj31nlrHEtBtq2oiC4QcgeuyFmx8wOnEQg4QYGmc9xWlYgeDG
|
||||
W2TTiMfO9lFw+cUTuWMU0/Fc0e7D/4a/5xnA3fv0/IjiUnn1uJKY5MoBIu/eCuYL
|
||||
P3R6MLAlDwlsfX6C4n5xRHsn8T8neSLLUuqev7EPs1Bbsyy4hey5lAgwopPGJnzQ
|
||||
8mLwoEJ9jIY+EGPd5Mcl9HV5MX6UKXgySJcF643Cuu+r35n926elnRt4rIktqJ3V
|
||||
VB8jlsdqGtSkiLBwmbzTKw/g0oWAf5EQkHKnowouftd0tROxTbHfkvy2KDG5wX0C
|
||||
k231ckTQnmBqIV8k9JLC7fmWYcJQfGdMk85K/kZ89mpU7oJE9z3FABEBAAGJAjYE
|
||||
GAEIACAWIQSaDNTqWXyavjcTAIFsHl5THg1dfwUCXPfEegIbDAAKCRBsHl5THg1d
|
||||
f7LsEACjZ+VUnj0AX99uJXofBhNvQaHUoOyY/UBjAhutuwOGe7a5boUYMITp+SbC
|
||||
decqgKewxV5x3ki4noAYR13ctzkDKqdV3IfCR/U1fSuRvCQxdamUM1S6aLX1SL8t
|
||||
GOYvmsaeiW3gRsRsKng4puW0woozQPQfJi7Zlhzu5o0xkBt91YKhzAFna+sxqJAH
|
||||
XAjF02F04JhSw7+tnTn+taekkpsmywrKR1tgMfBODyY+WVtXer7aonA0GrQPd8ki
|
||||
9sCK7txOUZ6xan+8qJeIyGOswa62o9OSVkdElJJjUgwp6LlDqmg/BHON64Mb7m97
|
||||
6R8MIs4ONFpXaoWZhGdCYiSw+YaOuQGsrTVsHrxkBwyAEB9E29fv5tSyYcrxBnbq
|
||||
cX8GLNxL7ug6P1cFMYpu5CDfGywmtvnYvtteNsF4vhNe5KQvqvj2bVV4h7bU3qEc
|
||||
YWIWVVrgMN6SMMdXvUc6fTyn3g8Ka/k/orobGNiaxV1hlqiQ8Kj5KPduQUvtolGS
|
||||
1azef9t6Xurdqy1bHaMjblZkhvHJAB7NmCs5udHMHUFQBN/x+DSCbAOqKpoS2/Dv
|
||||
1WCLOJOAD6TvB6mBVIwAtU1JkqbXlx8k1/BTmTbLWTPPXFeHt/MMpxNXCX6mPDR9
|
||||
VN5HWu9lEl22Am8Ezkxy0Hva2Mw1DT0raOJln1qzq+8q4DsheQ==
|
||||
=xSlg
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
</pre>
|
||||
</p>
|
||||
@ -126,6 +112,6 @@ UzZbs54AnA==
|
||||
<h3>Fingerprint</h3>
|
||||
<p>
|
||||
<pre>
|
||||
7521 7C08 8B3E F6AE 55F4 D4C7 B586 EAFC DF2F 65F4
|
||||
9A0C D4EA 597C 9ABE 3713 0081 6C1E 5E53 1E0D 5D7F
|
||||
</pre>
|
||||
</p>
|
@ -1,23 +1,32 @@
|
||||
define(`TITLE', `Something completely different: SNMP to MySQL')
|
||||
define(`DATE', `2015-10-12')
|
||||
define(`CONTENT', `
|
||||
I'm helping to maintain a fleet of about 50 printers in a charity distributed over about 30 locations in the city. Now, we wanted to know how much the individual printers are used to get some numbers for an effort to reduce the number of printers.
|
||||
<!-- { "title": "Something completely different: SNMP to MySQL" } -->
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
I'm helping to maintain a fleet of about 50 printers in a charity distributed over about 30 locations in the city. Now, they wanted to know how much the individual printers are utilized to get some numbers for an effort to reduce the number of printers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So, what is more self-evident then using SNMP to query the total page counter on a daily base - or better on an hourly base since the printers are switched off at this or that time and those we at least get sometimes valid data.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Typical monitoring tools like Cacti or Zabbix are very good in drawing nice graphs but not so good in delivering absolute numbers. So I decided to write something on my own: query some devices for some SNMP data points and store the results in a database. Which devices and which data points and which combinations? Everything in the database too.
|
||||
</p>
|
||||
|
||||
I looked for a SNMP library, first in Python, then in Java - since I'm quite familiar with these languages - but everything I found was rather complicated to use. Then I looked for something in C# and found ''SnmpSharpNet''. Still not that easy to use but easier then what I found in Python or Java.
|
||||
<p>
|
||||
I looked for a SNMP library, first in Python, then in Java - since I'm quite familiar with these languages - but everything I found was rather complicated to use. Then I looked for something in C# and found ''SnmpSharpNet''. Still not that easy to use but much easier then what I found in Python or Java.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For that reason I started coding the little tool in C#. And what I did is working very well now. Configuration and error-handling is not perfect yet, but it is working. Enough for today.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
BTW: I switched developing the code between Microsoft Visual Studio 2013 (on Windows) and Xamarin Studio (on the Mac) and run the tool on Linux. Works without any problem. Very nice!
|
||||
|
||||
<!--more-->
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
[code language="csharp"]
|
||||
<pre>
|
||||
<code language="csharp">
|
||||
namespace Snmp2Mysql
|
||||
{
|
||||
|
||||
@ -67,9 +76,11 @@ namespace Snmp2Mysql
|
||||
}
|
||||
}
|
||||
}
|
||||
[/code]
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
[code language="SQL"]
|
||||
<pre>
|
||||
<code language="SQL">
|
||||
CREATE TABLE `device_t` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`address` varchar(45) NOT NULL,
|
||||
@ -107,14 +118,14 @@ CREATE TABLE `collecteddata_t` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `devicedataitem_fk_idx` (`devicedataitem`),
|
||||
CONSTRAINT `devicedataitem_fk` FOREIGN KEY (`devicedataitem`) REFERENCES `devicedataitem_t` (`id`)
|
||||
[/code]
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
And here are the sources:
|
||||
|
||||
<a href="http://a385e-5.de/wp-content/uploads/Snmp2Mysql.zip">Snmp2Mysql</a>
|
||||
<a href="https://gitlab.com/wolutator/Snmp2Mysql.git">https://gitlab.com/wolutator/Snmp2Mysql.git</a>
|
||||
|
||||
I'm using GPL code from MySQL (the MySQL Connector for .NET), find it here <a href="http://dev.mysql.com/downloads/connector/net/" target="_blank">http://dev.mysql.com/downloads/connector/net/</a> and the SNMP library from <a href="http://www.snmpsharpnet.com" target="_blank">http://www.snmpsharpnet.com</a>.
|
||||
|
||||
Ah, evaluation of the data? Haven't thought about, maybe using some tricky SQL statement or an Excel pivot table. I'll come back about that.
|
||||
|
||||
')
|
@ -1,19 +1,34 @@
|
||||
define(`TITLE', `Why always SPI CS on pin 10?')
|
||||
define(`DATE', `2016-03-03')
|
||||
define(`CONTENT', `
|
||||
<!-- { "title": "Why always SPI CS on pin 10?" } -->
|
||||
<h1>#title#</h1>
|
||||
|
||||
<p>
|
||||
Thank you, Ladyada, for <a href="https://learn.adafruit.com/adafruit-2-8-tft-touch-shield-v2">this great display</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
But why is TFT CS on pin 10?
|
||||
</p>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/bildschirmfoto-2016-03-03-um-21-48-49.png" rel="attachment wp-att-711"><img src="http://a385e5.files.wordpress.com/2016/03/bildschirmfoto-2016-03-03-um-21-48-49.png" alt="Bildschirmfoto 2016-03-03 um 21.48.49" width="722" height="449" class="alignnone size-full wp-image-711" /></a>
|
||||
<p>
|
||||
<a href="files/bildschirmfoto-2016-03-03-um-21-48-49.png" rel="attachment wp-att-711"><img src="files/bildschirmfoto-2016-03-03-um-21-48-49.png" alt="Bildschirmfoto 2016-03-03 um 21.48.49" width="722" height="449" class="alignnone size-full wp-image-711" /></a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pin 10 is also the SPI CS for the Ethernet shield. Why not, for instance, pin 6:
|
||||
</p>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/img_1211-e1457038834523.jpg" rel="attachment wp-att-712"><img src="http://a385e-5.de/wp-content/uploads/IMG_1211-e1457038834523-1024x768.jpg" alt="IMG_1211" width="474" height="356" class="alignnone size-large wp-image-712" /></a>
|
||||
<p>
|
||||
<a href="files/img_1211-e1457038834523.jpg" rel="attachment wp-att-712"><img src="files/IMG_1211-e1457038834523-1024x768.jpg" alt="IMG_1211" width="474" height="356" class="alignnone size-large wp-image-712" /></a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Carefully lift pin 9 of the level shifter and connect it using a thin wire with pin 6 of the Arduino connector.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And voila, both the display and the ethernet shield is working:
|
||||
</p>
|
||||
|
||||
<a href="http://a385e5.files.wordpress.com/2016/03/img_1212-e1457039094609.jpg" rel="attachment wp-att-713"><img src="http://a385e-5.de/wp-content/uploads/IMG_1212-e1457039094609-1024x768.jpg" alt="IMG_1212" width="474" height="356" class="alignnone size-large wp-image-713" /></a>
|
||||
')
|
||||
<p>
|
||||
<a href="files/img_1212-e1457039094609.jpg" rel="attachment wp-att-713"><img src="files/IMG_1212-e1457039094609-1024x768.jpg" alt="IMG_1212" width="474" height="356" class="alignnone size-large wp-image-713" /></a>
|
||||
</p>
|
||||
|
81
docroot/posts/2019-01-04.01/article.pag
Normal file
@ -0,0 +1,81 @@
|
||||
<!-- { "title": "From InfluxDB to Twitter - daily temperature tweet" } -->
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
This is my first attempt to build a tweetbot. I'm using node-red both as development and runtime environment. It comes with dedicated plugins for both InfluxDB and Twitter.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The whole flow of the tweetbot is this:
|
||||
|
||||
<img src="files/Screenshot_2019-01-04_08-28-39.png" width="1200"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It starts with an inject node "Daily at noon" (<a href="files/Screenshot_2019-01-04_08-29-24.png" target="_blank">*</a>), with triggers the whole flow once a day at high noon.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The four influx query nodes read data from the InfluxDB using the following queries, each one encapsulated in one influx query node:
|
||||
|
||||
<pre><code class="SQL">
|
||||
select mean(pv) from measured where deviceid = 'Hedge' and kind = 'Temperature' and time > now() - 15m
|
||||
select mean(pv) from measured where deviceid = 'Hedge' and kind = 'Temperature' and time > now() - 24h
|
||||
select min(pv) from measured where deviceid = 'Hedge' and kind = 'Temperature' and time > now() - 24h
|
||||
select max(pv) from measured where deviceid = 'Hedge' and kind = 'Temperature' and time > now() - 24h
|
||||
</code></pre>
|
||||
|
||||
See one of this node <a href="files/Screenshot_2019-01-04_08-29-47.png" target="_blank">here</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The data in the InfluxDB considered by these queries looks like this:
|
||||
|
||||
<pre>
|
||||
> select * from measured where kind = 'Temperature' and deviceid = 'Hedge' limit 10
|
||||
name: measured
|
||||
time category deviceid kind pv qv sv tv
|
||||
---- -------- -------- ---- -- -- -- --
|
||||
2018-12-24T12:57:42.749065469Z Outdoor Hedge Temperature 5.029083728790283 -1
|
||||
2018-12-24T12:58:54.77913537Z Outdoor Hedge Temperature 5.020352363586426 -1
|
||||
2018-12-24T13:00:06.754460483Z Outdoor Hedge Temperature 5.032242298126221 -1
|
||||
2018-12-24T13:01:18.76525238Z Outdoor Hedge Temperature 5.024284362792969 -1
|
||||
2018-12-24T13:02:30.767286588Z Outdoor Hedge Temperature 5.016140937805176 -1
|
||||
2018-12-24T13:03:42.765550192Z Outdoor Hedge Temperature 5.0108466148376465 -1
|
||||
2018-12-24T13:04:54.774511705Z Outdoor Hedge Temperature 5.019856929779053 -1
|
||||
2018-12-24T13:06:05.772434549Z Outdoor Hedge Temperature 5.020042419433594 -1
|
||||
2018-12-24T13:07:16.759739681Z Outdoor Hedge Temperature 5.036855697631836 -1
|
||||
2018-12-24T13:08:27.757626686Z Outdoor Hedge Temperature 4.993878364562988 -1
|
||||
>
|
||||
</pre>
|
||||
|
||||
<code>pv</code> has the temperature, <code>sv</code> has the battery voltage. In this case it is -1 since this particular thermometer is powered by a power supply from mains.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
In the following four change nodes (<a href="files/Screenshot_2019-01-04_08-30-06.png" target="_blank">*</a>) a dedicated topic for the messages from the influx query nodes will be set to merge them into a single key/value object in the following join node (<a href="files/Screenshot_2019-01-04_08-30-27.png" target="_blank">*</a>). This node will collect four messages and put them into a single object with the topic as key and the message as value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This object in turn is input for the function node "TextPreparator" (<a href="files/Screenshot_2019-01-04_08-30-48.png" target="_blank">*</a>) where the tweet is prepared using a small snippet of JavaScript code:
|
||||
|
||||
<pre><code class="JavaScript">
|
||||
let output = ""
|
||||
output += `Die aktuelle Temperatur zuhause ist ${msg.payload.avg15min[0].mean.toFixed(1)}°C.\n`
|
||||
output += `Die Durchschnittstemperatur der letzten 24 Stunden war ${msg.payload.avg24h[0].mean.toFixed(1)}°C, `
|
||||
output += `die Tiefsttemperatur war ${msg.payload.min[0].min.toFixed(1)}°C um ${msg.payload.min[0].time.getHours()}:${msg.payload.min[0].time.getMinutes()} Uhr und `
|
||||
output += `die Höchsttemperatur war ${msg.payload.max[0].max.toFixed(1)}°C um ${msg.payload.max[0].time.getHours()}:${msg.payload.max[0].time.getMinutes()} Uhr.\n`
|
||||
output += "Powered by @NodeRED and @InfluxDB."
|
||||
msg.payload = output
|
||||
return msg;
|
||||
</code></pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally this text will be sent to Twitter via the node "Tweet" (<a href="files/Screenshot_2019-01-04_08-31-06.png" target="_blank">*</a>). Done.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<img src="files/Screenshot_2019-01-04_09-08-07.png"/>
|
||||
</p>
|
49
docroot/posts/2019-07-17.01/article.pag
Normal file
@ -0,0 +1,49 @@
|
||||
<!-- { "title": "SSH Key Forwarding meets Screen" } -->
|
||||
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
I'm using both SSH key forwarding and screen a lot. Since I discovered Nitrokey, the OpenPGP card and Yubikey, all my SSH keys are on those tokens.
|
||||
|
||||
It works perfectly: You authenticated using the token in the laptop and use that key over a whole chain of machines and in some cases and the third or fourth machine in a row to pull and push to git.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I'm also using screen a lot. I set up a bunch of related sessions, sometimes on different machine in one screen session, detach from it, use it again the next day and so on.
|
||||
|
||||
Also works fine. Longwinding login processes, especially when bastion hosts and jump hosts are involved can be avoided.
|
||||
|
||||
However, at least out of the box, SSH key forwarding does not work in this setup. Suddenly ssh asks for passwords. Ugh!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Google was my friend and I found this page: <a href="https://gist.github.com/martijnvermaat/8070533">https://gist.github.com/martijnvermaat/8070533</a>. Martijn explains an easy solution to address this problem.
|
||||
|
||||
Not to forget it again I will summarize it here.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<ol>
|
||||
<li>Create a file <tt>~/.screenrc</tt> and put
|
||||
|
||||
<pre><code class="shell">
|
||||
setenv SSH_AUTH_SOCK $HOME/.ssh/SSH_AUTH_SOCK
|
||||
</code></pre>
|
||||
|
||||
into it. If you are using bash, don't be tempted to write <tt>export</tt> instead of <tt>setenv</tt>, it won't work.
|
||||
</li>
|
||||
<li>
|
||||
Create a file <tt>~/.ssh/rc</tt> and put
|
||||
|
||||
<pre><code class="shell">
|
||||
if test "$SSH_AUTH_SOCK" ; then
|
||||
ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
|
||||
fi
|
||||
</code></pre>
|
||||
|
||||
into it.
|
||||
</li>
|
||||
<li>Restart the screen session, done. Works perfectly for me.</li>
|
||||
</ol>
|
||||
|
||||
|
102
docroot/posts/2020-02-09.01/article.pag
Normal file
@ -0,0 +1,102 @@
|
||||
<!-- { "title": "Migrating a Grafana configuration database from SQLite to MySQL/MariaDB" } -->
|
||||
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
In the default installation <a href="https://grafana.com">Grafana</a> is using a SQLite database for its configuration and session data. Certainly, this is working very well in most situations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Nevertheless I preferred to use my anyhow existing MariaDB server.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
So, I had to migrate the already existing SQLite database containing the Grafana configuration to MySQL syntax. Not to difficult, but at least it was not working without some adjustments. I found some hints how to do this migration. However, at least one hint I found more than once pointed to a paid migration service - no, thank you.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I think for text processing using regular expressions Perl is the language of choice. so I prepared a small processing frame:
|
||||
<pre><code class="perl">
|
||||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
|
||||
print "$_\n";
|
||||
}
|
||||
</code></pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I deployed a dedicated test instance of a MariaDB server using Docker on my laptop, created a database on that MariaDB server
|
||||
|
||||
<pre><code class="SQL">
|
||||
create database grafana;
|
||||
create user 'grafana'@'%' identified by 'test123';
|
||||
grant all privileges on grafana.* to 'grafana'@'%';
|
||||
flush privileges;
|
||||
</code></pre>
|
||||
|
||||
and used a small shell script to export the SQLite database into a SQL file, pass it through the above Perl script and feed it into the MariaDB server:
|
||||
|
||||
<pre><code class="shell">
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
DB_HOST=127.0.0.1
|
||||
DB_ROOT_PASS=geheim123
|
||||
DB_NAME=grafana
|
||||
DB_USER=grafana
|
||||
DB_PASS=test123
|
||||
|
||||
|
||||
cat grafana.in | sqlite3 grafana.db && \
|
||||
cat grafana.sql | ./sqlite2mariadb.pl > new.sql && \
|
||||
echo "drop database $DB_NAME; create database $DB_NAME;' | \
|
||||
mysql -h $DB_HOST -u root --password=$DB_ROOT_PASS mysql && \
|
||||
cat new.sql | mysql -h $DB_HOST -u $DB_USER --password=$DB_PASS --abort-source-on-error -v $DB_NAME
|
||||
</code></pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Inspecting the error messages from the import into the MariaDB I extended the Perl script more and more and finally ended up with this code:
|
||||
|
||||
<pre><code class="perl">
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
s/^BEGIN TRANSACTION;//;
|
||||
s/^PRAGMA .+?;//;
|
||||
s/AUTOINCREMENT/AUTO_INCREMENT/;
|
||||
s/TEXT PRIMARY KEY/VARCHAR(1024) PRIMARY KEY/;
|
||||
s/` TEXT /` MEDIUMTEXT /;
|
||||
s/`for` INTEGER/`for` BIGINT/;
|
||||
s/`frequency` INTEGER/`frequency` BIGINT/;
|
||||
s/`epoch` INTEGER/`epoch` BIGINT/;
|
||||
s/`epoch_end` INTEGER/`epoch_end` BIGINT/;
|
||||
s/`created` INTEGER/`created` BIGINT/;
|
||||
s/`updated` INTEGER/`updated` BIGINT/;
|
||||
s/^.+? sqlite_sequence.*$//;
|
||||
s/^CREATE INDEX `.+$//;
|
||||
print "$_\n";
|
||||
}
|
||||
</code></pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Maybe on a different installation or using a future version of Grafana you would run into more issues. In that case: just put additional substitutions into the script.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When the whole stuff ran through without errors I backupped the configuration and storage volumes of my Grafana container, created new ones with copies of the old ones. I removed the <tt>grafana.db</tt> file from the storage volume and modified the <tt>grafana.ini</tt> in the configuration volume to use the MariaDB server, loaded the transformed SQL into the productive MariaDB server and restarted the Grafana container with the new volumes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Suprisingly it works immediately.
|
||||
</p>
|
||||
|
8
docroot/posts/2020-06-24.01/article.pag
Normal file
@ -0,0 +1,8 @@
|
||||
<!-- { "title": "Wiki created" } -->
|
||||
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
At <a href="https://home.hottis.de/dokuwiki/">https://home.hottis.de/dokuwiki/</a> a local wiki can be found now.
|
||||
</p>
|
||||
|
22
docroot/posts/2021-05-15.01/article.pag
Normal file
@ -0,0 +1,22 @@
|
||||
<!-- { "title": "Mains Frequency Measurement Project" } -->
|
||||
|
||||
|
||||
<h1>#title#</h1>
|
||||
<p>
|
||||
The homepage of my "Mains Frequency Measurement Project" is at <a href="https://wiki.mainscnt.eu">https://wiki.mainscnt.eu/</a>.
|
||||
</p>
|
||||
<p>
|
||||
Measurements from already seven locations all over Europe are collected in the project's database and displayed in one visualization at <a href="https://grafana.mainscnt.eu">https://grafana.mainscnt.eu</a>.
|
||||
</p>
|
||||
<p>
|
||||
More data contributions are welcome.
|
||||
</p>
|
||||
<p>
|
||||
Access to the collected data can be granted. Just contact me.
|
||||
</p>
|
||||
<p>
|
||||
<img src="files/IMG_2507.jpg" width="300"/>
|
||||
</p>
|
||||
|
||||
|
||||
|
101
files/9A0CD4EA597C9ABE371300816C1E5E531E0D5D7F.key
Normal file
@ -0,0 +1,101 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
JWjBNR9VP6VNX9nvxRC3f7u4gl6fSiZViYJ43a0nR24LbQKXudE88waxL+IV7563
|
||||
JJUicKI7X+PAiVwp3DsPA0/fxbcrkanNau9L75RCtHVIEK72QBIcCIBTMARktIQH
|
||||
bChNd/+1V+WxH1diUIeFRx9svQT3UX89R9qn6INy0qrUCzQ9ZtKrru+orngOlFLc
|
||||
93zKcICJYyoC82LSGZA4+ax8Cn6E/z2gjAw8aSEaOm/C9GUJ4cWpPTYp9LQlV29s
|
||||
ZmdhbmcgSG90dGdlbnJvdGggPHdvaG9AaG90dGlzLmRlPokCTgQTAQgAOBYhBJoM
|
||||
1OpZfJq+NxMAgWweXlMeDV1/BQJc+B2MAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4B
|
||||
AheAAAoJEGweXlMeDV1/b34P/A0ZLFKNZ7RXILqfAxW5aNURMNbRuc3Z1QJPmOQU
|
||||
1WRjQt71yYcD1SVNwjW5NKTbueMWqS+I/pVIdgCVDhBxHhwnAl8Xq131hZ7+84TR
|
||||
MGw/rsLx7dU3jmogpijqc8ghcMshuPXUDxEg6Qso0Bi4LrxdEvZaIDbXVaayhdrz
|
||||
bJe8JVs7cXngnrtfIwwUhpc+YkA1v4DShygXPVvKFQtDuEwzbtdMvlKJNi1iuK5v
|
||||
ssc6A3ANaQ532GsUlW/qtE/E2/QnbcBuV29gY+lezhDwU9IJY70lDxULL822APW5
|
||||
623KgqooqjWo2O4LKFvxGNqDwe/QQltQbNEfRMOm9ugAjDYr/mUu8sZ+lVNXIvQ5
|
||||
cp1IfzExG4htcuHwwQRcsHW5c/8VAbJZ2yoWS2klDDvqy3KxfZ6EsPd6/7yIWwrZ
|
||||
m+d4O+ujQn/6NRHONNYPA2YH8sfbL+C3m02FyTVQO6ZzpLdlHKs9h2wd5aEw7MjH
|
||||
JO05K/PyGaUn07J7z3pk8XcK8qf1FuCTooDSgQVqI0i3X7PWgtIhqKfvyJaspxxT
|
||||
U4X8NHt95o1ZhWp8NPQlfTDLmxwU5QUrK8VZ5FxTStcdZZg+9OucBVVbrVQLLL2Y
|
||||
Q80npcus3I90styh7tQwtzojkERr/WLwDfj3hahiCMFqLagLkg5nw10mwY0xY019
|
||||
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
|
||||
=xSlg
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
BIN
files/IMG_1211-e1457038834523-1024x768.jpg
Normal file
After Width: | Height: | Size: 266 KiB |
BIN
files/IMG_1212-e1457039094609-1024x768.jpg
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
files/IMG_2507.JPG
Normal file
After Width: | Height: | Size: 959 KiB |
BIN
files/IMG_2507.jpg
Normal file
After Width: | Height: | Size: 448 KiB |
BIN
files/Screenshot_2019-01-04_08-28-39.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
files/Screenshot_2019-01-04_08-29-24.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
files/Screenshot_2019-01-04_08-29-47.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
files/Screenshot_2019-01-04_08-30-06.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
files/Screenshot_2019-01-04_08-30-27.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
files/Screenshot_2019-01-04_08-30-48.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
files/Screenshot_2019-01-04_08-31-06.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
files/Screenshot_2019-01-04_09-08-07.png
Normal file
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
BIN
files/img_1211-e1457038834523.jpg
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
files/img_1212-e1457039094609.jpg
Normal file
After Width: | Height: | Size: 1.3 MiB |
@ -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>.
|
||||
|
||||
')
|
@ -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:
|
||||
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
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>
|
||||
|
||||
|
||||
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.
|
||||
|
||||
')
|
@ -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:
|
||||
|
||||
|
||||
|
||||
|
||||
<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 ...)
|
||||
')
|
@ -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 = [
|
||||
{"label":"_", "key":"magic", "type":"I", "default": ""},
|
||||
{"label":"Wifi SSID", "key":"wifiSsid", "type":"C", "length":32, "default":"test"},
|
||||
{"label":"Wifi Key", "key":"wifiKey", "type":"C", "length":64, "default":"geheim"},
|
||||
{"label":"MQTT Broker", "key":"mqttBroker", "type":"C", "length":64, "default":"broker.hottis.de"},
|
||||
{"label":"MQTT Username", "key":"mqttUser", "type":"C", "length":32, "default":"esp1"},
|
||||
{"label":"MQTT Password", "key":"mqttPass", "type":"C", "length":32, "default":"geheim"},
|
||||
{"label":"MQTT ClientId", "key":"mqttClientId", "type":"C", "length":32, "default":"changeThis"},
|
||||
{"label":"MQTT Topic", "key":"mqttTopic", "type":"C", "length":64, "default":"IoT/espThermometer2/location/measurement"},
|
||||
{"label":"MQTT Port", "key":"mqttPort", "type":"I", "default":8883},
|
||||
{"label":"Measure Period", "key":"measurePeriod", "type":"I", "default":300}
|
||||
]
|
||||
|
||||
h_file = Template(file="configuration_h.tmpl", searchList=[{"configItems":configItems}])
|
||||
open('configuration.h','w').write(str(h_file))
|
||||
c_file = Template(file="configuration_c.tmpl", searchList=[{"configItems":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 <Arduino.h>
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "configuration.h"
|
||||
#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 != "_"
|
||||
#if $configItem.type == "C"
|
||||
strcpy(configBlock.$configItem.key, "$configItem.default");
|
||||
#else if $configItem.type == "I"
|
||||
configBlock.$configItem.key = $configItem.default;
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
}
|
||||
|
||||
String buffer =
|
||||
"<!doctype html"
|
||||
"<html lang=\"en\">"
|
||||
" <head>"
|
||||
" <title>ESP8266 Thermometer Configuration Page</title>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h1>ESP8266 Configuration Page</h1>";
|
||||
|
||||
if (configSaved) {
|
||||
configSaved = false;
|
||||
buffer += "<h2>Configuration saved</h2>";
|
||||
}
|
||||
|
||||
buffer +=
|
||||
" <form action=\"/config\" method=\"GET\">"
|
||||
" <table>"
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.label != "_"
|
||||
" <tr>"
|
||||
" <td>"
|
||||
" <label for\"$configItem.key\">$configItem.label</label>"
|
||||
" </td><td>"
|
||||
" <input type=\"text\" name=\"$configItem.key\" id=\"$configItem.key\" ";
|
||||
|
||||
#if $configItem.type == "C"
|
||||
buffer += " size=\"$configItem.length\" ";
|
||||
buffer += " value=\"";
|
||||
buffer += configBlock.$configItem.key;
|
||||
buffer += "\"";
|
||||
#else if $configItem.type == "I"
|
||||
buffer += " value=\"";
|
||||
buffer += configBlock.$configItem.key;
|
||||
buffer += "\"";
|
||||
#end if
|
||||
|
||||
buffer +=
|
||||
" />"
|
||||
" </td>"
|
||||
" </tr>"
|
||||
#end if
|
||||
#end for
|
||||
" <tr>"
|
||||
" <td colspan=\"2\">"
|
||||
" <button type=\"submit\">Save</button>"
|
||||
" </td>"
|
||||
" </tr>"
|
||||
" </table>"
|
||||
" </form>"
|
||||
" </body>"
|
||||
"</html>";
|
||||
|
||||
webServer.send(200, "text/html", buffer);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println("indexHtml request served");
|
||||
#endif
|
||||
}
|
||||
|
||||
void configServeGetConfiguration() {
|
||||
String arg;
|
||||
|
||||
#for $configItem in $configItems
|
||||
#if $configItem.label != "_"
|
||||
arg = webServer.arg("$configItem.key");
|
||||
#if $configItem.type == "C"
|
||||
strcpy(configBlock.$configItem.key, arg.c_str());
|
||||
#else if $configItem.type == "I"
|
||||
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("EEPROM saved");
|
||||
|
||||
configSaved = true;
|
||||
webServer.sendHeader("Location", String("/"), true);
|
||||
webServer.send(302, "text/plain", "");
|
||||
//webServer.send(200, "text/html", "configuration saved");
|
||||
}
|
||||
|
||||
void showConfiguration() {
|
||||
Serial.println("Configuration is");
|
||||
|
||||
#for $configItem in $configItems
|
||||
Serial.print("$configItem.key = ");
|
||||
Serial.println(configBlock.$configItem.key);
|
||||
|
||||
#end for
|
||||
|
||||
Serial.println("---");
|
||||
}
|
||||
[/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("Starting ...");
|
||||
#endif
|
||||
|
||||
pinMode(CONFIG_SWITCH, INPUT_PULLUP);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
EEPROM.begin(512);
|
||||
EEPROM.get(EEPROM_ADDR, configBlock);
|
||||
|
||||
Serial.print("Magic: ");
|
||||
Serial.println(configBlock.magic);
|
||||
|
||||
configMode = ((LOW == digitalRead(CONFIG_SWITCH)) || (configBlock.magic != MAGIC));
|
||||
|
||||
if (configMode) {
|
||||
#ifdef DEBUG
|
||||
Serial.println("Configuration mode");
|
||||
#endif
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
setupConfiguration();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
Serial.println("Production mode");
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
showConfiguration();
|
||||
#endif
|
||||
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
setupProduction();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println("Started.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (configMode) {
|
||||
loopConfiguration();
|
||||
} else {
|
||||
loopProduction();
|
||||
}
|
||||
}
|
||||
|
||||
void setupConfiguration() {
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP(CONFIG_SSID);
|
||||
#ifdef DEBUG
|
||||
Serial.println("AP started");
|
||||
#endif
|
||||
|
||||
webServer.on("/", configServeIndex);
|
||||
webServer.on("/config", configServeGetConfiguration);
|
||||
webServer.onNotFound(configServeNotFound);
|
||||
webServer.begin();
|
||||
#ifdef DEBUG
|
||||
Serial.println("Webserver started");
|
||||
#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>.
|
||||
|
||||
')
|
@ -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>).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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.
|
||||
')
|
@ -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 > (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->buttonPin);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (button->oldPressedState != button->pressedState) {
|
||||
Serial.print("Index ");
|
||||
Serial.print(button->index);
|
||||
Serial.print(", state changed from ");
|
||||
Serial.print(button->oldPressedState);
|
||||
Serial.print(" to ");
|
||||
Serial.print(button->pressedState);
|
||||
Serial.println();
|
||||
button->oldPressedState = button->pressedState;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (button->pressedState) {
|
||||
case psHIGH:
|
||||
if (buttonState == LOW) {
|
||||
button->pressedState = psLOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
} else {
|
||||
if (currentMicros > (button->lastStateChange + configBlock.debounce)) {
|
||||
button->pressedState = psACCEPTED_LOW;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case psACCEPTED_LOW:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psSHORT;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPress * 1000))) {
|
||||
button->pressedState = psLONG_START;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psSHORT:
|
||||
sendMsg(button->index, "PRESS_SHORT");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_START:
|
||||
sendMsg(button->index, "PRESS_LONG_START");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_CONT:
|
||||
if (buttonState == HIGH) {
|
||||
button->pressedState = psLONG_END;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros > (button->lastStateChange + (configBlock.longPressRepeat * 1000))) {
|
||||
button->pressedState = psLONG_CONT_SEND;
|
||||
button->lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLONG_CONT_SEND:
|
||||
sendMsg(button->index, "PRESS_LONG_CONT");
|
||||
button->pressedState = psLONG_CONT;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_END:
|
||||
sendMsg(button->index, "PRESS_LONG_END");
|
||||
button->pressedState = psHIGH;
|
||||
button->lastStateChange = currentMicros;
|
||||
break;
|
||||
default:
|
||||
button->pressedState = psHIGH;
|
||||
button->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.
|
||||
|
||||
')
|
@ -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' }
|
||||
];
|
||||
|
||||
|
||||
|