cleanup
This commit is contained in:
@@ -1,207 +0,0 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import signal
|
||||
|
||||
import bbctrl
|
||||
import bbctrl.Cmd as Cmd
|
||||
|
||||
|
||||
class AVREmu(object):
|
||||
def __init__(self, ctrl):
|
||||
self.ctrl = ctrl
|
||||
self.log = ctrl.log.get('AVREmu')
|
||||
|
||||
self.avrOut = None
|
||||
self.avrIn = None
|
||||
self.i2cOut = None
|
||||
self.read_cb = None
|
||||
self.write_cb = None
|
||||
self.pid = None
|
||||
|
||||
|
||||
def close(self):
|
||||
# Close pipes
|
||||
def _close(fd, withHandle):
|
||||
if fd is None: return
|
||||
try:
|
||||
if withHandle: self.ctrl.ioloop.remove_handler(fd)
|
||||
except: pass
|
||||
try:
|
||||
os.close(fd)
|
||||
except: pass
|
||||
|
||||
_close(self.avrOut, True)
|
||||
_close(self.avrIn, True)
|
||||
_close(self.i2cOut, False)
|
||||
|
||||
self.avrOut, self.avrIn, self.i2cOut = None, None, None
|
||||
|
||||
# Kill process and wait for it
|
||||
if self.pid is not None:
|
||||
os.kill(self.pid, signal.SIGKILL)
|
||||
os.waitpid(self.pid, 0)
|
||||
self.pid = None
|
||||
|
||||
|
||||
def _start(self):
|
||||
try:
|
||||
self.close()
|
||||
|
||||
# Create pipes
|
||||
stdinFDs = os.pipe()
|
||||
stdoutFDs = os.pipe()
|
||||
i2cFDs = os.pipe()
|
||||
|
||||
self.pid = os.fork()
|
||||
|
||||
if not self.pid:
|
||||
# Dup child ends
|
||||
os.dup2(stdinFDs[0], 0)
|
||||
os.dup2(stdoutFDs[1], 1)
|
||||
os.dup2(i2cFDs[0], 3)
|
||||
|
||||
# Close orig fds
|
||||
os.close(stdinFDs[0])
|
||||
os.close(stdoutFDs[1])
|
||||
os.close(i2cFDs[0])
|
||||
|
||||
# Close parent ends
|
||||
os.close(stdinFDs[1])
|
||||
os.close(stdoutFDs[0])
|
||||
os.close(i2cFDs[1])
|
||||
|
||||
cmd = ['bbemu']
|
||||
if self.ctrl.args.fast_emu: cmd.append('--fast')
|
||||
|
||||
os.execvp(cmd[0], cmd)
|
||||
os._exit(1) # In case of failure
|
||||
|
||||
# Parent, close child ends
|
||||
os.close(stdinFDs[0])
|
||||
os.close(stdoutFDs[1])
|
||||
os.close(i2cFDs[0])
|
||||
|
||||
# Non-blocking IO
|
||||
os.set_blocking(stdinFDs[1], False)
|
||||
os.set_blocking(stdoutFDs[0], False)
|
||||
os.set_blocking(i2cFDs[1], False)
|
||||
|
||||
self.avrOut = stdinFDs[1]
|
||||
self.avrIn = stdoutFDs[0]
|
||||
self.i2cOut = i2cFDs[1]
|
||||
|
||||
ioloop = self.ctrl.ioloop
|
||||
ioloop.add_handler(self.avrOut, self._avr_write_handler,
|
||||
ioloop.WRITE | ioloop.ERROR)
|
||||
ioloop.add_handler(self.avrIn, self._avr_read_handler,
|
||||
ioloop.READ | ioloop.ERROR)
|
||||
|
||||
self.write_enabled = True
|
||||
|
||||
except Exception:
|
||||
self.close()
|
||||
self.log.exception('Internal error: Failed to start bbemu')
|
||||
|
||||
|
||||
def set_handlers(self, read_cb, write_cb):
|
||||
if self.read_cb is not None or self.write_cb is not None:
|
||||
raise Exception('AVR handler already set')
|
||||
|
||||
self.read_cb = read_cb
|
||||
self.write_cb = write_cb
|
||||
self._start()
|
||||
|
||||
|
||||
def enable_write(self, enable):
|
||||
if self.avrOut is None: return
|
||||
|
||||
flags = self.ctrl.ioloop.WRITE if enable else 0
|
||||
self.ctrl.ioloop.update_handler(self.avrOut, flags)
|
||||
self.write_enabled = enable
|
||||
|
||||
|
||||
def _avr_write(self, data):
|
||||
try:
|
||||
length = os.write(self.avrOut, data)
|
||||
self.continue_write = length and length == len(data)
|
||||
return length
|
||||
|
||||
except BlockingIOError: pass
|
||||
except BrokenPipeError: pass
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def _avr_write_handler(self, fd, events):
|
||||
if self.avrOut is None: return
|
||||
|
||||
if events & self.ctrl.ioloop.ERROR:
|
||||
self._start()
|
||||
return
|
||||
|
||||
try:
|
||||
while True:
|
||||
self.continue_write = False
|
||||
self.write_cb(self._avr_write)
|
||||
if not self.continue_write: break
|
||||
|
||||
except Exception as e:
|
||||
self.log.warning('AVR write handler error: %s',
|
||||
traceback.format_exc())
|
||||
|
||||
|
||||
def _avr_read_handler(self, fd, events):
|
||||
if self.avrIn is None: return
|
||||
|
||||
if events & self.ctrl.ioloop.ERROR:
|
||||
self._start()
|
||||
return
|
||||
|
||||
try:
|
||||
data = os.read(self.avrIn, 4096)
|
||||
if data is not None: self.read_cb(data)
|
||||
|
||||
except Exception as e:
|
||||
self.log.warning('AVR read handler error: %s %s' %
|
||||
(data, traceback.format_exc()))
|
||||
|
||||
|
||||
def i2c_command(self, cmd, byte = None, word = None, block = None):
|
||||
if byte is not None: data = chr(byte)
|
||||
elif word is not None: data = word
|
||||
elif block is not None: data = block
|
||||
else: data = ''
|
||||
|
||||
try:
|
||||
if self.i2cOut is not None:
|
||||
os.write(self.i2cOut, bytes(cmd + data + '\n', 'utf-8'))
|
||||
|
||||
except BrokenPipeError: pass
|
||||
@@ -25,10 +25,7 @@ class Ctrl(object):
|
||||
self.log.get('Ctrl').info('Starting %s' % self.id)
|
||||
|
||||
try:
|
||||
if args.demo:
|
||||
self.avr = bbctrl.AVREmu(self)
|
||||
else:
|
||||
self.avr = bbctrl.AVR(self)
|
||||
self.avr = bbctrl.AVR(self)
|
||||
|
||||
self.i2c = bbctrl.I2C(args.i2c_port, args.demo)
|
||||
self.mach = bbctrl.Mach(self, self.avr)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -123,8 +123,6 @@ class State(object):
|
||||
|
||||
if not os.path.exists(upload):
|
||||
os.mkdir(upload)
|
||||
from shutil import copy
|
||||
copy(bbctrl.get_resource('http/buildbotics.nc'), upload)
|
||||
|
||||
for path in os.listdir(upload):
|
||||
if os.path.isfile(upload + '/' + path):
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import tornado
|
||||
@@ -53,13 +25,11 @@ from bbctrl.Comm import Comm
|
||||
from bbctrl.CommandQueue import CommandQueue
|
||||
from bbctrl.Camera import Camera, VideoHandler
|
||||
from bbctrl.AVR import AVR
|
||||
from bbctrl.AVREmu import AVREmu
|
||||
from bbctrl.IOLoop import IOLoop
|
||||
from bbctrl.MonitorTemp import MonitorTemp
|
||||
import bbctrl.Cmd as Cmd
|
||||
import bbctrl.v4l2 as v4l2
|
||||
import bbctrl.Log as log
|
||||
import bbctrl.ObjGraph as ObjGraph
|
||||
|
||||
|
||||
ctrl = None
|
||||
@@ -69,7 +39,7 @@ def get_resource(path):
|
||||
return resource_filename(Requirement.parse('bbctrl'), 'bbctrl/' + path)
|
||||
|
||||
|
||||
def on_exit(sig = 0, func = None):
|
||||
def on_exit(sig=0, func=None):
|
||||
global ctrl
|
||||
|
||||
print('Exit handler triggered: signal = %d', sig)
|
||||
@@ -85,76 +55,46 @@ def time_str():
|
||||
return datetime.datetime.now().strftime('%Y%m%d-%H:%M:%S')
|
||||
|
||||
|
||||
|
||||
class Debugger:
|
||||
def __init__(self, ioloop, freq = 60 * 15, depth = 100):
|
||||
self.ioloop = ioloop
|
||||
self.freq = freq
|
||||
self.depth = depth
|
||||
self._callback()
|
||||
|
||||
|
||||
def _callback(self):
|
||||
with open('bbctrl-debug-%s.log' % time_str(), 'w') as log:
|
||||
def line(name):
|
||||
log.write('==== ' + name + ' ' + '=' * (74 - len(name)) + '\n')
|
||||
|
||||
line('Common')
|
||||
ObjGraph.show_most_common_types(limit = self.depth, file = log)
|
||||
|
||||
log.write('\n')
|
||||
line('Growth')
|
||||
ObjGraph.show_growth(limit = self.depth, file = log)
|
||||
|
||||
log.write('\n')
|
||||
line('New IDs')
|
||||
ObjGraph.get_new_ids(limit = self.depth, file = log)
|
||||
|
||||
log.flush()
|
||||
self.ioloop.call_later(self.freq, self._callback)
|
||||
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Buildbotics Machine Controller')
|
||||
description='Buildbotics Machine Controller')
|
||||
|
||||
parser.add_argument('-p', '--port', default = 80,
|
||||
type = int, help = 'HTTP port')
|
||||
parser.add_argument('-a', '--addr', metavar = 'IP', default = '0.0.0.0',
|
||||
help = 'HTTP address to bind')
|
||||
parser.add_argument('-s', '--serial', default = '/dev/ttyAMA0',
|
||||
help = 'Serial device')
|
||||
parser.add_argument('-b', '--baud', default = 230400, type = int,
|
||||
help = 'Serial baud rate')
|
||||
parser.add_argument('--i2c-port', default = 1, type = int,
|
||||
help = 'I2C port')
|
||||
parser.add_argument('--avr-addr', default = 0x2b, type = int,
|
||||
help = 'AVR I2C address')
|
||||
parser.add_argument('--pwr-addr', default = 0x60, type = int,
|
||||
help = 'Power AVR I2C address')
|
||||
parser.add_argument('-v', '--verbose', action = 'store_true',
|
||||
help = 'Verbose output')
|
||||
parser.add_argument('-l', '--log', metavar = "FILE",
|
||||
help = 'Set a log file')
|
||||
parser.add_argument('--disable-camera', action = 'store_true',
|
||||
help = 'Disable the camera')
|
||||
parser.add_argument('--width', default = 640, type = int,
|
||||
help = 'Camera width')
|
||||
parser.add_argument('--height', default = 480, type = int,
|
||||
help = 'Camera height')
|
||||
parser.add_argument('--fps', default = 15, type = int,
|
||||
help = 'Camera frames per second')
|
||||
parser.add_argument('--camera-clients', default = 4,
|
||||
help = 'Maximum simultaneous camera clients')
|
||||
parser.add_argument('--demo', action = 'store_true',
|
||||
help = 'Enter demo mode')
|
||||
parser.add_argument('--debug', default = 0, type = int,
|
||||
help = 'Enable debug mode and set frequency in seconds')
|
||||
parser.add_argument('--fast-emu', action = 'store_true',
|
||||
help = 'Enter demo mode')
|
||||
parser.add_argument('--client-timeout', default = 5 * 60, type = int,
|
||||
help = 'Demo client timeout in seconds')
|
||||
parser.add_argument('-p', '--port', default=80,
|
||||
type=int, help='HTTP port')
|
||||
parser.add_argument('-a', '--addr', metavar='IP', default='0.0.0.0',
|
||||
help='HTTP address to bind')
|
||||
parser.add_argument('-s', '--serial', default='/dev/ttyAMA0',
|
||||
help='Serial device')
|
||||
parser.add_argument('-b', '--baud', default=230400, type=int,
|
||||
help='Serial baud rate')
|
||||
parser.add_argument('--i2c-port', default=1, type=int,
|
||||
help='I2C port')
|
||||
parser.add_argument('--avr-addr', default=0x2b, type=int,
|
||||
help='AVR I2C address')
|
||||
parser.add_argument('--pwr-addr', default=0x60, type=int,
|
||||
help='Power AVR I2C address')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Verbose output')
|
||||
parser.add_argument('-l', '--log', metavar="FILE",
|
||||
help='Set a log file')
|
||||
parser.add_argument('--disable-camera', action='store_true',
|
||||
help='Disable the camera')
|
||||
parser.add_argument('--width', default=640, type=int,
|
||||
help='Camera width')
|
||||
parser.add_argument('--height', default=480, type=int,
|
||||
help='Camera height')
|
||||
parser.add_argument('--fps', default=15, type=int,
|
||||
help='Camera frames per second')
|
||||
parser.add_argument('--camera-clients', default=4,
|
||||
help='Maximum simultaneous camera clients')
|
||||
parser.add_argument('--demo', action='store_true',
|
||||
help='Enter demo mode')
|
||||
parser.add_argument('--debug', default=0, type=int,
|
||||
help='Enable debug mode and set frequency in seconds')
|
||||
parser.add_argument('--fast-emu', action='store_true',
|
||||
help='Enter demo mode')
|
||||
parser.add_argument('--client-timeout', default=5 * 60, type=int,
|
||||
help='Demo client timeout in seconds')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -170,16 +110,15 @@ def run():
|
||||
# Create ioloop
|
||||
ioloop = tornado.ioloop.IOLoop.current()
|
||||
|
||||
# Set ObjGraph signal handler
|
||||
if args.debug: Debugger(ioloop, args.debug)
|
||||
|
||||
# Start server
|
||||
web = Web(args, ioloop)
|
||||
|
||||
try:
|
||||
ioloop.start()
|
||||
|
||||
except KeyboardInterrupt: on_exit()
|
||||
except KeyboardInterrupt:
|
||||
on_exit()
|
||||
|
||||
|
||||
if __name__ == '__main__': run()
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
Reference in New Issue
Block a user