diff --git a/pypozyx/__init__.py b/pypozyx/__init__.py index 30c6e56..4b3049d 100755 --- a/pypozyx/__init__.py +++ b/pypozyx/__init__.py @@ -80,6 +80,7 @@ from pypozyx.definitions import * from pypozyx.pozyx_serial import * +from pypozyx.pozyx_i2c import * from pypozyx.structures.device import * from pypozyx.structures.generic import * from pypozyx.structures.sensor_data import * diff --git a/pypozyx/definitions/constants.py b/pypozyx/definitions/constants.py index bdb79ee..82c19b8 100755 --- a/pypozyx/definitions/constants.py +++ b/pypozyx/definitions/constants.py @@ -8,6 +8,9 @@ class PozyxConstants: + # I2C + POZYX_I2C_ADDRESS = 0x4B + # Pozyx serial buffer sizes MAX_BUF_SIZE = 100 MAX_SERIAL_SIZE = 28 diff --git a/pypozyx/lib.py b/pypozyx/lib.py index 4d54283..72fd870 100755 --- a/pypozyx/lib.py +++ b/pypozyx/lib.py @@ -1117,10 +1117,10 @@ def doPositioning(self, position, dimension=PozyxConstants.DIMENSION_3D, height= def getPositioningData(self, positioning_data): flags = Data([positioning_data.flags], 'H') - flags.load_hex_string() - s = 'F,%0.2x,%s,%i\r' % (PozyxRegisters.DO_POSITIONING_WITH_DATA, flags.byte_data, positioning_data.byte_size + 61) - # very custom solution... - r = self.serialExchange(s) + temp_data = Data([0] * (positioning_data.byte_size + 60)) + ret = self.useFunction(PozyxRegisters.DO_POSITIONING_WITH_DATA, flags, temp_data) + temp_data.load_hex_string() + r = ('%0.2x' % ret) + temp_data.byte_data if positioning_data.has_ranges(): amount_of_ranges = int(r[2 * positioning_data.byte_size:2 * positioning_data.byte_size + 2], 16) positioning_data.set_amount_of_ranges(amount_of_ranges) diff --git a/pypozyx/pozyx_i2c.py b/pypozyx/pozyx_i2c.py index 6661266..bc5ecd9 100755 --- a/pypozyx/pozyx_i2c.py +++ b/pypozyx/pozyx_i2c.py @@ -1,34 +1,140 @@ -#!/usr/bin/env python -""" +"""pypozyx.pozyx_i2c - contains the I2C interface with Pozyx through PozyxI2C.""" +from pypozyx.core import PozyxConnectionError -""" +from pypozyx.definitions.constants import (POZYX_SUCCESS, POZYX_FAILURE, + PozyxConstants) from pypozyx.lib import PozyxLib -from pypozyx.definitions.constants import MODE_POLLING -# from pypozyx.definitions.registers import * +from pypozyx.structures.generic import SingleRegister +from smbus2 import SMBus, i2c_msg + +from warnings import warn class PozyxI2C(PozyxLib): + """This class provides the Pozyx I2C interface. + All functionality from PozyxLib and PozyxCore is included. + + Args: + bus: i2c bus number (e.g. 0 or 1) or an absolute file path (e.g. `/dev/i2c-42`). + print_output (optional): boolean for printing the serial exchanges, mainly for debugging purposes + suppress_warnings (optional): boolean for suppressing warnings in the Pozyx use, usage not recommended + debug_trace (optional): boolean for printing the trace on bad serial init (DEPRECATED) + show_trace (optional): boolean for printing the trace on bad serial init (DEPRECATED) + """ + + def __init__(self, bus=1, + print_output=False, debug_trace=False, show_trace=False, + suppress_warnings=False): + """Initializes the PozyxI2C object. See above for details.""" + super(PozyxI2C, self).__init__() + self.print_output = print_output + if debug_trace is True or show_trace is True: + if not suppress_warnings: + warn("debug_trace or show_trace are on their way out, exceptions of the type PozyxException are now raised.", + DeprecationWarning) + self.suppress_warnings = suppress_warnings - def __init__(self, mode=MODE_POLLING, print_output=False): - pass + self.bus = SMBus(bus) + + self.validatePozyx() + + def validatePozyx(self): + """Validates whether the connected device is indeed a Pozyx device""" + whoami = SingleRegister() + if self.getWhoAmI(whoami) != POZYX_SUCCESS: + raise PozyxConnectionError("Connected to device, but couldn't read I2C data. Is it a Pozyx?") + if whoami.value != 0x43: + raise PozyxConnectionError("POZYX_WHO_AM_I returned 0x%0.2x, something is wrong with Pozyx." % whoami.value) def regWrite(self, address, data): - pass + """ + Writes data to the Pozyx registers, starting at a register address, + if registers are writable. + + Args: + address: Register address to start writing at. + data: Data to write to the Pozyx registers. + Has to be ByteStructure-derived object. + + Returns: + POZYX_SUCCESS, POZYX_FAILURE + """ + bdata = data.transform_to_bytes() + try: + msg_addr = i2c_msg.write(PozyxConstants.POZYX_I2C_ADDRESS, bytes([address])) + msg_write = i2c_msg.write(PozyxConstants.POZYX_I2C_ADDRESS, bdata) + self.bus.i2c_rdwr(msg_addr, msg_write) + except OSError: + return POZYX_FAILURE + return POZYX_SUCCESS def regRead(self, address, data): - pass + """ + Reads data from the Pozyx registers, starting at a register address, + if registers are readable. + + Args: + address: Register address to start writing at. + data: Data to read from the Pozyx registers. + Has to be ByteStructure-derived object. + + Returns: + POZYX_SUCCESS, POZYX_FAILURE + """ + try: + msg_addr = i2c_msg.write(PozyxConstants.POZYX_I2C_ADDRESS, bytes([address])) + msg_read = i2c_msg.read(PozyxConstants.POZYX_I2C_ADDRESS, data.byte_size) + self.bus.i2c_rdwr(msg_addr, msg_read) + r = bytes(msg_read) + except OSError: + return POZYX_FAILURE + data.load_packed(r) + return POZYX_SUCCESS def regFunction(self, address, params, data): - pass + """ + Performs a register function on the Pozyx, if the address is a register + function. + + Args: + address: Register function address of function to perform. + params: Parameters for the register function. + Has to be ByteStructure-derived object. + data: Container for the data the register function returns. + Has to be ByteStructure-derived object. + + Returns: + POZYX_SUCCESS, POZYX_FAILURE + """ + bparams = params.transform_to_bytes() + try: + msg_write = i2c_msg.write(PozyxConstants.POZYX_I2C_ADDRESS, bytes([address]) + bytes(bparams)) + msg_read = i2c_msg.read(PozyxConstants.POZYX_I2C_ADDRESS, data.byte_size + 1) + self.bus.i2c_rdwr(msg_write, msg_read) + r = bytes(msg_read) + except OSError: + return POZYX_FAILURE + if len(data) > 0: + data.load_packed(r[1:]) + return r[0] + + def waitForFlag(self, interrupt_flag, timeout_s, interrupt): + """ + Waits for a certain interrupt flag to be triggered, indicating that + that type of interrupt occured. - # - def waitForFlag(self, interrupt_flag, timeout_ms, interrupt): - pass + Args: + interrupt_flag: Flag indicating interrupt type. + timeout_s: time in seconds that POZYX_INT_STATUS will be checked + for the flag before returning POZYX_TIMEOUT. - # - def waitForFlagSafe(self, interrupt_flag, timeout_ms, interrupt): - pass + Kwargs: + interrupt: Container for the POZYX_INT_STATUS data - def configInterruptPin(self, pin, mode, bActiveHigh, bLatch, remote_id=None): - pass + Returns: + POZYX_SUCCESS, POZYX_FAILURE, POZYX_TIMEOUT + """ + if interrupt is None: + interrupt = SingleRegister() + return self.waitForFlagSafe(interrupt_flag, timeout_s, interrupt) diff --git a/pypozyx/pozyx_serial.py b/pypozyx/pozyx_serial.py index 4359b20..a7f7497 100644 --- a/pypozyx/pozyx_serial.py +++ b/pypozyx/pozyx_serial.py @@ -250,7 +250,7 @@ def regRead(self, address, data): Args: address: Register address to start writing at. - data: Data to write to the Pozyx registers. + data: Data to read from the Pozyx registers. Has to be ByteStructure-derived object. Returns: diff --git a/requirements.txt b/requirements.txt index 24b4c2f..b9f919b 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ pyserial>=3.0 +smbus2>=0.3.0 diff --git a/setup.py b/setup.py index c60dcd2..f1fe0bf 100755 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ description='Python library for Pozyx devices', install_requires=[ 'pyserial>=3.0' + 'smbus2>=0.3.0' ], long_description=long_description, author='Laurent Van Acker',