initial import
This commit is contained in:
parent
c28dea17f1
commit
5e4f375f71
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
test.env
|
||||||
|
*~
|
||||||
|
\#*#
|
||||||
|
.*
|
||||||
|
!.gitignore
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk add python3 py3-pip curl mosquitto-clients
|
||||||
|
|
||||||
|
COPY requirements.txt /requirements.txt
|
||||||
|
RUN pip install -r /requirements.txt
|
||||||
|
COPY grab.py /grab.py
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
CMD ["python3", "/grab.py"]
|
||||||
|
|
||||||
|
COPY health.sh /health.sh
|
||||||
|
HEALTHCHECK CMD /health.sh
|
4
build.sh
Executable file
4
build.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
docker build -t jamesandariese/vncmqtt:latest .
|
||||||
|
docker push jamesandariese/vncmqtt:latest
|
110
grab.py
Normal file
110
grab.py
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
from vncdotool import api
|
||||||
|
from twisted.internet import reactor
|
||||||
|
import paho.mqtt.client as paho
|
||||||
|
|
||||||
|
# LOGGING
|
||||||
|
|
||||||
|
# setup logging to console
|
||||||
|
class SkipLevelsFilter(logging.Filter):
|
||||||
|
def __init__(self, skip_levels=[]):
|
||||||
|
self.skip_levels = skip_levels
|
||||||
|
|
||||||
|
def filter(self, rec):
|
||||||
|
return rec.levelno not in self.skip_levels
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('keywords_pipeline')
|
||||||
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
|
# stderr for >=ERROR
|
||||||
|
stderr_handler = logging.StreamHandler(sys.stderr)
|
||||||
|
stderr_handler.setLevel(logging.ERROR)
|
||||||
|
stderr_handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
# stdout for everything but ERROR.
|
||||||
|
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||||
|
stdout_handler.addFilter(SkipLevelsFilter([logging.ERROR]))
|
||||||
|
stdout_handler.setLevel(logging.DEBUG)
|
||||||
|
stdout_handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
# attach the handlers and set the default level to DEBUG for the remainder of the logger setup
|
||||||
|
logger.addHandler(stdout_handler)
|
||||||
|
logger.addHandler(stderr_handler)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
# now extract the desired loglevel or use INFO if not specified, DEBUG is still the _active_ level though
|
||||||
|
# so if anything fails here, it will be logged even if it's a debug message
|
||||||
|
LOGLEVEL = os.getenv('LOGLEVEL') or "INFO"
|
||||||
|
numeric_level = getattr(logging, LOGLEVEL.upper(), None)
|
||||||
|
if not isinstance(numeric_level, int):
|
||||||
|
logger.critical('Invalid log level: %s' % LOGLEVEL)
|
||||||
|
os.exit(78)
|
||||||
|
# here's the debug message which will be logged before changing the level.
|
||||||
|
logger.debug(f'setting loglevel to {LOGLEVEL}')
|
||||||
|
logger.setLevel(numeric_level)
|
||||||
|
|
||||||
|
# END LOGGING
|
||||||
|
|
||||||
|
MQTT_USER=os.environ['MQTT_USER']
|
||||||
|
MQTT_PASSWORD=os.environ['MQTT_PASSWORD']
|
||||||
|
MQTT_HOST=os.environ['MQTT_HOST']
|
||||||
|
VNC_HOST=os.environ['VNC_HOST']
|
||||||
|
VNC_PASSWORD=os.environ['VNC_PASSWORD']
|
||||||
|
MQTT_TOPIC=os.environ['MQTT_TOPIC']
|
||||||
|
DEVICE_NAME=os.environ.get('DEVICE_NAME', None)
|
||||||
|
DEVICE_ID=os.environ.get('DEVICE_ID', None)
|
||||||
|
INTERVAL=float(os.environ.get('INTERVAL', '5'))
|
||||||
|
|
||||||
|
SANITIZED_HOST=VNC_HOST.replace('.','_')
|
||||||
|
NAME=DEVICE_NAME or SANITIZED_HOST
|
||||||
|
DEVICE_ID = DEVICE_ID or SANITIZED_HOST
|
||||||
|
OBJECT_ID = base64.b32encode(hashlib.sha1(NAME.encode('utf-8')).digest()).decode('utf-8')
|
||||||
|
|
||||||
|
mqtt = paho.Client()
|
||||||
|
mqtt.username_pw_set(MQTT_USER, MQTT_PASSWORD)
|
||||||
|
mqtt.connect(MQTT_HOST)
|
||||||
|
mqtt.loop_start()
|
||||||
|
|
||||||
|
mqtt.publish(f"homeassistant/camera/{DEVICE_ID}/config", json.dumps({
|
||||||
|
"name": NAME,
|
||||||
|
"topic": MQTT_TOPIC + "/image",
|
||||||
|
"unique_id": DEVICE_ID+"-T",
|
||||||
|
"device_class": "camera",
|
||||||
|
"device": {
|
||||||
|
"identifiers": DEVICE_ID,
|
||||||
|
"manufacturer": "VNC-MQTT",
|
||||||
|
"model": "v0.1",
|
||||||
|
},
|
||||||
|
}), retain=True)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
t = time.time()
|
||||||
|
with api.connect(VNC_HOST, VNC_PASSWORD) as vnc:
|
||||||
|
logger.debug("refreshing for capture")
|
||||||
|
vnc.refreshScreen()
|
||||||
|
logger.debug("capturing")
|
||||||
|
vnc.captureScreen('capture.png')
|
||||||
|
logger.debug("publishing to mqtt")
|
||||||
|
with open('capture.png', 'rb') as f:
|
||||||
|
capture = f.read()
|
||||||
|
with open('capture.time', 'wb') as f:
|
||||||
|
pass # touch :D
|
||||||
|
|
||||||
|
p = mqtt.publish(topic=MQTT_TOPIC + "/image", payload=capture)
|
||||||
|
time_left = INTERVAL - (time.time() - t)
|
||||||
|
if time_left > 0:
|
||||||
|
logger.debug(f"sleeping for {time_left}s")
|
||||||
|
time.sleep(time_left)
|
||||||
|
else:
|
||||||
|
logger.warning(f"interval missed ({time_left}s overdue)")
|
||||||
|
|
||||||
|
mqtt.loop_end()
|
||||||
|
reactor.stop()
|
12
health.sh
Executable file
12
health.sh
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
DT=$(date +%s)
|
||||||
|
CT=$(stat -c %Z capture.time)
|
||||||
|
|
||||||
|
if [ $(( DT - CT )) -gt $INTERVAL ];then
|
||||||
|
echo bad
|
||||||
|
false
|
||||||
|
else
|
||||||
|
echo good
|
||||||
|
true
|
||||||
|
fi
|
14
requirements.txt
Normal file
14
requirements.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
attrs==23.1.0
|
||||||
|
Automat==22.10.0
|
||||||
|
constantly==15.1.0
|
||||||
|
hyperlink==21.0.0
|
||||||
|
idna==3.4
|
||||||
|
incremental==22.10.0
|
||||||
|
paho-mqtt==1.6.1
|
||||||
|
Pillow==10.0.0
|
||||||
|
pycryptodomex==3.18.0
|
||||||
|
six==1.16.0
|
||||||
|
Twisted==22.10.0
|
||||||
|
typing_extensions==4.7.1
|
||||||
|
vncdotool==1.2.0
|
||||||
|
zope.interface==6.0
|
9
test.env.sample
Normal file
9
test.env.sample
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
DEVICE_NAME="Testly Desktop"
|
||||||
|
LOGLEVEL=debug
|
||||||
|
MQTT_TOPIC=cameras/testly-desktop
|
||||||
|
MQTT_HOST=192.168.1.3
|
||||||
|
MQTT_USER=write
|
||||||
|
MQTT_PASSWORD=mqttpassword
|
||||||
|
VNC_HOST=192.168.1.185
|
||||||
|
VNC_PASSWORD=vncpassword
|
||||||
|
INTERVAL=5
|
Loading…
Reference in New Issue
Block a user