Some work on a RPi4 image.
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Mon, 11 Jan 2021 05:04:00 +0000 (21:04 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Mon, 11 Jan 2021 05:04:00 +0000 (21:04 -0800)
Added support for DMM DYN4 VFD.
Added copyright to LCD boot up.
Support more gamepads.
time.clock() deprecaited.
Logging fixes.

18 files changed:
CHANGELOG.md
Makefile
scripts/browser
scripts/install.sh
scripts/setup_rpi.sh
src/avr/src/lcd.c
src/avr/src/spindle.h
src/avr/src/vfd_spindle.c
src/pug/templates/tool-view.pug
src/py/bbctrl/Camera.py
src/py/bbctrl/Jog.py
src/py/bbctrl/plan.py
src/py/inevent/EventStream.py
src/py/inevent/FindDevices.py [deleted file]
src/py/inevent/InEvent.py
src/py/inevent/JogHandler.py
src/py/lcd/__init__.py
src/resources/config-template.json

index 71331d67e79a1f5a6708a2546d1982fa3651f8b1..a10f6b1608845a5c08b3506e5af88465a0d7ccf1 100644 (file)
@@ -3,6 +3,9 @@ Buildbotics CNC Controller Firmware Changelog
 
 ## v0.4.16
  - Improved axis under/over warning tooltip.
+ - Added support for DMM DYN4 VFD.
+ - Only enable ``rapid-auto-off`` in PWM mode. #272
+ - Support more gamepads.
 
 ## v0.4.15
  - Set GCode variables ``#5400`` and ``#<_tool>``.
index 0aed58e7f4ea9cf98efb5cffbebde0705354186e..4ecd2bfad93e83beb3166d792306a589dd04ec03 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -110,7 +110,7 @@ $(TARGET_DIR)/%.html: src/pug/%.pug node_modules
        $(PUG) -O pug-opts.js -P $< -o $(TARGET_DIR) || (rm -f $@; exit 1)
 
 pylint:
-       pylint3 -E $(shell find src/py -name \*.py | grep -v flycheck_)
+       pylint -E $(shell find src/py -name \*.py | grep -v flycheck_)
 
 jshint:
        ./node_modules/jshint/bin/jshint --config jshint.json src/js/*.js
index 92bd07f8121347f57e56720a8e5a4899089caadc..304877a6c1db8696fa2b809a287406d0cf3ce818 100755 (executable)
@@ -6,8 +6,11 @@ import subprocess
 
 
 def enter_cgroup():
-    with open('/sys/fs/cgroup/memory/chrome/tasks', 'w') as f:
-        f.write(str(os.getpid()))
+    cgroup = '/sys/fs/cgroup/memory/chrome/tasks'
+
+    if os.path.exists(cgroup):
+        with open(cgroup, 'w') as f:
+            f.write(str(os.getpid()))
 
 
 # Start browser
index af1b37055bbb6eec68c1908951dc9940f5266ff6..5965308ae0cd4676a4c8bf54414b7853c2c29275 100755 (executable)
@@ -17,6 +17,7 @@ if $UPDATE_PY; then
     systemctl stop bbctrl
 
     # Update service
+    mkdir -p /var/lib/bbctrl
     rm -f /etc/init.d/bbctrl
     cp scripts/bbctrl.service /etc/systemd/system/
     systemctl daemon-reload
index 89c8b28cf79a2d90373b7143c1c513ebc2cb891c..d65c8349275c47db8f8e0452e333818451e99088 100755 (executable)
@@ -10,7 +10,8 @@ apt-get dist-upgrade -y
 # Install packages
 apt-get install -y avahi-daemon avrdude minicom python3-pip python3-smbus \
   i2c-tools python3-rpi.gpio libjpeg8 wiringpi dnsmasq hostapd \
-  iptables-persistent chromium-browser xorg rpd-plym-splash samba
+  iptables-persistent chromium-browser xorg rpd-plym-splash samba ratpoison \
+  libpython3.5
 pip3 install --upgrade tornado sockjs-tornado pyserial
 
 # Clean
@@ -39,21 +40,10 @@ sed -i 's/#dtparam=i2c/dtparam=i2c/' /boot/config.txt
 echo i2c-bcm2708 >> /etc/modules
 echo i2c-dev >> /etc/modules
 
-# Install bbctrl w/ init.d script
-cp bbctrl.init.d /etc/init.d/bbctrl
-chmod +x /etc/init.d/bbctrl
-update-rc.d bbctrl defaults
-
 # Disable Pi 3 USART BlueTooth swap
 echo -e "\ndtoverlay=pi3-disable-bt" >> /boot/config.txt
 rm -f /etc/systemd/system/multi-user.target.wants/hciuart.service
 
-# Install hawkeye
-dpkg -i hawkeye_0.6_armhf.deb
-sed -i 's/localhost/0.0.0.0/' /etc/hawkeye/hawkeye.conf
-echo 'ACTION=="add", KERNEL=="video0", RUN+="/usr/sbin/service hawkeye restart"' > /etc/udev/rules.d/50-hawkeye.rules
-adduser hawkeye video
-
 # Disable HDMI to save power and remount /boot read-only
 sed -i 's/^exit 0$//' /etc/rc.local
 echo "mount -o remount,ro /boot" >> /etc/rc.local
@@ -97,7 +87,7 @@ smbpasswd -a bbmc
 # Install bbctrl
 tar xf /mnt/host/bbctrl-*.tar.bz2
 cd $(basename bbctrl-*.tar.bz2 .tar.bz2)
-./setup.py install
+./scripts/install.sh
 cd ..
 rm -rf $(basename bbctrl-*.tar.bz2 .tar.bz2)
 
@@ -108,3 +98,4 @@ chmod +s /sbin/{halt,reboot,shutdown,poweroff}
 # Clean up
 apt-get autoremove -y
 apt-get autoclean -y
+apt-get clean
index 4417881e4d8f3b207d3d9a84f0e9fdc5ba059eb9..5e8f71d3f7c123492c2e0c5b3c571e96d9cd31b3 100644 (file)
@@ -121,10 +121,12 @@ void lcd_pgmstr(uint8_t addr, const char *s) {
 
 void _splash(uint8_t addr) {
   lcd_init(addr);
-  lcd_goto(addr, 1, 1);
+  lcd_goto(addr, 0, 0);
   lcd_pgmstr(addr, PSTR("Controller booting"));
-  lcd_goto(addr, 3, 2);
+  lcd_goto(addr, 0, 1);
   lcd_pgmstr(addr, PSTR("Please wait..."));
+  lcd_goto(addr, 0, 3);
+  lcd_pgmstr(addr, PSTR("(c) Buildbotics LLC"));
 }
 
 
index 14207410bc0698b009bf7ea4f9a3d0dc0014b7af..90e24f0eaa7e8cadec6f8d3287e67f2565b79762 100644 (file)
@@ -59,6 +59,7 @@ typedef enum {
   SPINDLE_TYPE_OMRON_MX2,
   SPINDLE_TYPE_V70,
   SPINDLE_TYPE_WJ200,
+  SPINDLE_TYPE_DMM_DYN4,
 } spindle_type_t;
 
 
index 144383c528bde837b2d086411296f6f4e7d310be..7849c56d27481e21dc7da9e7f566f03a93292991 100644 (file)
@@ -181,6 +181,16 @@ const vfd_reg_t v70_regs[] PROGMEM = {
 };
 
 
+const vfd_reg_t dmm_dyn4_regs[] PROGMEM = {
+  {REG_MAX_FREQ_FIXED, 0x00, 6000}, // Maximum operating frequency
+  {REG_FREQ_SIGN_SET,  0x0e, 0}, // Set frequency in 0.1Hz
+  {REG_STOP_WRITE,     0x0e, 0}, // Stop
+  {REG_FREQ_SIGN_READ, 0x14, 0}, // Read operating frequency
+  {REG_STATUS_READ,    0x02, 0}, // Read status
+  {REG_DISABLED},
+};
+
+
 // Same as OMRON MX2
 #define wj200_regs omron_mx2_regs
 
@@ -405,6 +415,7 @@ void vfd_spindle_init() {
   case SPINDLE_TYPE_OMRON_MX2:        _load(omron_mx2_regs);          break;
   case SPINDLE_TYPE_V70:              _load(v70_regs);                break;
   case SPINDLE_TYPE_WJ200:            _load(wj200_regs);              break;
+  case SPINDLE_TYPE_DMM_DYN4:         _load(dmm_dyn4_regs);           break;
   default: break;
   }
 
index 7b9a611f5979c393fa1ab2c41295f17d376b27cf..2139237c9fbf04e6a41d1eb731ecc7c1108337bd 100644 (file)
@@ -487,3 +487,38 @@ script#tool-view-template(type="text/x-template")
           |
           a(href="https://buildbotics.com/upload/vfd/wj200.pdf",
             target="_blank") WJ200 VFD manual
+
+      .notes(v-if="tool_type.startsWith('DMM DYN4')")
+        h2 Notes
+        p Set the following using the VFD's front panel.
+        table.modbus-regs.fixed-regs
+          tr
+            th Address
+            th Value
+            th Meaning
+            th Description
+          tr
+            td.reg-addr 40001
+            td.reg-value 1
+            td Drive ID
+            td Must match #[tt bus-id] above
+          tr
+            td.reg-addr 40002
+            td.reg-value 0
+            td RS232, relative mode, enable
+            td Drive config
+          tr
+            td.reg-addr 40035
+            td.reg-value 0
+            td 8-bit data, 1 start, no parity, two stop
+            td Communication format
+          tr
+            td.reg-addr 40036
+            td.reg-value 1
+            td 9600 BAUD rate
+            td Must match #[tt baud] above
+        p
+          | Other settings according to the
+          |
+          a(href="https://buildbotics.com/upload/vfd/dmm_dyn4.pdf",
+            target="_blank") DMM DYN4 VFD manual
index c3e8e48ddd43a58a34a7555b7560fd8b3b40149d..9273757c1935ae0070cc7d839b63553995732664 100644 (file)
@@ -465,7 +465,6 @@ class VideoHandler(web.RequestHandler):
         self.camera = app.camera
 
 
-    @web.asynchronous
     def get(self):
         self.request.connection.stream.max_write_buffer_size = 10000
 
index cbb25ee4f3624926f6c3dab91b7b7bc97f93c428..5129b99a37f9a6490b64d99a14066203df715582 100644 (file)
 import inevent
 from inevent.Constants import *
 
+type2 = [
+    'USB Gamepad',
+    'Logitech Logitech RumblePad 2 USB'
+]
+
+config1 = {
+    "deadband": 0.1,
+    "axes":     [ABS_X, ABS_Y, ABS_RY, ABS_RX],
+    "dir":      [1, -1, -1, 1],
+    "arrows":   [ABS_HAT0X, ABS_HAT0Y],
+    "speed":    [0x133, 0x130, 0x131, 0x134],
+    "lock":     [0x136, 0x137],
+}
+
+config2 = {
+    "deadband": 0.1,
+    "axes":     [ABS_X, ABS_Y, ABS_RZ, ABS_Z],
+    "dir":      [1, -1, -1, 1],
+    "arrows":   [ABS_HAT0X, ABS_HAT0Y],
+    "speed":    [0x120, 0x121, 0x122, 0x123],
+    "lock":     [0x124, 0x125],
+}
+
 
 # Listen for input events
 class Jog(inevent.JogHandler):
     def __init__(self, ctrl):
+        super().__init__(ctrl.log.get('JogHandler'))
+
         self.ctrl = ctrl
         self.log = ctrl.log.get('Jog')
 
-        config = {
-            "Logitech Logitech RumblePad 2 USB": {
-                "deadband": 0.1,
-                "axes":     [ABS_X, ABS_Y, ABS_RZ, ABS_Z],
-                "dir":      [1, -1, -1, 1],
-                "arrows":   [ABS_HAT0X, ABS_HAT0Y],
-                "speed":    [0x120, 0x121, 0x122, 0x123],
-                "lock":     [0x124, 0x125],
-            },
-
-            "default": {
-                "deadband": 0.1,
-                "axes":     [ABS_X, ABS_Y, ABS_RY, ABS_RX],
-                "dir":      [1, -1, -1, 1],
-                "arrows":   [ABS_HAT0X, ABS_HAT0Y],
-                "speed":    [0x133, 0x130, 0x131, 0x134],
-                "lock":     [0x136, 0x137],
-            }
-        }
-
-        super().__init__(config)
-
         self.v = [0.0] * 4
         self.lastV = self.v
         self.callback()
 
-        self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js'])
+        self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js'],
+                                         log = ctrl.log.get('InEvent'))
+
+
+    # From JobHandler
+    def get_config(self, name):
+        if name in type2: return config2
+
+        # Microsoft X-Box 360 pad
+        # Logitech Gamepad F310
+        return config1
 
 
     def up(self): self.ctrl.lcd.page_up()
index 8f354997e1d8c6722b91ec753703b6503cc19037..f0bf413667de2047a175bc3b4adb2db575ffce43 100644 (file)
@@ -48,6 +48,9 @@ reLogLine = re.compile(
     r'(?P<msg>.*)$')
 
 
+def clock(): return time.process_time()
+
+
 def compute_unit(a, b):
     unit = dict()
     length = 0
@@ -186,10 +189,10 @@ class Plan(object):
 
 
     def _run(self):
-        start = time.clock()
+        start = clock()
         line = 0
         maxLine = 0
-        maxLineTime = time.clock()
+        maxLineTime = clock()
         position = {axis: 0 for axis in 'xyz'}
         rapid = False
 
@@ -242,7 +245,7 @@ class Plan(object):
                         line = cmd['value']
                         if maxLine < line:
                             maxLine = line
-                            maxLineTime = time.clock()
+                            maxLineTime = clock()
 
                     elif cmd['name'] == 'speed':
                         s = cmd['value']
@@ -250,11 +253,11 @@ class Plan(object):
 
                 elif cmd['type'] == 'dwell': self.time += cmd['seconds']
 
-                if args.max_time < time.clock() - start:
+                if args.max_time < clock() - start:
                     raise Exception('Max planning time (%d sec) exceeded.' %
                                     args.max_time)
 
-                if args.max_loop < time.clock() - maxLineTime:
+                if args.max_loop < clock() - maxLineTime:
                     raise Exception('Max loop time (%d sec) exceeded.' %
                                     args.max_loop)
 
index 6cedf4aa75f547e410d7557d8f2e9cd760ac2b4c..91c7417c7a552cec2fd2f73b95e733ec4e737a82 100644 (file)
@@ -65,8 +65,6 @@ from inevent import Event
 from inevent.EventState import EventState
 
 
-log = logging.getLogger('inevent')
-
 EVIOCGRAB = ioctl._IOW(ord('E'), 0x90, "i") # Grab/Release device
 
 
@@ -116,7 +114,7 @@ class EventStream(object):
     ABS_DISTANCE, ABS_TILT_X, ABS_TILT_Y, ABS_TOOL_WIDTH]
 
 
-  def __init__(self, devIndex, devType, devName):
+  def __init__(self, devIndex, devType, devName, log = None):
     """
     Opens the given /dev/input/event file and grabs it.
 
@@ -125,6 +123,8 @@ class EventStream(object):
     self.devIndex = devIndex
     self.devType = devType
     self.devName = devName
+    self.log = log if log else logging.getLogger('inevent')
+
     self.filename = "/dev/input/event" + str(devIndex)
     self.filehandle = os.open(self.filename, os.O_RDWR)
     self.state = EventState()
@@ -195,7 +195,7 @@ class EventStream(object):
         return event
 
     except Exception as e:
-      log.info('Reading event: %s' % e)
+      self.log.info('Reading event: %s' % e)
 
 
   def __enter__(self): return self
diff --git a/src/py/inevent/FindDevices.py b/src/py/inevent/FindDevices.py
deleted file mode 100644 (file)
index 695d37a..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-################################################################################
-#                                                                              #
-#                 This file is part of the Buildbotics firmware.               #
-#                                                                              #
-#        Copyright (c) 2015 - 2020, Buildbotics LLC, All rights reserved.      #
-#                                                                              #
-#         This Source describes Open Hardware and is licensed under the        #
-#                                 CERN-OHL-S v2.                               #
-#                                                                              #
-#         You may redistribute and modify this Source and make products        #
-#    using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl).  #
-#           This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED          #
-#    WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS  #
-#     FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable    #
-#                                  conditions.                                 #
-#                                                                              #
-#                Source location: https://github.com/buildbotics               #
-#                                                                              #
-#      As per CERN-OHL-S v2 section 4, should You produce hardware based on    #
-#    these sources, You must maintain the Source Location clearly visible on   #
-#    the external case of the CNC Controller or other product you make using   #
-#                                  this Source.                                #
-#                                                                              #
-#                For more information, email info@buildbotics.com              #
-#                                                                              #
-################################################################################
-
-# 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 re
-import logging
-from inevent.Constants import *
-
-log = logging.getLogger('inevent')
-
-
-def test_bit(nlst, b):
-  index = b / 32
-  bit = b % 32
-  return index < len(nlst) and nlst[index] & (1 << bit)
-
-
-def EvToStr(events):
-  s = []
-
-  if test_bit(events, EV_SYN):       s.append("EV_SYN")
-  if test_bit(events, EV_KEY):       s.append("EV_KEY")
-  if test_bit(events, EV_REL):       s.append("EV_REL")
-  if test_bit(events, EV_ABS):       s.append("EV_ABS")
-  if test_bit(events, EV_MSC):       s.append("EV_MSC")
-  if test_bit(events, EV_LED):       s.append("EV_LED")
-  if test_bit(events, EV_SND):       s.append("EV_SND")
-  if test_bit(events, EV_REP):       s.append("EV_REP")
-  if test_bit(events, EV_FF):        s.append("EV_FF" )
-  if test_bit(events, EV_PWR):       s.append("EV_PWR")
-  if test_bit(events, EV_FF_STATUS): s.append("EV_FF_STATUS")
-
-  return s
-
-
-class DeviceCapabilities(object):
-  def __init__(self, firstLine, filehandle):
-    self.EV_SYNevents = []
-    self.EV_KEYevents = []
-    self.EV_RELevents = []
-    self.EV_ABSevents = []
-    self.EV_MSCevents = []
-    self.EV_LEDevents = []
-    self.EV_SNDevents = []
-    self.EV_REPevents = []
-    self.EV_FFevents = []
-    self.EV_PWRevents = []
-    self.EV_FF_STATUSevents = []
-    self.eventTypes = []
-
-    match = re.search(".*Bus=([0-9A-Fa-f]+).*Vendor=([0-9A-Fa-f]+).*"
-                      "Product=([0-9A-Fa-f]+).*Version=([0-9A-Fa-f]+).*",
-                      firstLine)
-
-    if not match:
-      log.warning("Do not understand device ID: %s", firstLine)
-      self.bus = 0
-      self.vendor = 0
-      self.product = 0
-      self.version = 0
-
-    else:
-      self.bus = int(match.group(1), base = 16)
-      self.vendor = int(match.group(2), base = 16)
-      self.product = int(match.group(3), base = 16)
-      self.version = int(match.group(4), base = 16)
-
-    for line in filehandle:
-      if not line.strip(): break
-
-      if line[0] == "N":
-        match = re.search('Name="([^"]+)"', line)
-        if match: self.name = match.group(1)
-        else: self.name = "UNKNOWN"
-
-      elif line[0] == "P":
-        match = re.search('Phys=(.+)', line)
-        if match: self.phys = match.group(1)
-        else: self.phys = "UNKNOWN"
-
-      elif line[0] == "S":
-          match = re.search('Sysfs=(.+)', line)
-          if match: self.sysfs = match.group(1)
-          else: self.sysfs = "UNKNOWN"
-
-      elif line[0] == "U":
-        match = re.search('Uniq=(.*)', line)
-        if match: self.uniq = match.group(1)
-        else: self.uniq = "UNKNOWN"
-
-      elif line[0] == "H":
-        match = re.search('Handlers=(.+)', line)
-        if match: self.handlers = match.group(1).split()
-        else: self.handlers = []
-
-      elif line[:5] == "B: EV":
-        eventsNums = [int(x, base = 16) for x in line[6:].split()]
-        eventsNums.reverse()
-        self.eventTypes = eventsNums
-
-      elif line[:6] == "B: KEY":
-        eventsNums = [int(x, base = 16) for x in line[7:].split()]
-        eventsNums.reverse()
-        self.EV_KEYevents = eventsNums
-
-      elif line[:6] == "B: ABS":
-        eventsNums = [int(x, base = 16) for x in line[7:].split()]
-        eventsNums.reverse()
-        self.EV_ABSevents = eventsNums
-
-      elif line[:6] == "B: MSC":
-        eventsNums = [int(x, base = 16) for x in line[7:].split()]
-        eventsNums.reverse()
-        self.EV_MSCevents = eventsNums
-
-      elif line[:6] == "B: REL":
-        eventsNums = [int(x, base = 16) for x in line[7:].split()]
-        eventsNums.reverse()
-        self.EV_RELevents = eventsNums
-
-      elif line[:6] == "B: LED":
-        eventsNums = [int(x, base = 16) for x in line[7:].split()]
-        eventsNums.reverse()
-        self.EV_LEDevents = eventsNums
-
-    for handler in self.handlers:
-      if handler[:5] == "event": self.eventIndex = int(handler[5:])
-
-    self.isMouse = False
-    self.isKeyboard = False
-    self.isJoystick = False
-
-
-  def doesProduce(self, eventType, eventCode):
-    return test_bit(self.eventTypes, eventType) and (
-      (eventType == EV_SYN and test_bit(self.EV_SYNevents, eventCode)) or
-      (eventType == EV_KEY and test_bit(self.EV_KEYevents, eventCode)) or
-      (eventType == EV_REL and test_bit(self.EV_RELevents, eventCode)) or
-      (eventType == EV_ABS and test_bit(self.EV_ABSevents, eventCode)) or
-      (eventType == EV_MSC and test_bit(self.EV_MSCevents, eventCode)) or
-      (eventType == EV_LED and test_bit(self.EV_LEDevents, eventCode)) or
-      (eventType == EV_SND and test_bit(self.EV_SNDevents, eventCode)) or
-      (eventType == EV_REP and test_bit(self.EV_REPevents, eventCode)) or
-      (eventType == EV_FF  and test_bit(self.EV_FFevents,  eventCode)) or
-      (eventType == EV_PWR and test_bit(self.EV_PWRevents, eventCode)) or
-      (eventType == EV_FF_STATUS and
-       test_bit(self.EV_FF_STATUSevents, eventCode)))
-
-
-  def __str__(self):
-    return (
-      ("%s\n"
-       "Bus: %s Vendor: %s Product: %s Version: %s\n"
-       "Phys: %s\n"
-       "Sysfs: %s\n"
-       "Uniq: %s\n"
-       "Handlers: %s Event Index: %s\n"
-       "Keyboard: %s Mouse: %s Joystick: %s\n"
-       "Events: %s") % (
-        self.name, self.bus, self.vendor, self.product, self.version, self.phys,
-        self.sysfs, self.uniq, self.handlers, self.eventIndex, self.isKeyboard,
-        self.isMouse, self.isJoystick, EvToStr(self.eventTypes)))
-
-
-deviceCapabilities = []
-
-
-def get_devices(filename = "/proc/bus/input/devices"):
-  global deviceCapabilities
-
-  with open("/proc/bus/input/devices", "r") as filehandle:
-    for line in filehandle:
-      if line[0] == "I":
-        deviceCapabilities.append(DeviceCapabilities(line, filehandle))
-
-  return deviceCapabilities
-
-
-def print_devices():
-  devs = get_devices()
-
-  for dev in devs:
-    print(str(dev))
-    print("   ABS: {}"
-          .format([x for x in range(64) if test_bit(dev.EV_ABSevents, x)]))
-    print("   REL: {}"
-          .format([x for x in range(64) if test_bit(dev.EV_RELevents, x)]))
-    print("   MSC: {}"
-          .format([x for x in range(64) if test_bit(dev.EV_MSCevents, x)]))
-    print("   KEY: {}"
-          .format([x for x in range(512) if test_bit(dev.EV_KEYevents, x)]))
-    print("   LED: {}"
-          .format([x for x in range(64) if test_bit(dev.EV_LEDevents, x)]))
-    print()
index 05d19960af60bb8bc86536e063c1a67ae28e5cc5..27390a09f5e5c0b97f2ba03fa89216fe5c3f9ba0 100644 (file)
@@ -66,8 +66,6 @@ from inevent.Constants import *
 from inevent.EventStream import EventStream
 
 
-log = logging.getLogger('inevent')
-
 _KEYS = (k for k in vars(Keys) if not k.startswith('_'))
 KEY_CODE = dict((k, getattr(Keys, k)) for k in _KEYS)
 CODE_KEY = {}
@@ -117,12 +115,13 @@ class InEvent(object):
   The keys are listed in inevent.Constants.py or /usr/include/linux/input.h
   Note that the key names refer to a US keyboard.
   """
-  def __init__(self, ioloop, cb, types = 'kbd mouse js'.split()):
+  def __init__(self, ioloop, cb, types = 'kbd mouse js'.split(), log = None):
     self.ioloop = ioloop
     self.cb = cb
     self.streams = []
     self.handler = EventHandler()
     self.types = types
+    self.log = log if log else logging.getLogger('inevent')
 
     self.udevCtx = pyudev.Context()
     self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx)
@@ -143,8 +142,9 @@ class InEvent(object):
   def get_dev_name(self, index):
     try:
       dev = self.get_dev(index)
-      return dev.parent.attributes.asstring('name').decode('utf-8')
-    except: pass
+      return dev.parent.attributes.asstring('name').strip()
+    except Exception as e:
+      self.log.error(e)
 
 
   def find_devices(self, types):
@@ -213,10 +213,10 @@ class InEvent(object):
       self.ioloop.add_handler(stream.filehandle, self.stream_handler,
                               self.ioloop.READ)
 
-      log.info('Added %s[%d] %s', devType, devIndex, devName)
+      self.log.info('Added %s[%d] %s', devType, devIndex, devName)
 
     except OSError as e:
-      log.warning('Failed to add %s[%d]: %s', devType, devIndex, e)
+      self.log.warning('Failed to add %s[%d]: %s', devType, devIndex, e)
 
 
   def remove_stream(self, devIndex):
@@ -227,7 +227,7 @@ class InEvent(object):
         stream.release()
         self.cb.clear()
 
-        log.info('Removed %s[%d]', stream.devType, devIndex)
+        self.log.info('Removed %s[%d]', stream.devType, devIndex)
 
 
   def key_state(self, key):
index 7c407fca9685adc1f70b95bf4b043ceb73d266e3..dd0ee85a510ae7f40ffbc1b05cdc9f43b9805a27 100644 (file)
@@ -30,10 +30,6 @@ import logging
 from inevent.Constants import *
 
 
-log = logging.getLogger('inevent')
-log.setLevel(logging.INFO)
-
-
 def axes_to_string(axes):
     s = ''
     for axis in axes:
@@ -63,19 +59,20 @@ def event_to_string(event, state):
 
 
 class JogHandler:
-    def __init__(self, config):
-        self.config = config
+    def __init__(self, log = None):
         self.reset()
 
+        self.log = log if log else logging.getLogger('inevent')
+
 
     def changed(self):
-        log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed))
+        self.log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed))
 
 
-    def up(self): log.debug('up')
-    def down(self): log.debug('down')
-    def left(self): log.debug('left')
-    def right(self): log.debug('right')
+    def up(self): self.log.debug('up')
+    def down(self): self.log.debug('down')
+    def left(self): self.log.debug('left')
+    def right(self): self.log.debug('right')
 
 
     def reset(self):
@@ -90,9 +87,7 @@ class JogHandler:
         self.changed()
 
 
-    def get_config(self, name):
-        if name in self.config: return self.config[name]
-        return self.config['default']
+    def get_config(self, name): raise Exception('No configs')
 
 
     def event(self, event, state, dev_name):
@@ -130,7 +125,7 @@ class JogHandler:
                 if index == 0: self.horizontal_lock = True
                 if index == 1: self.vertical_lock = True
 
-        log.debug(event_to_string(event, state))
+        self.log.debug(event_to_string(event, state))
 
         # Update axes
         old_axes = list(self.axes)
index 77d086b2203564bf112537c42a0ed5d4b2e5fc7f..b21f3cebbf6a2da73b6693819c492fa67580266d 100644 (file)
 ################################################################################
 
 import time
-import logging
-
-
-log = logging.getLogger('LCD')
 
 
 # Control flags
index c4eaa0df576fb9b71733a24fae10db8dd2826cba..d21bc132781c6ea1d49f9ea10140ed9ed49fbbcf 100644 (file)
       "values": ["Disabled", "PWM Spindle", "Huanyang VFD", "Custom Modbus VFD",
                  "AC-Tech VFD", "Nowforever VFD", "Delta VFD015M21A (Beta)",
                  "YL600, YL620, YL620-A VFD (Beta)", "FR-D700 (Beta)",
-                 "Sunfar E300 (Beta)", "OMRON MX2", "V70", "WJ200"],
+                 "Sunfar E300 (Beta)", "OMRON MX2", "V70", "WJ200",
+                 "DMM DYN4 (Beta)"],
       "default": "Disabled",
       "code": "st"
     },