Skip to content

Commit

Permalink
Merge pull request #5 from Eelviny/master
Browse files Browse the repository at this point in the history
Merge from upstream
  • Loading branch information
tcwan authored Jun 13, 2018
2 parents 20c396e + 096954b commit da5fa82
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 81 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
10 changes: 5 additions & 5 deletions nxt/bluesock.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ class BlueSock(object):

type = 'bluetooth'

def __init__(self, host):
def __init__(self, host, debug=False):
self.host = host
self.sock = None
self.debug = False
self.debug = debug

def __str__(self):
return 'Bluetooth (%s)' % self.host
Expand Down 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
6 changes: 3 additions & 3 deletions nxt/sensor/digital.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def __init__(self, brick, port, check_compatible=True):
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) + '. ' + """
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 Down
31 changes: 31 additions & 0 deletions nxt/sensor/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,34 @@ def get_color(self):
return self.get_input_values().scaled_value

get_sample = get_color


class Temperature(BaseDigitalSensor):
"""Object for LEGO MINDSTORMS NXT Temperature sensors"""
# This is actually a TI TMP275 chip: http://www.ti.com/product/tmp275
I2C_DEV = 0x98
I2C_ADDRESS = {'raw_value': (0x00, '>h')}

def __init__(self, brick, port):
# This sensor does not follow the convention of having version/vendor/
# product at I2C registers 0x00/0x08/0x10, so check_compatible is
# always False
super(Temperature, self).__init__(brick, port, False)

def _get_raw_value(self):
"""Returns raw unscaled value"""
# this is a 12-bit value
return self.read_value('raw_value')[0] >> 4

def get_deg_c(self):
"""Returns the temperature in degrees C"""
v = self._get_raw_value()
# technically, 16 should be 0x7ff/128 but 16 is close enough
return round(v / 16, 1)

def get_deg_f(self):
v = self._get_raw_value()
# technically, 16 should be 0x7ff/128 but 16 is close enough
return round(9 / 5 * v / 16 + 32, 1)

get_sample = get_deg_c
2 changes: 1 addition & 1 deletion nxt/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def get_device_info(opcode):

def _parse_get_device_info(tgram):
tgram.check_status()
name = tgram.parse_string(15)
name = tgram.parse_string(15).decode('utf-8').split('\0')[0]
a0 = tgram.parse_u8()
a1 = tgram.parse_u8()
a2 = tgram.parse_u8()
Expand Down
6 changes: 5 additions & 1 deletion nxt/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ def bytes(self):
def is_reply(self):
return self.typ == Telegram.TYPE_REPLY

def add_bytes(self, b):
self.pkt.write(pack('%ds' % len(b), b))

def add_string(self, n_bytes, v):
self.pkt.write(pack('%ds' % n_bytes, v.encode('windows-1252')))

def add_filename(self, fname):
self.pkt.write(pack('20s', fname))
self.pkt.write(pack('20s', fname.encode('windows-1252')))


def add_s8(self, v):
self.pkt.write(pack('<b', v))
Expand Down
7 changes: 0 additions & 7 deletions scripts/fantom_test

This file was deleted.

10 changes: 9 additions & 1 deletion scripts/nxt_test
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import nxt.locator
import nxt.brick

debug = False
if '--verbose' in sys.argv:
if '--verbose' in sys.argv or '--debug' in sys.argv:
debug = True
print('debug = True')

b = None
try:
print('Find brick...', flush=True)
b = nxt.locator.find_one_brick(debug=debug)
name, host, signal_strength, user_flash = b.get_device_info()
print('NXT brick name: %s' % name)
Expand All @@ -33,6 +35,12 @@ try:
print('Firmware version %s.%s' % fw_version)
millivolts = b.get_battery_level()
print('Battery level %s mV' % millivolts)
print('Play test sound...', end='', flush=True)
b.play_tone_and_wait(300, 50)
b.play_tone_and_wait(400, 50)
b.play_tone_and_wait(500, 50)
b.play_tone_and_wait(600, 50)
print('done')
b.sock.close()
except:
print("Error while running test:")
Expand Down
Loading

0 comments on commit da5fa82

Please sign in to comment.