Relay Station KW1FOX-2 #6

Open
Kenwood wants to merge 28 commits from station2-cad into master
28 changed files with 325 additions and 23 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
# Python
__pycache__
Pipfile
Pipfile.lock
# CAD
*.stl

Binary file not shown.

View File

@ -1,23 +0,0 @@
from discord_webhook import DiscordWebhook
from picamera import PiCamera
from time import sleep
def get_uptime():
with open('/proc/uptime', 'r') as f:
uptime_seconds = float(f.readline().split()[0])
return uptime_seconds
webhookURL = "https://discord.com/api/webhooks/856609966404534272/TR9tnLq2sIGZoOeADNswmGRNlzBcqM5aKihfU6snVTP9WhSSoVVvi7nT6i-ZfZS7Hcqm"
webhook = DiscordWebhook(url=webhookURL, content="Uptime: " + str( round( ((get_uptime() / 60) / 60 ), 2 )) + " hours")
camera = PiCamera()
sleep(3) # let iso settle out
camera.capture('still.jpg')
with open("still.jpg", "rb") as f:
webhook.add_file(file=f.read(), filename='still.jpg')
response = webhook.execute() # Hit send

Binary file not shown.

View File

@ -0,0 +1,22 @@
Setting up getty override
=========================
```console
systemctl edit getty@tty1.service
```
add
```
[Service]
ExecStart=
ExecStart=-/opt/lewis-crawler/companion_software/dashboard/entrypoint.sh
StandardInput=tty
StandardOutput=tty
```
then
```
systemctl daemon-reload; systemctl restart getty@tty1.service
```

View File

@ -0,0 +1,9 @@
#!/bin/bash
cd /opt/lewis-crawler/companion_software
git pull
pipenv install -r requirements.txt
pipenv run python -m houston -v

View File

@ -0,0 +1,43 @@
# Lewis Crawler
# 2021 - 2022
# Kitsune Scientific
import logging
import argparse
import verboselogs
import coloredlogs
from houston.houston import Houston
# Get debug args
parser = argparse.ArgumentParser()
parser.add_argument(
'-d', '--debug',
help="Print lots of debugging statements",
action="store_const", dest="loglevel", const='DEBUG',
default='WARNING',
)
parser.add_argument(
'-v', '--verbose',
help="Be verbose",
action="store_const", dest="loglevel", const='INFO',
)
args = parser.parse_args()
# Install verbose logs
verboselogs.install()
# Create a logger object.
logger = logging.getLogger('Houston_Log')
# Install colored logs
coloredlogs.install(level=args.loglevel,
logger=logger,
fmt='%(asctime)s,%(msecs)03d %(hostname)s %(levelname)s %(message)s') # noqa: E501
logger.info('Lewis Companion Software Started.')
if __name__ == '__main__':
app = Houston(logger)
app.run()

View File

@ -0,0 +1,30 @@
# Lewis Crawler
# 2021 - 2022
# Kitsune Scientific
import time
from houston.robotstreamer.streamer import RobotStreamer
class Houston:
def __init__(self, logger):
# Setup logger
self.log = logger
# Setup robotstreamer
self.rs = RobotStreamer(self.log)
# We're ready to go!
self.log.success('Ready to robot!')
def run(self):
self.rs.run()
# Junk~
while True:
try:
self.log.debug('Nothing to do.')
time.sleep(1)
except KeyboardInterrupt:
break

View File

@ -0,0 +1,3 @@
# Lewis Crawler
# 2021 - 2022
# Kitsune Scientific

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -0,0 +1 @@
ffmpeg -f image2 -loop 1 -framerate 25 -video_size 1280x720 -r 25 -i Test-Pattern.jpg -vcodec libx264 -profile:v main -preset:v medium -r 30 -g 60 -keyint_min 60 -sc_threshold 0 -b:v 2500k -maxrate 2500k -bufsize 2500k -sws_flags lanczos+accurate_rnd -acodec aac -b:a 96k -ar 48000 -ac 2 -f flv -maxrate 55k "rtmp://rtmp.robotstreamer.com/live/4619?key=jEquBubjizYDMQNe8nKjLdu88iqFpNe3sVQmGRJ2tzbxd4QJrkSSEZBQhi9UTL3k"

View File

