26 Commits

Author SHA1 Message Date
b75e4b270b Basically a stash... 2021-12-11 23:00:00 -05:00
a054e368cb Bump holes 2021-11-29 00:46:19 -05:00
db1a261012 Create bottom layer for station2 stack 2021-11-28 23:27:16 -05:00
7b318831f2 Move filesystem 2021-11-28 23:06:16 -05:00
48c532a81c Add test-pattern 2021-11-28 16:42:12 -05:00
c302674958 Attempt stream! 2021-11-27 21:49:48 -05:00
c2df56e15e Add magic debug values via cli 2021-11-27 21:32:52 -05:00
93fd03e717 Implement fixes suggested by jinsun on irc 2021-11-27 21:28:07 -05:00
3682fc1448 Boilerplate RS code 2021-11-27 21:13:20 -05:00
f67379f85d Final bleh 2021-11-27 16:54:52 -05:00
ac4ff7a657 Boilerplate 2021-11-27 16:52:55 -05:00
e94f342739 Shuffle it all up 2021-11-27 16:25:55 -05:00
e421634432 Stay up to date 2021-11-27 16:03:37 -05:00
fba81ef345 Add ability to log remote 2021-11-27 16:03:20 -05:00
888ed4db9d Levels by avahai 2021-11-27 15:20:58 -05:00
e89b964d27 Who even needs a window manager anyway 2021-11-27 14:59:23 -05:00
d74b40b7e2 Use urwid over curses 2021-11-27 14:39:18 -05:00
05e5785fc0 Bump entrypoint 2021-11-27 14:28:58 -05:00
716f01a5be Add readme: 2021-11-27 14:23:02 -05:00
5fad6f294c ignore gross 2021-11-27 14:21:09 -05:00
9a771e8cd4 Create all dashboard code 2021-11-27 14:20:22 -05:00
8a54cedb5b Spits out epoch time now, lol 2021-08-21 16:39:56 -04:00
8e3b3abe8a This testscreen generator works 2021-08-21 16:21:55 -04:00
b50cfeaac8 Upgrade to fancy color changing test pattern while remote 2021-08-20 14:30:02 -04:00
8ac68b6ab0 this color method works fine! 2021-08-20 12:30:03 -04:00
502822a7a1 include image 2021-08-20 11:57:03 -04:00
26 changed files with 222 additions and 132 deletions

2
.gitignore vendored
View File

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

Binary file not shown.

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

@@ -1,6 +0,0 @@
import json
import robot_util
url = '%s/v1/get_endpoint/jsmpeg_video_capture/%s' % ('https://api.robotstreamer.com', '4618')
response = robot_util.getWithRetry(url)
print(json.loads(response))

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

@@ -1,126 +0,0 @@
import os
import time
import traceback
import ssl
import urllib.request
import getpass
import json
import _thread
ConfigFilename = "/home/pi/config_" + getpass.getuser() + ".json" #this is never used
KeepAlivePeriod = 6
def times(lst, number):
return [x*number for x in lst]
def getWithRetry(url, secure=True):
for retryNumber in range(2000):
try:
print("GET", url)
if secure:
object = urllib.request.urlopen(url)
else:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
object = urllib.request.urlopen(url, context=ctx)
break
except:
print("could not open url", url)
traceback.print_exc()
time.sleep(2)
data = object.read()
encoding = object.info().get_content_charset('utf-8')
return data.decode(encoding)
def getNoRetry(url, secure=True):
#socket test has retry
try:
print("GET", url)
if secure:
object = urllib.request.urlopen(url)
else:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
object = urllib.request.urlopen(url, context=ctx)
except:
print("could not open url", url)
return
data = object.read()
encoding = object.info().get_content_charset('utf-8')
return data.decode(encoding)
def sendSerialCommand(ser, command):
print(ser.name) # check which port was really used
ser.nonblocking()
# loop to collect input
#s = "f"
#print "string:", s
print(str(command.lower()))
ser.write(command.lower() + "\r\n") # write a string
#ser.write(s)
ser.flush()
#while ser.in_waiting > 0:
# print "read:", ser.read()
#ser.close()
def makePOST(url, data):
params = json.dumps(data).encode('utf8')
req = urllib.request.Request(url,
data=params,
headers={'content-type': 'application/json'})
response = urllib.request.urlopen(req)
return response
def sendCameraAliveMessage(apiServer, cameraID, streamKey):
print("sending camera alive message")
url = '%s/v1/set_camera_status' % (apiServer)
print("url", url)
try:
response = makePOST(url, {'camera_id': cameraID,
'camera_status': 'online',
'stream_key': streamKey,
'type': 'robot_git'})
#todo:send unified stream key here
except:
print("could not make post to", url)
def aplayFile(filename):
for hardwareNumber in (2, 0, 1):
_thread.start_new_thread(os.system, ('aplay -D plughw:%d,0 %s' % (hardwareNumber, filename),))
def handleSoundCommand(command, keyPosition):
print("command:", command, "key position:", keyPosition)
if len(command) >= 6:
if command[0:5] == "SOUND" and keyPosition == "down":
number = int(command[5:])
aplayFile('/home/pi/sound/SOUND%d.WAV' % number)

View File

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