Initial commit
This commit is contained in:
commit
1ce1081375
|
@ -0,0 +1,6 @@
|
||||||
|
__pycache__/
|
||||||
|
*.swp
|
||||||
|
*.tmp
|
||||||
|
garage.cfg
|
||||||
|
www/*
|
||||||
|
!www/.gitkeep
|
|
@ -0,0 +1,47 @@
|
||||||
|
# garage
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
```
|
||||||
|
sudo raspi-config nonint do_spi 0
|
||||||
|
sudo apt install python3-pip python3-dev python3-spidev
|
||||||
|
sudo pip3 install unicornhathd
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
```
|
||||||
|
cp garage.sample.cfg garage.cfg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
```
|
||||||
|
sudo ./install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
By default output will be in `/var/log/syslog`.
|
||||||
|
A separate log file can be used by creating `/etc/rsyslog.d/30-garage.conf` containing:
|
||||||
|
```
|
||||||
|
if $programname == 'garage' then /var/log/garage.log
|
||||||
|
& stop
|
||||||
|
```
|
||||||
|
and then restart the rsyslog service:
|
||||||
|
```
|
||||||
|
sudo systemctl restart rsyslog
|
||||||
|
```
|
||||||
|
This log file can be rotated by creating `/etc/logrotate.d/garage` containing:
|
||||||
|
```
|
||||||
|
/var/log/garage.log
|
||||||
|
{
|
||||||
|
rotate 14
|
||||||
|
daily
|
||||||
|
create
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
postrotate
|
||||||
|
/usr/lib/rsyslog/rsyslog-rotate
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,82 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from configparser import ConfigParser
|
||||||
|
from gpio import Button
|
||||||
|
from signal import pause
|
||||||
|
from signal import signal
|
||||||
|
from signal import SIGTERM
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
|
state = {"east-door": "opened", "west-door": "opened"}
|
||||||
|
threadLock = Lock()
|
||||||
|
stateFile = 'www/garage.json'
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
signal(SIGTERM, cleanExit())
|
||||||
|
config = ConfigParser()
|
||||||
|
config.read('garage.cfg')
|
||||||
|
eastPin = config['garage'].getint('east-pin')
|
||||||
|
westPin = config['garage'].getint('west-pin')
|
||||||
|
# eastUri = config['push'].getint('east-uri')
|
||||||
|
# westUri = config['push'].getint('west-uri')
|
||||||
|
|
||||||
|
persistState()
|
||||||
|
|
||||||
|
eastButton = Button(eastPin)
|
||||||
|
westButton = Button(westPin)
|
||||||
|
|
||||||
|
pause()
|
||||||
|
|
||||||
|
|
||||||
|
def eastDoorOpened():
|
||||||
|
try:
|
||||||
|
threadLock.aquire()
|
||||||
|
state["east-door"] = "opened"
|
||||||
|
persistState()
|
||||||
|
finally:
|
||||||
|
threadLock.release()
|
||||||
|
|
||||||
|
|
||||||
|
def eastDoorClosed():
|
||||||
|
try:
|
||||||
|
threadLock.aquire()
|
||||||
|
state["east-door"] = "closed"
|
||||||
|
persistState()
|
||||||
|
finally:
|
||||||
|
threadLock.release()
|
||||||
|
|
||||||
|
|
||||||
|
def westDoorOpened():
|
||||||
|
try:
|
||||||
|
threadLock.aquire()
|
||||||
|
state["west-door"] = "opened"
|
||||||
|
persistState()
|
||||||
|
finally:
|
||||||
|
threadLock.release()
|
||||||
|
|
||||||
|
|
||||||
|
def westDoorClosed():
|
||||||
|
try:
|
||||||
|
threadLock.aquire()
|
||||||
|
state["west-door"] = "closed"
|
||||||
|
persistState()
|
||||||
|
finally:
|
||||||
|
threadLock.release()
|
||||||
|
|
||||||
|
|
||||||
|
def persistState():
|
||||||
|
with open(stateFile, 'w') as file:
|
||||||
|
json.dump(state, file)
|
||||||
|
|
||||||
|
|
||||||
|
def cleanExit():
|
||||||
|
def _exit_(signum, frame):
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
return _exit_
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,7 @@
|
||||||
|
[garage]
|
||||||
|
east-pin=1
|
||||||
|
west-pin=1
|
||||||
|
|
||||||
|
[push]
|
||||||
|
east-uri=uri
|
||||||
|
west-uri=uri
|
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Garage
|
||||||
|
After=multi.user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
KillMode=mixed
|
||||||
|
WorkingDirectory=$workingDirectory
|
||||||
|
ExecStart=$execStart
|
||||||
|
Restart=on-failure
|
||||||
|
SyslogIdentifier=garage
|
||||||
|
User=$user
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,36 @@
|
||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from string import Template
|
||||||
|
from subprocess import check_call
|
||||||
|
from subprocess import check_output
|
||||||
|
|
||||||
|
EXEC = 'garage.py'
|
||||||
|
SERVICE = 'garage.service'
|
||||||
|
SYSTEM_DIR = '/etc/systemd/system'
|
||||||
|
|
||||||
|
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
SERVICE_TEMPLATE = os.path.join(CURRENT_DIR, SERVICE)
|
||||||
|
SERVICE_FILE = os.path.join(SYSTEM_DIR, SERVICE)
|
||||||
|
PYTHON = sys.executable
|
||||||
|
EXEC_START = f'{PYTHON} {EXEC}'
|
||||||
|
USER = check_output(['logname']).decode('utf-8').strip()
|
||||||
|
|
||||||
|
with open(SERVICE_TEMPLATE) as f:
|
||||||
|
serviceTemplate = Template(f.read())
|
||||||
|
|
||||||
|
serviceFile = serviceTemplate.substitute(
|
||||||
|
workingDirectory=CURRENT_DIR,
|
||||||
|
execStart=EXEC_START,
|
||||||
|
user=USER
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(SERVICE_FILE, 'w') as f:
|
||||||
|
f.write(serviceFile)
|
||||||
|
|
||||||
|
check_call(['systemctl', 'daemon-reload'])
|
||||||
|
check_call(['systemctl', 'enable', '--no-pager', SERVICE])
|
||||||
|
check_call(['systemctl', 'restart', '--no-pager', SERVICE])
|
||||||
|
check_call(['systemctl', 'status', '--no-pager', SERVICE])
|
Loading…
Reference in New Issue