initial import

This commit is contained in:
James Andariese 2023-07-24 15:33:13 -05:00
parent c28dea17f1
commit 5e4f375f71
8 changed files with 172 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
test.env
*~
\#*#
.*
!.gitignore

14
Dockerfile Normal file
View 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
View File

@ -0,0 +1,4 @@
#!/bin/sh
docker build -t jamesandariese/vncmqtt:latest .
docker push jamesandariese/vncmqtt:latest

110
grab.py Normal file
View 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
View 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
View 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
View 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

4
test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
bash build.sh
docker run --rm -ti --name vncmqtt-test --env-file test.env jamesandariese/vncmqtt:latest