def setup(self, direction, resistor=GPIO.PULL_UP): if not direction in [self.OUTPUT, self.INPUT]: raise IoTPy_APIError( "Invalid digital pin direction. Should be INPUT or OUTPUT") if direction == self.INPUT and not resistor in [ GPIO.NONE, GPIO.PULL_UP, GPIO.PULL_DOWN ]: raise IoTPy_APIError( "Invalid GPIO resistor setting. Should be GPIO.NONE, GPIO.PULL_UP or GPIO.PULL_DOWN" ) self.direction = direction if direction == self.INPUT: self.resistor = resistor if resistor == self.PULL_UP: mode = 4 # PULL_UP elif resistor == self.PULL_DOWN: mode = 2 # PULL_DOWN else: mode = 0 # HIGH_Z else: mode = 1 # OUTPUT self.board.low_level_io( 0, encode_sfp( 3, [self._logical_pins, chr(mode) * len(self._logical_pins)]))
def set_pulse_time(self, pulse_us): """ Set PWM high (on state) time. :param pulse_us: Pulse time in microseconds. :type pulse_us: int :raise: IoTPy_APIError """ if self.primary: self.board.low_level_io(0, encode_sfp( 2, [self.logical_pin])) # set pin secondary function self.primary = False if 0 <= pulse_us <= PWM_PORT_RUNNING[self.pwm_port]['period']: self.pulse_time = pulse_us high_time = pulse_us if self.polarity == 0: high_time = PWM_PORT_RUNNING[ self.pwm_port]['period'] - pulse_us self.board.low_level_io( 0, encode_sfp(PWM._PWM_PORT_FUNCTIONS[self.pwm_port][1], [self.pwm_pin, high_time])) else: errmsg( "UPER error: PWM high time is out of range on logical pin %d." % self.logical_pin) raise IoTPy_APIError("PWM high time is out of range.")
def __init__(self, *args, **kw): super(IoPinout, self).__init__(*args, **kw) for key in self: if not (isinstance(key, int) or isinstance( key, string_types)) or not isinstance(self[key], Pin): raise IoTPy_APIError( "IoPinout must consist of integer or string keys and Pin values." )
def spi(self, name, clock=1000000, mode=SPI.MODE_0): _names = {"SPI0": 0, "SPI1": 1} if isinstance(name, int): port = name elif isinstance(name, str): if _names.has_key(name): port = _names[name] else: raise IoTPy_APIError( "Invalid SPI name %s. Must be one of %s." % (name, ", ".join(sorted(_names.keys())))) else: raise IoTPy_APIError("PWM name must be an integer or a string") divider = int(round(2.0e6 / clock)) return SPI(self, port, divider, mode)
def _encode_bytes(byte_string): if len(byte_string) < 64: return chr(0x40 | len(byte_string)).encode('latin-1') + byte_string packedlen = pack('>I', len(byte_string)).lstrip(b'\x00') if len(packedlen) == 1: return b'\xc4' + packedlen + byte_string elif len(packedlen) == 2: return b'\xc5' + packedlen + byte_string else: raise IoTPy_APIError("UPER API: - too long string passed to UPER, encode_bytes can't handle it.")
def __init__(self, board, pin): self.board = board if self.board.pinout[pin].capabilities & CAP_GPIO: self.logical_pin = self.board.pinout[pin].pinID else: raise IoTPy_APIError("Trying to assign OneWire function to non GPIO pin.") #self.board.low_level_io(0, encode_sfp(1, [self.logical_pin])) # set primary #self.board.low_level_io(0, encode_sfp(3, [self.logical_pin, 1])) # gpio mode output self.board.low_level_io(0, encode_sfp(100, [self.logical_pin]))
def low_level_io(self, ret, output_buf): """ :param ret: :param output_buf: :return: """ # print(':'.join(hex(ord(n)) for n in output_buf)) try: self.io.write(output_buf) except: raise IoTPy_APIError( "Unrecoverable transport writing error, dying.") data = None if ret != 0: try: data = self.outq.get(True, 1) except queue.Empty: raise IoTPy_APIError( "IoTPy: Nothing to read on port exception.") # print('|'.join(hex(ord(n)) for n in data)) return data
def __init__(self, board, pin): self.board = board if self.board.pinout[pin].capabilities & CAP_ADC: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("IO API: Pin " + str(pin) + " is not an ADC pin.") raise IoTPy_APIError( "Trying to assign ADC function to non ADC pin.") self.adc_pin = self.board.pinout[pin].extra[0] self.board.low_level_io(0, encode_sfp( 3, [self.logical_pin, 0])) # set GPIO to HIGH_Z self.board.low_level_io(0, encode_sfp( 2, [self.logical_pin])) # set secondary pin function self.primary = False
def setup(self, direction, resistor=PULL_UP): """ Configure GPIO. :param direction: GPIO direction: GPIO.OUTPUT or GPIO.INPUT :param resistor: GPIO internal resistor mode. Used when direction is GPIO.INPUT. Should be GPIO.PULL_UP, \ GPIO.PULL_DOWN or GPIO.NONE. :raise: IoTPy_APIError """ if not direction in [self.OUTPUT, self.INPUT]: raise IoTPy_APIError( "Invalid digital pin direction. Should be INPUT or OUTPUT") if direction == self.INPUT and not resistor in [ self.NONE, self.PULL_UP, self.PULL_DOWN ]: raise IoTPy_APIError( "Invalid digital pin resistor setting. Should be GPIO.NONE, GPIO.PULL_UP or GPIO.PULL_DOWN" ) self.direction = direction if direction == self.INPUT: self.resistor = resistor if resistor == self.PULL_UP: mode = 4 # PULL_UP elif resistor == self.PULL_DOWN: mode = 2 # PULL_DOWN else: mode = 0 # HIGH_Z else: mode = 1 # OUTPUT self.board.low_level_io(0, encode_sfp(3, [self.logical_pin, mode]))
def __init__(self, board, pin, freq=100, polarity=1): self.board = board if self.board.pinout[pin].capabilities & CAP_PWM: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("UPER API: Pin No:%d is not a PWM pin.", pin) raise IoTPy_APIError( "Trying to assign PWM function to non PWM pin.") self.pwm_port = self.board.pinout[pin].extra[0] self.pwm_pin = self.board.pinout[pin].extra[1] self.primary = True self.pulse_time = 0 self.polarity = polarity PWM_PORT_RUNNING[self.pwm_port]['channels'] += 1 if PWM_PORT_RUNNING[self.pwm_port]['channels'] == 1: self.set_frequency(freq)
def decode_sfp(io_buffer): """ Decode SFP command from byte buffer. :param io_buffer: A byte buffer which stores SFP command. :type io_buffer: bytes string :return: SFP function ID and arguments list. """ if io_buffer[0:1] != b'\xd4': return command_length = unpack('>H', io_buffer[1:3])[0] + 3 # get SFP command length located in two bytes sfp_command = unpack('B', io_buffer[3:4])[0] # get SFP command code pointer = 4 args = [] while pointer < command_length: arg_type = ord(io_buffer[pointer:pointer + 1]) pointer += 1 if arg_type < 64: # short int args.append(arg_type) elif arg_type < 128: # short str arg_len = arg_type & 0x3f args.append(io_buffer[pointer:pointer + arg_len]) pointer += arg_len else: arg_len = arg_type & 0x0f if arg_len < 4: # decoding integers if arg_len == 0: args.append(ord(io_buffer[pointer:pointer + 1])) elif arg_len == 1: args.append(unpack('>H', io_buffer[pointer:pointer + 2])[0]) elif arg_len == 2: args.append(unpack('>I', b'\x00' + io_buffer[pointer:pointer + 3])[0]) elif arg_len == 3: args.append(unpack('>I', io_buffer[pointer:pointer + 4])[0]) pointer += arg_len + 1 else: if arg_type == 0xc4: # decoding strings arg_len = ord(io_buffer[pointer:pointer + 1]) elif arg_type == 0xc5: arg_len = unpack('>H', io_buffer[pointer:pointer + 2])[0] pointer += 1 else: raise IoTPy_APIError("UPER API: Bad parameter type in decodeSFP method.") pointer += 1 args.append(io_buffer[pointer:pointer + arg_len]) pointer += arg_len return sfp_command, args
def detect_sfp_serial(uid=None): ports_list = [] my_platform = platform.system() if uid: uid = UUID(uid) if my_platform == "Windows": for i in range(256): try: serial_tmp = serial.Serial('COM' + str(i)) ports_list.append(serial_tmp.portstr) serial_tmp.close() except serial.SerialException: pass elif my_platform == "Darwin": ports_list = glob.glob("/dev/tty.usbmodem*") elif my_platform == "Linux": ports_list = glob.glob("/dev/ttyACM*") for my_port in ports_list: try: port_to_try = serial.Serial( port=my_port, baudrate=230400, # virtual com port on USB is always max speed parity=serial.PARITY_ODD, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1) komanda_siuntimui = encode_sfp(255, []) port_to_try.write(komanda_siuntimui) response = port_to_try.read(1) # read one, blocking n = port_to_try.inWaiting() # look if there is more if n: response = response + port_to_try.read(n) sfp = decode_sfp(response) if sfp[0] == 255: # device info sfp packet dev_uid = UUID(bytes=sfp[1][1]) if not uid or uid == dev_uid: return port_to_try port_to_try.close() except: pass raise IoTPy_APIError("No SFP device was found on serial ports.")
def __init__(self, board, pin): self.board = board if self.board.pinout[pin].capabilities & CAP_GPIO: self.logical_pin = self.board.pinout[pin].pinID else: errmsg("UPER API: Pin No:%d is not GPIO pin.", pin) raise IoTPy_APIError( "Trying to assign GPIO function to non GPIO pin.") # Configure default state to be input with pull-up resistor self.board.low_level_io(0, encode_sfp(1, [self.logical_pin])) # set primary self.direction = self.INPUT self.resistor = self.PULL_UP self.setup( self.direction, self.resistor) # default GPIO pin state is INPUT and PULL_UP
def __init__(self, board, pins): self.board = board for pin in pins: if not self.board.pinout[pin].capabilities & CAP_GPIO: raise IoTPy_APIError( "Trying to assign GPIO function to non GPIO pin.") self._logical_pins = list(self.board.pinout[pin].pinID for pin in pins) self._logical_pins = struct.pack("B" * len(self._logical_pins), *self._logical_pins) # Configure default state to be input with pull-up resistor self.direction = GPIO.INPUT self.resistor = GPIO.PULL_UP self.setup(self.direction, self.resistor) self.board.low_level_io(0, encode_sfp( 1, [self._logical_pins])) # set primary
def attach_irq(self, event, callback=None, user_object=None, debounce_time=50): """ Attach (enable) or reconfigure GPIO interrupt event. :param event: GPIO interrupt event. Can have one of these values: GPIO.RISE, GPIO.FALL, GPIO.CHANGE, \ GPIO.LOW or GPIO.HIGH. :param callback: User callback function. This function is executed when the interrupt event is received. \ It should take two arguments: interrupt event description and user object. Interrupt event descriptor is \ dictionary with three fields: 'id' - the interrupt ID (interrupt channel), 'event' - interrupt event type \ and 'values' - the logical values on each of interrupt channel (N-th bit represents logical pin value of \ interrupt channel N). User object is the same object as user_object. :param user_object: User defined object, which will be passed back to the callback function. Optional, \ default is None. :param debounce_time: Interrupt disable time in milliseconds after the triggering event. This is used to \ "debounce" buttons or to protect communication channel from data flood. Optional, default is 50ms. :return: Logical interrupt ID :rtype: int :raise: IoTPy_APIError """ try: irq_id = self.board.interrupts.index(self.logical_pin) self.board.low_level_io(0, encode_sfp(7, [irq_id])) # detach interrupt except ValueError: try: irq_id = self.board.interrupts.index(None) self.board.interrupts[irq_id] = self.logical_pin except ValueError: errmsg("UPER API: more than 8 interrupts requested") raise IoTPy_APIError("Too many interrupts.") self.board.callbackdict[self.logical_pin] = { 'mode': event, 'callback': callback, 'userobject': user_object } self.board.low_level_io( 0, encode_sfp(6, [irq_id, self.logical_pin, event, debounce_time])) return irq_id
def __init__(self, board, port=0, divider=1, mode=MODE_0): divider = min(max(divider, 1), 256) self.board = board self.port = port self.divider = divider self.mode = mode if self.port == 1: self.board.low_level_io(0, encode_sfp(2, [4])) self.board.low_level_io(0, encode_sfp(2, [5])) self.board.low_level_io(0, encode_sfp(2, [11])) self.board.low_level_io(0, encode_sfp(30, [self.divider, self.mode])) elif self.port == 0: self.board.low_level_io(0, encode_sfp(2, [12])) self.board.low_level_io(0, encode_sfp(2, [13])) self.board.low_level_io(0, encode_sfp(2, [14])) self.board.low_level_io(0, encode_sfp(20, [self.divider, self.mode])) else: errmsg("UPER API: Wrong SPI port number.", self.port) raise IoTPy_APIError("SPI port must be 0 or 1, trying to assign something else.")
def set_period(self, period_us): """ Set PWM period. :param period_us: PWM signal period in microseconds. :type period_us: int :raise: IoTPy_APIError """ if 0 <= period_us <= self._PWM_PORT_MAX[self.pwm_port]: if PWM_PORT_RUNNING[self.pwm_port]['period'] != period_us: self.board.low_level_io( 0, encode_sfp(self._PWM_PORT_FUNCTIONS[self.pwm_port][0], [period_us])) PWM_PORT_RUNNING[self.pwm_port]['period'] = period_us else: errmsg( "UPER API: PWM period for port %d can be only between 0-%d" % (self.pwm_port, self._PWM_PORT_MAX[self.pwm_port])) raise IoTPy_APIError("PWM period is out of range.")
def __delitem__(self, key): raise IoTPy_APIError("IoPinout can not be modified.")
def __setitem__(self, key, value): raise IoTPy_APIError("IoPinout can not be modified.")
def digital_port(self, names): for name in names: if not isinstance(name, int): raise IoTPy_APIError("GPIO name must be an integer.") return GPIOPort(self, names)
def digital(self, name): if not (isinstance(name, int) or isinstance(name, string_types)): raise IoTPy_APIError("GPIO name must be an integer.") return GPIO(self, name)