.toolbar
button.pure-button(title="Home the machine.", @click="home",
- :disabled="state.x != 'ready'")
+ :disabled="state.x != 'READY'")
.fa.fa-home
button.pure-button(
- title="{{state.x == 'running' ? 'Pause' : 'Start'}} program.",
+ title="{{state.x == 'RUNNING' ? 'Pause' : 'Start'}} program.",
@click="start_pause",
- :disabled="state.c == 'homing'")
- .fa(:class="state.x == 'running' ? 'fa-pause' : 'fa-play'")
+ :disabled="state.c == 'HOMING'")
+ .fa(:class="state.x == 'RUNNING' ? 'fa-pause' : 'fa-play'")
button.pure-button(title="Stop program.", @click="stop",
- :disabled="state.x == 'ready'")
+ :disabled="state.x == 'READY'")
.fa.fa-stop
button.pure-button(title="Pause program at next optional stop (M1).",
- @click="optional_pause", :disabled="state.c == 'homing'")
+ @click="optional_pause", :disabled="state.c == 'HOMING'")
.fa.fa-stop-circle-o
button.pure-button(title="Execute one program step.", @click="step",
- :disabled="(state.x != 'ready' && state.x != 'holding') || !file")
+ :disabled="(state.x != 'READY' && state.x != 'HOLDING') || !file")
.fa.fa-step-forward
.tabs
section#content1.tab-content
.toolbar
button.pure-button(title="Upload a new program file.", @click="open",
- :disabled="state.x == 'running' || state.x == 'stopping'")
+ :disabled="state.x == 'RUNNING' || state.x == 'STOPPING'")
.fa.fa-folder-open
input.gcode-file-input(type="file", @change="upload",
select(title="Select previously uploaded program files.",
v-model="file", @change="load",
- :disabled="state.x == 'running' || state.x == 'stopping'")
+ :disabled="state.x == 'RUNNING' || state.x == 'STOPPING'")
option(v-for="file in files", :value="file") {{file}}
.gcode(:class="{placeholder: !gcode}")
fieldset
button.pure-button.pure-button-primary(
title="Manually execute instructions.", @click="submit_mdi",
- :disabled="state.x != 'ready'") MDI
+ :disabled="state.x != 'READY'") MDI
input(v-model="mdi", @keyup.enter="submit_mdi")
.history(:class="{placeholder: !history}")
methods: {
estop: function () {
- if (this.state.x == 'estopped') api.put('clear');
+ if (this.state.x == 'ESTOPPED') api.put('clear');
else api.put('estop');
},
start_pause: function () {
- if (this.state.x == 'running') this.pause();
+ if (this.state.x == 'RUNNING') this.pause();
- else if (this.state.x == 'stopping' || this.state.x == 'holding')
+ else if (this.state.x == 'STOPPING' || this.state.x == 'HOLDING')
this.unpause();
else this.start();
import re
import serial
import json
+import time
import logging
from collections import deque
self.sp.nonblocking()
except Exception as e:
+ self.sp = None
log.warning('Failed to open serial port: %s', e)
- return
- ctrl.ioloop.add_handler(self.sp, self.serial_handler, ctrl.ioloop.READ)
+ if self.sp is not None:
+ ctrl.ioloop.add_handler(self.sp, self.serial_handler,
+ ctrl.ioloop.READ)
try:
self.i2c_bus = smbus.SMBus(ctrl.args.avr_port)
def _i2c_command(self, cmd, word = None):
- if not hasattr(self, 'i2c_bus'): return
+ if self.i2c_bus is None: return
log.info('I2C: %d' % cmd)
+ retry = 5
- if word is not None:
- self.i2c_bus.write_word_data(self.i2c_addr, cmd, word)
- self.i2c_bus.write_byte(self.i2c_addr, cmd)
+ while True:
+ try:
+ if word is not None:
+ self.i2c_bus.write_word_data(self.i2c_addr, cmd, word)
+ self.i2c_bus.write_byte(self.i2c_addr, cmd)
+ break
+
+ except IOError as e:
+ retry -= 1
+
+ if retry:
+ log.error('I2C communication failed, retrying: %s' % e)
+ self.i2c_bus.close()
+ time.sleep(0.1)
+ self.i2c_bus = smbus.SMBus(self.ctrl.args.avr_port)
+ continue
+
+ else: raise e
def report(self): self._i2c_command(I2C_REPORT)
def set_write(self, enable):
- if not hasattr(self, 'sp'): return
+ if self.sp is None: return
flags = self.ctrl.ioloop.READ
if enable: flags |= self.ctrl.ioloop.WRITE
except Exception as e:
log.error('%s, data: %s', e, line)
+ return
if 'firmware' in msg:
log.error('AVR rebooted')
self._stop_sending_gcode()
self.report()
- if 'x' in msg and msg['x'] == 'estopped':
+ if 'x' in msg and msg['x'] == 'ESTOPPED':
self._stop_sending_gcode()
self.vars.update(msg)
self.v = [0.0] * 4
self.lastV = self.v
+ self.callback()
self.processor = inevent.InEvent(ctrl.ioloop, self,
types = "js kbd".split())
- def processed_events(self):
+ def callback(self):
if self.v != self.lastV:
self.lastV = self.v
self.ctrl.avr.jog(self.v)
+ self.ctrl.ioloop.call_later(0.25, self.callback)
+
def changed(self):
if self.speed == 1: scale = 1.0 / 128.0
if has('x') or has('c'):
v = self.ctrl.avr.vars
- state = v.get('x', 'init')
- if 'c' in v and state == 'running': state = v['c']
+ state = v.get('x', 'INIT')
+ if 'c' in v and state == 'RUNNING': state = v['c']
- self.lcd.text('%-9s' % state.upper(), 0, 0)
+ self.lcd.text('%-9s' % state, 0, 0)
if has('xp'): self.lcd.text('% 10.4fX' % msg['xp'], 9, 0)
if has('yp'): self.lcd.text('% 10.4fY' % msg['yp'], 9, 1)
if has('zp'): self.lcd.text('% 10.4fZ' % msg['zp'], 9, 2)
if has('ap'): self.lcd.text('% 10.4fA' % msg['ap'], 9, 3)
if has('t'): self.lcd.text('%2uT' % msg['t'], 6, 1)
- if has('u'): self.lcd.text('%s' % msg['u'].upper(), 0, 1)
+ if has('u'): self.lcd.text('%s' % msg['u'], 0, 1)
if has('f'): self.lcd.text('%8uF' % msg['f'], 0, 2)
if has('s'): self.lcd.text('%8dS' % msg['s'], 0, 3)
import struct
-from inevent import Format
from inevent.Constants import *
+_format = 'llHHi'
+size = struct.calcsize(_format)
+
class Event(object):
"""
tint = long(self.time)
tfrac = long((self.time - tint) * 1000000)
- return \
- struct.pack(Format.Event, tsec, tfrac, self.type, self.code, self.value)
+ return struct.pack(_format, tsec, tfrac, self.type, self.code, self.value)
def decode(self, s):
*s*
A binary structure packed into a string.
"""
- tsec, tfrac, self.type, self.code, self.value = \
- struct.unpack(Format.Event, s)
+ tsec, tfrac, self.type, self.code, self.value = struct.unpack(_format, s)
self.time = tsec + tfrac / 1000000.0
from inevent import ioctl
from inevent.AbsAxisScaling import AbsAxisScaling
from inevent import Event
-from inevent import Format
from inevent.EventState import EventState
Read and return the next waiting event.
"""
try:
- s = os.read(self.filehandle, Format.EventSize)
+ s = os.read(self.filehandle, Event.size)
if s:
event = Event.Event(self)
event.decode(s)
+++ /dev/null
-# The inevent Python module was adapted from pi3d.event from the pi3d
-# project.
-#
-# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
-# Copyright (c) 2015, Tim Skillman.
-# Copyright (c) 2015, Paddy Gaunt.
-# Copyright (c) 2015, Tom Ritchford.
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-import struct
-
-Event = 'llHHi'
-EventSize = struct.calcsize(Event)
for stream in self.streams:
if stream.filehandle == fd:
while True:
- event = stream.read()
+ event = stream.next()
if event: self.handler.event(event, self.cb)
else: break