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