Initial commit

This commit is contained in:
Sillyfrog 2018-06-04 08:27:11 +10:00
parent 15d8d45d27
commit c84da24975
8 changed files with 272 additions and 1 deletions

94
Dockerfile Normal file
View File

@ -0,0 +1,94 @@
FROM python:2.7
EXPOSE 8080
RUN apt-get update && \
apt-get install -y cmake libjpeg62-turbo-dev g++ wget unzip psmisc
RUN cd /tmp/ && \
wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip && \
unzip master
RUN cd /tmp/mjpg-streamer-master/mjpg-streamer-experimental/ && \
make && \
make install
EXPOSE 5000
ENV CURA_VERSION=15.04.6
ARG tag=master
WORKDIR /opt/octoprint
#install ffmpeg
RUN cd /tmp \
&& wget -O ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-32bit-static.tar.xz \
&& mkdir -p /opt/ffmpeg \
&& tar xvf ffmpeg.tar.xz -C /opt/ffmpeg --strip-components=1 \
&& rm -Rf /tmp/*
#install Cura
RUN cd /tmp \
&& wget https://github.com/Ultimaker/CuraEngine/archive/${CURA_VERSION}.tar.gz \
&& tar -zxf ${CURA_VERSION}.tar.gz \
&& cd CuraEngine-${CURA_VERSION} \
&& mkdir build \
&& make \
&& mv -f ./build /opt/cura/ \
&& rm -Rf /tmp/*
#Create an octoprint user
RUN useradd -ms /bin/bash octoprint && adduser octoprint dialout
RUN chown octoprint:octoprint /opt/octoprint
USER octoprint
#This fixes issues with the volume command setting wrong permissions
RUN mkdir /home/octoprint/.octoprint
#Install Octoprint
RUN git clone --branch $tag https://github.com/foosel/OctoPrint.git /opt/octoprint \
&& virtualenv venv \
&& ./venv/bin/python setup.py install \
&& echo 2
RUN /opt/octoprint/venv/bin/python -m pip install https://github.com/FormerLurker/Octolapse/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/pablogventura/Octoprint-ETA/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/1r0b1n0/OctoPrint-Tempsgraph/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/dattas/OctoPrint-DetailedProgress/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/kennethjiang/OctoPrint-Slicer/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/marian42/octoprint-preheat/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/jneilliii/OctoPrint-TasmotaMQTT/archive/0.3.0.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/mikedmor/OctoPrint_MultiCam/archive/master.zip
# Installing from sillyfrog until the PR is merged to master
RUN /opt/octoprint/venv/bin/python -m pip install https://github.com/sillyfrog/Octoslacka/archive/master.zip && \
/opt/octoprint/venv/bin/python -m pip install https://github.com/sillyfrog/OctoPrint-MQTT/archive/devel.zip
VOLUME /home/octoprint/.octoprint
### Klipper setup ###
USER root
RUN apt-get install -y sudo
COPY klippy.sudoers /etc/sudoers.d/klippy
RUN useradd -ms /bin/bash klippy
USER octoprint
WORKDIR /home/octoprint
RUN git clone https://github.com/KevinOConnor/klipper
RUN ./klipper/scripts/install-octopi.sh
RUN cp klipper/config/printer-anet-a8-2017.cfg /home/octoprint/printer.cfg
USER root
COPY start.py /
CMD ["/start.py"]

View File

@ -1,2 +1,31 @@
# OctoPrint-Klipper-mjpg-Dockerfile
A Dockerfile for running OctoPrint Klipper and mjpg in a single container
A Dockerfile for running OctoPrint Klipper and mjpg in a single container.
My initial goal was to run these across different containers, but I couldn't get the Docker permissions to play nicely.
This is very much written for what I needed, so you'll likely need to hack this up for your setup. I've been using it for a little while now and it's going well.
Also included are some udev rules for reference that I use. These will need to be updated with your API key etc, however it makes connecting/disconnecting (power on/off) of the printer much less painful.
## Running the container
Once the container is built (the usual `docker build . -t okmd`), I use the following command to run it (again, you will need to customise for your setup, I have 3 cameras also connected):
```
docker kill octoprint2
docker rm octoprint2
docker run --name octoprint2 -d -v /etc/localtime:/etc/localtime:ro -v /home/user/Documents/octoprint-config:/home/octoprint/.octoprint \
--device /dev/ttyUSB0:/dev/ttyUSB0 \
--device /dev/video0:/dev/video0 \
--device /dev/video1:/dev/video1 \
--device /dev/video2:/dev/video2 \
-p 5000:5000 -p 8080:8080 -p 8081:8081 -p 8082:8082\
-e "MJPG=input_uvc.so -r HD -d /dev/video2" \
-e "MJPG1=input_uvc.so -r HD -d /dev/video0" -e "MJPG_PORT1=8081" \
-e "MJPG2=input_uvc.so -r HD -d /dev/video1" -e "MJPG_PORT2=8082" \
okmd
```
Your Klipper `printer.cfg` should be kept in the OctoPrint config directory (this is where it looks for it at startup).
If you have any questions, feel free to log an issue on this project, and I'll see if I can help.

1
klippy.sudoers Normal file
View File

@ -0,0 +1 @@
octoprint ALL=(ALL:ALL) NOPASSWD: ALL

57
start.py Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
import subprocess
import time
import os
import pwd
MJPG = [
"/usr/local/bin/mjpg_streamer",
"-i",
"%(input)s",
"-o",
"output_http.so -p %(port)s -w /usr/local/share/mjpg-streamer/www/",
]
MJPG_INPUT_DEFAULT = "input_uvc.so -r HD"
OCTOPRINT = ["/opt/octoprint/venv/bin/octoprint", "serve"]
def main():
mjpg_processes = []
mjpg_ports = [5000] # Reserve the OctoPrint port
for k, v in os.environ.iteritems():
if k.startswith("MJPG") and not k.startswith("MJPG_"):
v = v.strip()
port_env = "MJPG_PORT" + k[4:]
port = int(os.environ.get(port_env, 8080))
if port in mjpg_ports:
raise ValueError("Port %s from key %s already in use" % (port, port_env))
if not v:
v = MJPG_INPUT_DEFAULT
subs = {'input': v, 'port': port}
cmd = []
for part in MJPG:
cmd.append(part % subs)
print("Starting: %s" % (cmd,))
mjpg_processes.append(subprocess.Popen(cmd))
# Start klipper
klipper = subprocess.Popen(['sudo', '-u', 'octoprint', '/home/octoprint/klippy-env/bin/python', '/home/octoprint/klipper/klippy/klippy.py', '/home/octoprint/.octoprint/printer.cfg'])
os.setgid(
1000
) # Drop privileges, https://stackoverflow.com/questions/2699907/dropping-root-permissions-in-python#2699996
os.setuid(1000)
os.environ['HOME'] = '/home/octoprint'
# subprocess.Popen('env', shell=True).wait()
while 1:
Poctoprint = subprocess.Popen(OCTOPRINT)
Poctoprint.wait()
time.sleep(1)
if __name__ == '__main__':
main()

7
udev/README.md Normal file
View File

@ -0,0 +1,7 @@
# udev Rules and Commands
This directory contains the commands and rules I add to udev to make turning the printer on and off go smoothly, including re-connecting (my Docker container runs 24x7, however I turn off the printer when not in use).
The `okmd-udev.rules` file should be copied to `/etc/udev/rules.d/`, and updated to have the correct paths and device names for your environment.
The commands (`printer-*`), should also be updated to match your device names, and include your OctoPrint API key.

2
udev/okmd-udev.rules Normal file
View File

@ -0,0 +1,2 @@
ACTION=="add", KERNEL=="ttyUSB*", SUBSYSTEM=="tty", RUN+="/somewhere/printer-connected"
ACTION=="remove", KERNEL=="ttyUSB*", SUBSYSTEM=="tty", RUN+="/somewhere/printer-disconnected"

20
udev/printer-connected Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python
import time
import os
logf = open('/var/tmp/printer-connected.log', 'a')
DEVNAME = os.environ['DEVNAME']
def log(msg):
logf.write('%s\n' % (msg,))
def main():
log(time.asctime())
log(DEVNAME)
os.system('chmod a+wr %s' % (DEVNAME,))
if __name__ == '__main__':
main()

61
udev/printer-disconnected Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python
import time
import os
import requests
import sys
logf = open('/var/tmp/printer-connected.log', 'a')
DEVNAME = os.environ['DEVNAME']
RESTART_STATES = [
'Offline',
'Cancelling',
'Operational',
]
OCTOPRINT_URL = 'http://localhost:5000/'
API_KEY = 'XXX'
def log(msg):
logf.write('%s\n' % (msg,))
def currentstate():
headers = {'X-Api-Key': API_KEY}
url = OCTOPRINT_URL + '/api/job'
r = requests.get(url, headers=headers)
return r.json()['state']
def main():
log(time.asctime())
log("Disconnecting: {}".format(DEVNAME))
state = currentstate()
if state not in RESTART_STATES and DEVNAME != '/dev/ttyUSB0':
log("Not restarting. State: {} DEVNAME: {}".format(state, DEVNAME))
# Don't reset the firmware if not in a known safe state
return
headers = {'X-Api-Key': API_KEY}
json = {
"command": "FIRMWARE_RESTART",
}
url = OCTOPRINT_URL + '/api/printer/command'
r = requests.post(
url,
json=json,
headers=headers
)
if (r.status_code == 204):
log("Disconnected OK")
sys.exit(0)
else:
log("Error disconnecting: %s" % (r,))
sys.exit(1)
if __name__ == '__main__':
main()