@ -0,0 +1,30 @@
# Lewis Crawler
# 2021 - 2022
# Kitsune Scientific
import ffmpeg
class RobotStreamer:
def __init__(self, logger):
self.log = logger
def run(self):
self.log.debug('Running RobotStreamer')
stream = ffmpeg.input(
'houston/robotstreamer/resources/Test-Pattern.jpg',
f='image2',
loop='1',
framerate=25,
video_size='1280x720')
stream = ffmpeg.output(
stream,
'http://robotstreamer.com/<secret>/1280/720',
f='mpegts',
bf=0,
muxdelay=0.001,
codec='mpeg1video')
ffmpeg.run(stream)

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,79 @@
import time
from PIL import Image, ImageDraw, ImageFont
def testScreen(
x=1280, y=720,
image=None,
stripeList=["lightgrey",
"yellow",
"cyan",
"lightgreen",
"magenta",
"red",
"blue"]):
if image is None:
image = Image.new("RGB", (x, y))
draw = ImageDraw.Draw(image)
for i, stripe in enumerate(stripeList):
draw.rectangle((
(x/len(stripeList)) * i, 0,
(x/len(stripeList)) * (i + 1), x),
fill=stripe)
draw.rectangle((
0, y - (y/3),
x, y),
fill="black")
for i, stripe in enumerate(stripeList):
if i % 2 != 0:
_fill = "black"
else:
_fill = stripeList[len(stripeList) - i - 1]
draw.rectangle((
(x/len(stripeList)) * i, y - (y/3.1),
(x/len(stripeList)) * (i + 1), y - (y/4.9)),
fill=_fill)
draw.rectangle((
(x/(len(stripeList)/4)), y - (y/5.3),
(0), y),
fill="darkblue")
draw.rectangle((
(x/(len(stripeList)/2)), y - (y/5.3),
(x/(len(stripeList)/1)), y),
fill="white")
return image
def drawText(image):
# get a font
fnt = ImageFont.truetype("FreeMono.ttf", 50)
# get a drawing context
d = ImageDraw.Draw(image)
# draw multiline text
d.multiline_text((10, 10), str(time.time()), font=fnt, fill=(0, 0, 0))
return image
if __name__ == '__main__':
blank_screen = testScreen()
while True:
annotated_image = drawText(blank_screen.copy())
annotated_image.save('Test-Pattern.png')
time.sleep(2)
# testScreen().save('Test-Pattern.png')

View File

@ -0,0 +1 @@
ffmpeg -re -f image2 -loop 1 -framerate 25 -video_size 1280x720 -r 25 -i Test-Pattern.png -c:v libx264 -b:v 1M -g 50 -bf 0 -muxdelay 0.001 -f flv "rtmp://rtmp.robotstreamer.com/live/4619?key=jEquBubjizYDMQNe8nKjLdu88iqFpNe3sVQmGRJ2tzbxd4QJrkSSEZBQhi9UTL3k"

View File

@ -0,0 +1,3 @@
coloredlogs
verboselogs
ffmpeg-python

View File

@ -0,0 +1,14 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
picamera = "*"
PySSTV = "*"
pyotp = "*"
[dev-packages]
[requires]
python_version = "3.9"

View File

