Skip to content

Commit

Permalink
Merge branch 'master' into nxtfilemgr1
Browse files Browse the repository at this point in the history
  • Loading branch information
GoldSloth authored Apr 30, 2018
2 parents ebf0902 + 17a5a29 commit bdb5c74
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 84 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/

2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ NXT-Python is a package for controlling a LEGO NXT robot using the Python progra
* Mac: [LightBlue](http://lightblue.sourceforge.net/)
* USB Communications:
* [PyUSB](https://walac.github.io/pyusb/)
Fantom Communications:
* [Pyfantom](http://pyfantom.ni.fr.eu.org/)

## Installation
1. Go and grab the latest version from the [releases](https://github.com/Eelviny/nxt-python/releases) page - **the master branch is too unstable to use**
Expand Down
2 changes: 2 additions & 0 deletions nxt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__
*.pyc
6 changes: 3 additions & 3 deletions nxt/bluesock.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ def send(self, data):

def recv(self):
data = self.sock.recv(2)
l0 = ord(data[0])
l1 = ord(data[1])
l0 = data[0]
l1 = data[1]
plen = l0 + (l1 << 8)
data = self.sock.recv(plen)
if self.debug:
print('Recv:', end=' ')
print(':'.join('%02x' % ord(c) for c in data))
print(':'.join('%02x' % c for c in data))
return data

def _check_brick(arg, value):
Expand Down
6 changes: 3 additions & 3 deletions nxt/devsock.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ def close(self):
def send(self, data):
l0 = len(data) & 0xFF
l1 = (len(data) >> 8) & 0xFF
d = chr(l0) + chr(l1) + data
d = bytes((l0, l1)) + data
self._device.write(d)

def recv(self):
data = self._device.read(2)
l0 = ord(data[0])
l1 = ord(data[1])
l0 = data[0]
l1 = data[1]
plen = l0 + (l1 << 8)
return self._device.read(plen)

Expand Down
2 changes: 1 addition & 1 deletion nxt/direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def ls_write(opcode, port, tx_data, rx_bytes):
tgram.add_u8(port)
tgram.add_u8(len(tx_data))
tgram.add_u8(rx_bytes)
tgram.add_string(len(tx_data), tx_data)
tgram.add_bytes(tx_data)
return tgram

def ls_read(opcode, port):
Expand Down
87 changes: 55 additions & 32 deletions nxt/locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (C) 2006, 2007 Douglas P Lau
# Copyright (C) 2009 Marcus Wanner
# Copyright (C) 2013 Dave Churchill, Marcus Wanner
# Copyright (C) 2015, 2016, 2017, 2018 Multiple Authors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -18,9 +19,11 @@
class BrickNotFoundError(Exception):
pass


class NoBackendError(Exception):
pass


class Method():
"""Used to indicate which comm backends should be tried by find_bricks/
find_one_brick. Any or all can be selected."""
Expand All @@ -30,6 +33,7 @@ def __init__(self, usb=True, bluetooth=True, device=False):
self.bluetooth = bluetooth
self.device = device


def find_bricks(host=None, name=None, silent=False, method=Method()):
"""Used by find_one_brick to look for bricks ***ADVANCED USERS ONLY***"""
methods_available = 0
Expand Down Expand Up @@ -87,52 +91,69 @@ def find_one_brick(host=None, name=None, silent=False, strict=None, debug=False,
information will be read from if no brick location directives (host,
name, strict, or method) are provided."""
if debug and silent:
silent=False
silent = False
print("silent and debug can't both be set; giving debug priority")

conf = read_config(confpath, debug)
if not (host or name or strict or method):
host = conf.get('Brick', 'host')
name = conf.get('Brick', 'name')
strict = bool(int(conf.get('Brick', 'strict')))
method = eval('Method(%s)' % conf.get('Brick', 'method'))
method_value = conf.get('Brick', 'method')
if method_value:
methods = map(lambda x: x.strip().split('='),
method_value.split(','))
method = Method(**{k: v == 'True' for k, v in methods
if k in ('bluetooth', 'usb', 'device')})
if not strict: strict = True
if not method: method = Method()

if debug:
print("Host: %s Name: %s Strict: %s" % (host, name, str(strict)))
print("USB: {} BT: {}".format(method.usb, method.bluetooth))

for s in find_bricks(host, name, silent, method):
try:
if host and 'host' in dir(s) and s.host != host:
if debug:
print("Warning: the brick found does not match the host provided (s.host).")
if strict: continue
b = s.connect()
info = b.get_device_info()
print(info)
strict = False
if host and info[1] != host:
if debug:
print("Warning: the brick found does not match the host provided (get_device_info).")
if strict:
s.close()
continue
info = list(info)
info[0] = str(info[0])
info[0] = info[0][2:(len(info[0])-1)]
info[0] = info[0].strip('\\x00')
if info[0] != name:
if debug:
print("Warning; the brick found does not match the name provided.")
if strict:
s.close()
continue
return b
except:
for s in find_bricks(host, name, silent, method):
try:
if host and 'host' in dir(s) and s.host != host:
if debug:
traceback.print_exc()
print("Failed to connect to possible brick")
print("Warning: the brick found does not match the host provided (s.host).")
if strict: continue
b = s.connect()
info = b.get_device_info()
if debug:
print("info: " + str(info))

strict = False

if host and info[1] != host:
if debug:
print("Warning: the brick found does not match the host provided (get_device_info).")
print(" host:" + str(host))
print(" info[1]:" + info[1])
if strict:
s.close()
continue

info = list(info)
info[0] = str(info[0])
info[0] = info[0][2:(len(info[0])-1)]
info[0] = info[0].strip('\\x00')

if info[0] != name:
if debug:
print("Warning; the brick found does not match the name provided.")
print(" host:" + str(host))
print(" info[0]:" + info[0])
print(" name:" + str(name))
if strict:
s.close()
continue

return b
except:
if debug:
traceback.print_exc()
print("Failed to connect to possible brick")

print("""No brick was found.
Is the brick turned on?
Expand All @@ -146,6 +167,7 @@ def server_brick(host, port = 2727):
sock = ipsock.IpSock(host, port)
return sock.connect()


def device_brick(filename):
from . import devsock
sock = devsock.find_bricks(filename=filename)
Expand All @@ -161,6 +183,7 @@ def read_config(confpath=None, debug=False):
conf.add_section('Brick')
return conf


def make_config(confpath=None):
conf = configparser.RawConfigParser()
if not confpath: confpath = os.path.expanduser('~/.nxt-python')
Expand Down
2 changes: 1 addition & 1 deletion nxt/sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .common import *
from .analog import BaseAnalogSensor
from .digital import BaseDigitalSensor, find_class
from .generic import Touch, Light, Sound, Ultrasonic, Color20
from .generic import Touch, Light, Sound, Ultrasonic, Color20, Temperature
from . import mindsensors
MSSumoEyes = mindsensors.SumoEyes
MSCompassv2 = mindsensors.Compassv2
Expand Down
28 changes: 14 additions & 14 deletions nxt/sensor/digital.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ def __init__(self, version, product_id, sensor_type):
self.version = version
self.product_id = product_id
self.sensor_type = sensor_type

def clarifybinary(self, instr, label):
outstr = ''
outstr += (label + ': `' + instr + '`\n')
for char in instr:
outstr += (hex(ord(char))+', ')
outstr += ('\n')
return outstr

def __str__(self):
outstr = ''
outstr += (self.clarifybinary(str(self.version), 'Version'))
Expand All @@ -55,7 +55,7 @@ class BaseDigitalSensor(Sensor):
'factory_scale_factor': (0x12, 'B'),
'factory_scale_divisor': (0x13, 'B'),
}

def __init__(self, brick, port, check_compatible=True):
"""Creates a BaseDigitalSensor. If check_compatible is True, queries
the sensor for its name, and if a wrong sensor class was used, prints
Expand All @@ -72,8 +72,8 @@ def __init__(self, brick, port, check_compatible=True):
if check_compatible:
sensor = self.get_sensor_info()
if not sensor in self.compatible_sensors:
print(('WARNING: Wrong sensor class chosen for sensor ' +
str(sensor.product_id) + ' on port ' + str(port) + '. ' + """
print(('WARNING: Wrong sensor class chosen for sensor ' +
str(sensor.product_id) + ' on port ' + str(port + 1) + '. ' + """
You may be using the wrong type of sensor or may have connected the cable
incorrectly. If you are sure you're using the correct sensor class for the
sensor, this message is likely in error and you should disregard it and file a
Expand All @@ -95,7 +95,7 @@ def _i2c_command(self, address, value, format):
a tuple of values corresponding to the given format.
"""
value = struct.pack(format, *value)
msg = chr(self.I2C_DEV) + chr(address) + value
msg = bytes((self.I2C_DEV, address)) + value
now = time()
if self.last_poll+self.poll_delay > now:
diff = now - self.last_poll
Expand All @@ -109,7 +109,7 @@ def _i2c_query(self, address, format):
module. See http://docs.python.org/library/struct.html#format-strings
"""
n_bytes = struct.calcsize(format)
msg = chr(self.I2C_DEV) + chr(address)
msg = bytes((self.I2C_DEV, address))
now = time()
if self.last_poll+self.poll_delay > now:
diff = now - self.last_poll
Expand All @@ -125,7 +125,7 @@ def _i2c_query(self, address, format):
raise I2CError('Read failure: Not enough bytes')
data = struct.unpack(format, data[-n_bytes:])
return data

def read_value(self, name):
"""Reads a value from the sensor. Name must be a string found in
self.I2C_ADDRESS dictionary. Entries in self.I2C_ADDRESS are in the
Expand All @@ -150,13 +150,13 @@ def write_value(self, name, value):
"""
address, fmt = self.I2C_ADDRESS[name]
self._i2c_command(address, value, fmt)

def get_sensor_info(self):
version = self.read_value('version')[0].decode('windows-1252').split('\0')[0]
product_id = self.read_value('product_id')[0].decode('windows-1252').split('\0')[0]
sensor_type = self.read_value('sensor_type')[0].decode('windows-1252').split('\0')[0]
return SensorInfo(version, product_id, sensor_type)

@classmethod
def add_compatible_sensor(cls, version, product_id, sensor_type):
"""Adds an entry in the compatibility table for the sensor. If version
Expand All @@ -171,8 +171,8 @@ def add_compatible_sensor(cls, version, product_id, sensor_type):
cls.compatible_sensors.append(SCompatibility(version, product_id,
sensor_type))
add_mapping(cls, version, product_id, sensor_type)


class SCompatibility(SensorInfo):
"""An object that helps manage the sensor mappings"""
def __eq__(self, other):
Expand All @@ -194,7 +194,7 @@ def add_mapping(cls, version, product_id, sensor_type):
if product_id not in sensor_mappings:
sensor_mappings[product_id] = {}
models = sensor_mappings[product_id]

if sensor_type is None:
if sensor_type in models:
raise ValueError('Already registered!')
Expand All @@ -204,7 +204,7 @@ def add_mapping(cls, version, product_id, sensor_type):
if sensor_type not in models:
models[sensor_type] = {}
versions = models[sensor_type]

if version in versions:
raise ValueError('Already registered!')
else:
Expand Down
Loading

0 comments on commit bdb5c74

Please sign in to comment.