From 385b87e95fb1bfc8679e5221dfe080998581467a Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Tue, 20 Dec 2016 16:35:49 -0800 Subject: [PATCH] Added console in Web, Don't fail to start when LCD is not found, Retry LCD connection, Added pyudev dep, probably others --- setup.py | 2 +- src/jade/templates/control-view.jade | 23 ++++++++++++++++++ src/js/app.js | 5 +++- src/js/control-view.js | 28 +++++++++++++++++++--- src/py/bbctrl/AVR.py | 3 ++- src/py/bbctrl/Jog.py | 2 ++ src/py/bbctrl/LCD.py | 35 ++++++++++++++++++++++++---- src/py/lcd/__init__.py | 9 ++++++- src/stylus/style.styl | 32 ++++++++++++++++++++++--- 9 files changed, 124 insertions(+), 15 deletions(-) diff --git a/setup.py b/setup.py index 0028528..b6105b3 100755 --- a/setup.py +++ b/setup.py @@ -21,6 +21,6 @@ setup( 'bbctrl = bbctrl:run' ] }, - install_requires = 'tornado sockjs-tornado pyserial smbus2'.split(), + install_requires = 'tornado sockjs-tornado pyserial pyudev smbus2'.split(), zip_safe = False, ) diff --git a/src/jade/templates/control-view.jade b/src/jade/templates/control-view.jade index 247b296..36d3e70 100644 --- a/src/jade/templates/control-view.jade +++ b/src/jade/templates/control-view.jade @@ -114,6 +114,9 @@ script#control-view-template(type="text/x-template") input#tab3(type="radio", name="tabs") label(for="tab3") Manual + input#tab4(type="radio", name="tabs") + label(for="tab4") Console + section#content1.tab-content .toolbar button.pure-button(title="Upload a new program file.", @click="open", @@ -157,3 +160,23 @@ script#control-view-template(type="text/x-template") axis-control(axes="BC", :colors="['cyan', 'purple']", :enabled="[enabled('b'), enabled('c')]", v-if="enabled('b') || enabled('c')") + + section#content4.tab-content + .toolbar + button.pure-button(title="Clear console.", @click="clear_console") + .fa.fa-trash + + table.console + tr + th Level + th Location + th Code + th Repeat + th Message + + tr(v-for="msg in console", :class="msg.level || 'info'") + td {{msg.level || 'info'}} + td {{msg.where || ''}} + td {{msg.code || '0'}} + td {{msg.repeat}} + td {{msg.msg}} diff --git a/src/js/app.js b/src/js/app.js index c676bca..55d45ed 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -82,9 +82,12 @@ module.exports = new Vue({ this.sock.onmessage = function (e) { var msg = e.data; - if (typeof msg == 'object') + if (typeof msg == 'object') { for (var key in msg) this.$set('state.' + key, msg[key]); + + if ('msg' in msg) this.$broadcast('message', msg); + } }.bind(this); this.sock.onopen = function (e) { diff --git a/src/js/control-view.js b/src/js/control-view.js index b926088..2524f78 100644 --- a/src/js/control-view.js +++ b/src/js/control-view.js @@ -3,11 +3,17 @@ var api = require('./api'); -function is_array(x) { +function _is_array(x) { return Object.prototype.toString.call(x) === '[object Array]'; } +function _msg_equal(a, b) { + return a.level == b.level && a.location == b.location && a.code == b.code && + a.msg == b.msg; +} + + module.exports = { template: '#control-view-template', props: ['config', 'state'], @@ -22,6 +28,7 @@ module.exports = { axes: 'xyzabc', gcode: '', history: '', + console: [], speed_override: 1, feed_override: 1 } @@ -40,7 +47,19 @@ module.exports = { events: { // TODO These should all be implemented via the API - jog: function (axis, move) {this.send('g91 g0' + axis + move)} + jog: function (axis, move) {this.send('g91 g0' + axis + move)}, + + + message: function (msg) { + if (this.console.length && + _msg_equal(msg, this.console[this.console.length - 1])) + this.console[this.console.length - 1].repeat++; + + else { + msg.repeat = 1; + this.console.push(msg); + } + } }, @@ -214,7 +233,10 @@ module.exports = { var data = {}; data[axis + 'pl'] = x; this.send(JSON.stringify(data)); - } + }, + + + clear_console: function () {this.console = [];} }, diff --git a/src/py/bbctrl/AVR.py b/src/py/bbctrl/AVR.py index fb6d6f2..5a534c9 100644 --- a/src/py/bbctrl/AVR.py +++ b/src/py/bbctrl/AVR.py @@ -81,7 +81,8 @@ class AVR(): def _i2c_command(self, cmd, byte = None, word = None): - if self.i2c_bus is None: return + if self.i2c_bus is None or not hasattr(self.i2c_bus, 'write_byte'): + return log.info('I2C: %d' % cmd) retry = 5 diff --git a/src/py/bbctrl/Jog.py b/src/py/bbctrl/Jog.py index f4c48a6..cb4f717 100644 --- a/src/py/bbctrl/Jog.py +++ b/src/py/bbctrl/Jog.py @@ -40,3 +40,5 @@ class Jog(inevent.JogHandler): if self.speed == 4: scale = 1.0 self.v = [x * scale for x in self.axes] + self.v[ABS_Y] = -self.v[ABS_Y] + self.v[ABS_Z] = -self.v[ABS_Z] diff --git a/src/py/bbctrl/LCD.py b/src/py/bbctrl/LCD.py index 1209e7f..9a6a037 100644 --- a/src/py/bbctrl/LCD.py +++ b/src/py/bbctrl/LCD.py @@ -1,17 +1,34 @@ import lcd import atexit +import logging + + +log = logging.getLogger('LCD') class LCD: def __init__(self, ctrl): self.ctrl = ctrl - - self.lcd = lcd.LCD(ctrl.args.lcd_port, ctrl.args.lcd_addr) + self.force = False atexit.register(self.goodbye) + self.connect() + + + def connect(self): + try: + self.lcd = None + self.lcd = lcd.LCD(self.ctrl.args.lcd_port, self.ctrl.args.lcd_addr) + self.lcd.clear() + self.lcd.display(1, 'Loading', lcd.JUSTIFY_CENTER) + self.force = True + + except IOError as e: + log.error('Connect failed, retrying: %s' % e) + self.ctrl.ioloop.call_later(1, self.connect) def update(self, msg, force = False): - def has(name): return force or name in msg + def has(name): return self.force or force or name in msg if has('x') or has('c'): v = self.ctrl.avr.vars @@ -29,7 +46,15 @@ class LCD: if has('f'): self.lcd.text('%8uF' % msg['f'], 0, 2) if has('s'): self.lcd.text('%8dS' % msg['s'], 0, 3) + self.force = False + def goodbye(self): - self.lcd.clear() - self.lcd.display(1, 'Goodbye', lcd.JUSTIFY_CENTER) + if self.lcd is None: return + + try: + self.lcd.clear() + self.lcd.display(1, 'Goodbye', lcd.JUSTIFY_CENTER) + + except IOError as e: + log.error('I2C communication failed: %s' % e) diff --git a/src/py/lcd/__init__.py b/src/py/lcd/__init__.py index b7b44ac..64648fe 100755 --- a/src/py/lcd/__init__.py +++ b/src/py/lcd/__init__.py @@ -80,7 +80,14 @@ class LCD: def reset(self): - self.clear() + time.sleep(0.050) + self.write_nibble(3 << 4) # Home + time.sleep(0.050) + self.write_nibble(3 << 4) # Home + time.sleep(0.050) + self.write_nibble(3 << 4) # Home + self.write_nibble(2 << 4) # 4-bit + self.write(LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | LCD_4_BIT_MODE) self.write(LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON) diff --git a/src/stylus/style.styl b/src/stylus/style.styl index dfd5ab0..a45dadd 100644 --- a/src/stylus/style.styl +++ b/src/stylus/style.styl @@ -285,7 +285,15 @@ body clear both > * - margin 0.5em 0 + margin 0.25em + + + .tabs + section + max-height 260px + overflow auto + padding 0 + margin 0 .gcode, .history clear both @@ -294,7 +302,7 @@ body max-width 99% min-width 99% height 200px - padding 2px + padding 0.25em white-space pre &.placeholder @@ -330,6 +338,23 @@ body > svg margin 1em + .console + width 100% + + tr + > td + margin 0 0.125em + background-color #fff + + &.error td + color red + + &.warning td + color orange + + &.debug td + color green + .tabs clear both @@ -359,7 +384,8 @@ body > #tab1:checked ~ #content1, > #tab2:checked ~ #content2, - > #tab3:checked ~ #content3 + > #tab3:checked ~ #content3, + > #tab4:checked ~ #content4 display block [id^="tab"]:checked + label -- 2.27.0