@ -0,0 +1,88 @@
{
"_meta": {
"hash": {
"sha256": "bd19925493e125dc5aa15b339778c61c21e0f1a5574097d1721abf99245fa605"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"picamera": {
"hashes": [
"sha256:890815aa01e4d855a6a95dd3ad0953b872a6b954982106407df0c5a31a163e50"
],
"index": "pypi",
"version": "==1.13"
},
"pillow": {
"hashes": [
"sha256:0b2efa07f69dc395d95bb9ef3299f4ca29bcb2157dc615bae0b42c3c20668ffc",
"sha256:114f816e4f73f9ec06997b2fde81a92cbf0777c9e8f462005550eed6bae57e63",
"sha256:147bd9e71fb9dcf08357b4d530b5167941e222a6fd21f869c7911bac40b9994d",
"sha256:15a2808e269a1cf2131930183dcc0419bc77bb73eb54285dde2706ac9939fa8e",
"sha256:196560dba4da7a72c5e7085fccc5938ab4075fd37fe8b5468869724109812edd",
"sha256:1c03e24be975e2afe70dfc5da6f187eea0b49a68bb2b69db0f30a61b7031cee4",
"sha256:1fd5066cd343b5db88c048d971994e56b296868766e461b82fa4e22498f34d77",
"sha256:29c9569049d04aaacd690573a0398dbd8e0bf0255684fee512b413c2142ab723",
"sha256:2b6dfa068a8b6137da34a4936f5a816aba0ecc967af2feeb32c4393ddd671cba",
"sha256:2cac53839bfc5cece8fdbe7f084d5e3ee61e1303cccc86511d351adcb9e2c792",
"sha256:2ee77c14a0299d0541d26f3d8500bb57e081233e3fa915fa35abd02c51fa7fae",
"sha256:37730f6e68bdc6a3f02d2079c34c532330d206429f3cee651aab6b66839a9f0e",
"sha256:3f08bd8d785204149b5b33e3b5f0ebbfe2190ea58d1a051c578e29e39bfd2367",
"sha256:479ab11cbd69612acefa8286481f65c5dece2002ffaa4f9db62682379ca3bb77",
"sha256:4bc3c7ef940eeb200ca65bd83005eb3aae8083d47e8fcbf5f0943baa50726856",
"sha256:660a87085925c61a0dcc80efb967512ac34dbb256ff7dd2b9b4ee8dbdab58cf4",
"sha256:67b3666b544b953a2777cb3f5a922e991be73ab32635666ee72e05876b8a92de",
"sha256:70af7d222df0ff81a2da601fab42decb009dc721545ed78549cb96e3a1c5f0c8",
"sha256:75e09042a3b39e0ea61ce37e941221313d51a9c26b8e54e12b3ececccb71718a",
"sha256:8960a8a9f4598974e4c2aeb1bff9bdd5db03ee65fd1fce8adf3223721aa2a636",
"sha256:9364c81b252d8348e9cc0cb63e856b8f7c1b340caba6ee7a7a65c968312f7dab",
"sha256:969cc558cca859cadf24f890fc009e1bce7d7d0386ba7c0478641a60199adf79",
"sha256:9a211b663cf2314edbdb4cf897beeb5c9ee3810d1d53f0e423f06d6ebbf9cd5d",
"sha256:a17ca41f45cf78c2216ebfab03add7cc350c305c38ff34ef4eef66b7d76c5229",
"sha256:a2f381932dca2cf775811a008aa3027671ace723b7a38838045b1aee8669fdcf",
"sha256:a4eef1ff2d62676deabf076f963eda4da34b51bc0517c70239fafed1d5b51500",
"sha256:c088a000dfdd88c184cc7271bfac8c5b82d9efa8637cd2b68183771e3cf56f04",
"sha256:c0e0550a404c69aab1e04ae89cca3e2a042b56ab043f7f729d984bf73ed2a093",
"sha256:c11003197f908878164f0e6da15fce22373ac3fc320cda8c9d16e6bba105b844",
"sha256:c2a5ff58751670292b406b9f06e07ed1446a4b13ffced6b6cab75b857485cbc8",
"sha256:c35d09db702f4185ba22bb33ef1751ad49c266534339a5cebeb5159d364f6f82",
"sha256:c379425c2707078dfb6bfad2430728831d399dc95a7deeb92015eb4c92345eaf",
"sha256:cc866706d56bd3a7dbf8bac8660c6f6462f2f2b8a49add2ba617bc0c54473d83",
"sha256:d0da39795049a9afcaadec532e7b669b5ebbb2a9134576ebcc15dd5bdae33cc0",
"sha256:f156d6ecfc747ee111c167f8faf5f4953761b5e66e91a4e6767e548d0f80129c",
"sha256:f4ebde71785f8bceb39dcd1e7f06bcc5d5c3cf48b9f69ab52636309387b097c8",
"sha256:fc214a6b75d2e0ea7745488da7da3c381f41790812988c7a92345978414fad37",
"sha256:fd7eef578f5b2200d066db1b50c4aa66410786201669fb76d5238b007918fb24",
"sha256:ff04c373477723430dce2e9d024c708a047d44cf17166bf16e604b379bf0ca14"
],
"markers": "python_version >= '3.6'",
"version": "==8.3.1"
},
"pyotp": {
"hashes": [
"sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28",
"sha256:d28ddfd40e0c1b6a6b9da961c7d47a10261fb58f378cb00f05ce88b26df9c432"
],
"index": "pypi",
"version": "==2.6.0"
},
"pysstv": {
"hashes": [
"sha256:91f85096591606e774811de8940aef57f30e10cbf81387064f8a686cff0ac3fa"
],
"index": "pypi",
"version": "==0.5.2"
}
},
"develop": {}
}