diff --git a/.gitignore b/.gitignore index e10fb58..3993394 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ arch/src arch/doorlockd arch/*.xz arch/BKCA.crt +gpio-wait diff --git a/Makefile b/Makefile index f666d77..de4004b 100644 --- a/Makefile +++ b/Makefile @@ -2,19 +2,21 @@ DESTDIR ?= / PREFIX ?= /usr SYSCONFDIR ?= /etc -all: +all: gpio-wait sed -i -r -e "s@(^SYSCONFDIR = ').*('$$)@\1$(SYSCONFDIR)\2@" doorlockd sed -i -r -e "s@(^PREFIX = ').*('$$)@\1$(PREFIX)\2@" doorlockd +gpio-wait: gpio-wait.c + install: mkdir -p $(DESTDIR)/$(PREFIX)/bin/ mkdir -p $(DESTDIR)/$(PREFIX)/share/ mkdir -p $(DESTDIR)/$(SYSCONFDIR)/systemd/system mkdir -p $(DESTDIR)/$(SYSCONFDIR) - install doorlockd $(DESTDIR)/$(PREFIX)/bin/ + install doorlockd gpio-wait doorstate $(DESTDIR)/$(PREFIX)/bin/ install doorlockd-passwd $(DESTDIR)/$(PREFIX)/bin/ install -m 0644 doorlockd.cfg $(DESTDIR)/$(SYSCONFDIR) - install -m 0644 doorlockd.service $(DESTDIR)/$(SYSCONFDIR)/systemd/system + install -m 0644 doorlockd.service doorstate.service $(DESTDIR)/$(SYSCONFDIR)/systemd/system cp -av share/* $(DESTDIR)/$(PREFIX)/share diff --git a/doorstate b/doorstate new file mode 100755 index 0000000..1087daa --- /dev/null +++ b/doorstate @@ -0,0 +1,23 @@ +#!/bin/bash + +GPIO=22 + +function publish { + mosquitto_pub -r -t kitchen/doorlock/frontdoor/doorstate -m "$1" +} + +if [ "$(id -u)" != "0" ]; then + echo "Please run as root!" + exit -1 +fi + +while true; do + gpio-wait /dev/gpiochip0 22 + ret=$? + + if [ $ret -eq 0 ]; then + publish "closed" + elif [ $ret -eq 1 ]; then + publish "open" + fi +done diff --git a/doorstate.service b/doorstate.service new file mode 100644 index 0000000..9d5a5bf --- /dev/null +++ b/doorstate.service @@ -0,0 +1,12 @@ +[Unit] +Description=Binary Kitchen doorstate service +After=network.target + +[Service] +User=root +Group=root +ExecStart=doorstate + +[Install] +WantedBy=multi-user.target + diff --git a/gpio-wait.c b/gpio-wait.c new file mode 100644 index 0000000..12b8f40 --- /dev/null +++ b/gpio-wait.c @@ -0,0 +1,100 @@ +/* + * Doorlockd -- Binary Kitchen's smart door opener + * + * Copyright (c) Binary Kitchen e.V., 2018 + * + * Author: Ralf Ramsauer + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the LICENSE file in the top-level directory. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, const char **argv) { + int gpiochip_fd, ret; + struct gpioevent_request req; + struct gpiohandle_data data; + struct gpioevent_data event; + + if (argc != 3) { + fprintf(stderr, "Usage: %s gpiochip pin\n", argv[0]); + return -1; + } + + gpiochip_fd = open(argv[1], 0); + if (gpiochip_fd == -1) { + perror("open"); + return -1; + } + + req.lineoffset = atoi(argv[2]); + req.handleflags = GPIOHANDLE_REQUEST_INPUT; + req.eventflags = GPIOEVENT_REQUEST_RISING_EDGE | GPIOEVENT_REQUEST_FALLING_EDGE; + req.consumer_label[0] = 0; + + ret = ioctl(gpiochip_fd, GPIO_GET_LINEEVENT_IOCTL, &req); + if (ret == -1) { + perror("ioctl"); + goto gpiochip_out; + } + + ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); + if (ret == -1) { + perror("ioctl"); + goto req_fd_out; + } + + printf("Initial Value: %u\n", data.values[0]); + +retry: + ret = read(req.fd, &event, sizeof(event)); + if (ret == -1) { + if (errno == -EAGAIN) { + printf("Nothing available, trying again\n"); + goto retry; + } + } + + if (ret != sizeof(event)) { + ret = -EIO; + goto req_fd_out; + } + + switch (event.id) { + case GPIOEVENT_EVENT_RISING_EDGE: + printf("Detected rising edge\n"); + ret = 1; + break; + case GPIOEVENT_EVENT_FALLING_EDGE: + printf("Detected falling edge\n"); + ret = 0; + break; + default: + printf("Unknown event\n"); + ret = -EIO; + + break; + } + +req_fd_out: + close(req.fd); +gpiochip_out: + close(gpiochip_fd); + + return ret; +}