Module htpio.telnetio

This is a telnet client i/o control module. Telnet is a client/server text-oriented communication protocol using a virtual terminal connection and operates over TCP. It provides a command-line interface to the operating system on a remote host.

Example:


import htpio.telnetio as telnetio

r = telnetio.RaspberryPi(host = '192.168.199.31',
                         port = 23,
                         user = 'pi',
                         password = 'raspberry')

try:
    r.lock(14)
except:
    r.logout()
    raise

r.configure(14, telnetio.RaspberryPi.OUTPUT)
r.set(14, 1)

print(r.get(14))

r.unlock(14)
r.deconfigure(14)

Source code
# Copyright (c) Hilscher GmbH. All Rights Reserved.
#
# $Author: bgeorgiev $
# $Date: 2019-05-16 11:34:02 +0300 (Thu, 16 May 2019) $
# $Revision: 654 $


"""
This is a telnet client i/o control module.
Telnet is a client/server text-oriented communication protocol using a virtual
terminal connection and operates over TCP. It provides a command-line interface
to the operating system on a remote host.

*** Example: ***

```python

import htpio.telnetio as telnetio

r = telnetio.RaspberryPi(host = '192.168.199.31',
                         port = 23,
                         user = 'pi',
                         password = 'raspberry')

try:
    r.lock(14)
except:
    r.logout()
    raise

r.configure(14, telnetio.RaspberryPi.OUTPUT)
r.set(14, 1)

print(r.get(14))

r.unlock(14)
r.deconfigure(14)

```

"""

# Compatibility imports
from __future__ import unicode_literals
from __future__ import absolute_import

# Third party imports
from telnetlib import Telnet

# Local imports
from htpio.bridge import Device
from htpio.exceptions import PinLockedByOtherProcess
from htpio.exceptions import InvalidLoginDetails
from htpio.exceptions import CannotMountRamDisk
from htpio.exceptions import CannotCreateLockDirectory


"""
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# DEVICE CLASSES : RaspberryPi, OrangePi, Arduino, etc.
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"""


class RaspberryPi(Telnet, Device):
    """
    RaspberryPi telnet remote i/o access class.
    
    This class provides basic functionality for controlling the GPIO by
    using a remote telnet session and sending commands to the operating system.

    ## Configuration

    The user should be part of the sudo and gpio group and the visudo file
    should be configured for no password prompt when using the sudo. This is
    accomplished by executing the following commands :

    ```
    sudo adduser htp
    sudo usermod -a -G gpio htp                
    sudo usermod -a -G sudo htp

    sudo visudo                
        (add line) htp     ALL=(ALL) NOPASSWD: ALL            
        (add line) %gpio   ALL=(ALL) NOPASSWD: ALL

    ```

    ## Class attributes

        LOCK_DIR         Location of lock files (ramdisk)
        MAX_GPIO         Maximum number of gpio locks ( from 0 .. MAX)
        INPUT            GPIO is digital input
        OUTPUT           GPIO is digital output
        EOF              End of file


    ## Instance attributes

        host            : ip v4 address
        port            : port (from 0 to 65535)
        user            : user
        password        : user password
        login_prompt    : token to detect when login is expected
        password_prompt : token to detect when password is expected
        shell_prompt    : token to detect return after command execution
        timeout         : timeout time in case of connectivity problems

    ## Public methods

        islocked(gpio)              : Check if the gpio is locked
        lock(gpio)                  : Locks the gpio
        unlock(gpio)                : Unlocks the gpio
        isconfigured(gpio)          : Checks if the gpio is configured
        configure(gpio, direction)  : Configures the gpio with direction
        deconfigure(gpio)           : Restores the default configuration
        get(gpio)                   : Reads the gpio status
        set(gpio, value)            : Writes new value to gpio
        login()                     : Registers to the remote system
        logout()                    : Unregisters from the remote system
        reset()                     : Deletes all configuration data
    """

    LOCKDIR = "/tmp/htp/locks"
    """ Directory containing the lock files """

    RAMDISK = "htp_lockdir"
    """ Label for the ramdisk mounted on the lock directory """

    MAX_GPIO = 128
    """ Maximum number of gpio lock files """

    INPUT = 0
    """ Direction of gpio is input """

    OUTPUT = 1
    """ Direction of gpio is output """

    EOF = "\r\n"
    """ Character used to mark end of line transmission"""

    def __init__(
            self,
            host=None,
            port=23,
            user='htp',
            password='sokotnar',
            login_prompt="login:",
            password_prompt="Password:",
            shell_prompt="$",
            timeout=20
    ):

        """
        ## Constructor

        When called with host address, the constructor creates
        a telnet connection and performs automatic login:

        ```python
        import htpio.telnetio as telnetio

        t = telnetio.RaspberryPi('192.168.199.31')
        ```

        When called without host address, the constructor creates
        an unconnected instance. In this case the object might be
        configured by using the instance attributes:

        ```python
        import htpio.telnetio as telnetio

        t = telnetio.RaspberryPi()

        t.host = '192.168.199.31'
        t.port = 23
        t.user = 'user'
        t.password = 'password'
        t.login_prompt = 'login:'
        t.password_prompt = 'Password:'
        t.shell_prompt = '$'
        t.timeout = 20
        ```

        After the configuration above the user is required to use the
        following statements:

        ```python
        t.open(host, port)
        t.login()
        ```

        """

        Telnet.__init__(self, host, port)

        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.timeout = timeout

        self.login_prompt = login_prompt.encode('ascii')
        self.password_prompt = password_prompt.encode('ascii')
        self.shell_prompt = shell_prompt.encode('ascii')

        self._session = None
        self._locklist = None
        self._iotag = "gpio"

        self._lockdir = self.LOCKDIR
        self._ramdisk = self.RAMDISK

        if host is not None:
            self.login()

    def __del__(self):
        """ # Destructor -- close telnet connection"""

        self.close()

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  islocked : Check if pin is locked and returns the owner
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def islocked(self, pin):
        """
        Check if pin is already locked by an object of this class and returns
        the identification number of the locking process.

        *** Shell: ***
        ```
        sudo cat /tmp/htp/locks/gpio14
        ```

        *** Example: ***
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.lock(14)
        if led.islocked(14) :
            print("LED is locked!!!")
        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = (self._lockdir + iotag)

        # Command to open file
        command = "sudo cat " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()
        result = result.split()
        result = result[0].replace(self.EOF, "")

        # Verify result (should be a number)
        try:
            int(result)
        except ValueError:
            result = None

        return result

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  lock : Checks if pin is used by other processes and creates a lock file
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def lock(self, pin):
        """
        Throws an exception <b>PinLockedByOtherProcess</b> or opens the gpio
        lock file and writes the session id in it.

        ***Shell***:
        ```shell
        echo 1921681993055555 | sudo tee /tmp/htp/gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.lock(14)
        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Create lock file
        lock_owner = self.islocked(pin)
        if lock_owner is not None:
            raise PinLockedByOtherProcess(lock_owner, self._session)
        else:
            command = "echo " + \
                      self._session + \
                      " | sudo tee " + \
                      lockfile + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  unlock : Deltetes the lock file
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def unlock(self, pin, ):
        """
        Unlocks the gpio by deleting the content of the lock file.

        ***Shell***:
        ```shell
        sudo truncate --size=0 /tmp/htp/locks/gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.unlock(14)
        ...
        ```

        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Empty lock file
        command = "sudo truncate --size=0 " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # isconfigured : Checks for folders with the name gpioXX
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def isconfigured(self, pin):
        """
        This function checks if the sysfs folder /sys/class/gpio/gpioNN exists.

        ***Shell:***
        ```shell
        find /sys/class/gpio -name gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        if led.isconfigured(14):
            print("LED is configured!!!")
        ...
        ```
        """

        # Dictionary to transform mode strings to integers
        modes = {
            "in": self.INPUT,
            "out": self.OUTPUT,
        }

        # GPIO to check
        iotag = self._iotag + str(pin)

        # Check if pin folder is exported
        # find /sys/class/gpio -name gpio14
        command = "find " + \
                  "/sys/class/gpio " + \
                  "-name gpio[0-9][0-9]" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command response
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()
        result = result.split(self.EOF)

        # Evaluate result in case sysfs folder exists
        if any(iotag in folders for folders in result):

            # Command to open file
            # sudo cat /sys/class/gpio/gpio14/direction
            command = "sudo cat " + \
                       "/sys/class/gpio/" + \
                       iotag + "/" + \
                       "direction" + \
                       self.EOF

            self.write(command.encode('ascii'))

            # Flush command echo
            self.read_until(self.EOF.encode('ascii'), self.timeout)

            # Read command result
            val = self.read_until(self.shell_prompt, self.timeout)
            val = bytes(val).decode()
            val = val.split()
            val = val[0].replace(self.EOF, "")
            val = val.lower()
            val = modes.get(val)

        else:
            val = 0

        return val

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  configure : Configures pin for use through the file system 
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def configure(self, pin, direction):
        """
        Create the sysfs virtual folder for gpio manipulation.

        *** Shell : ***
        ```shell
        echo 14 | tee /sys/class/gpio/export
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        ...
        ```

        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Configure pin
        if not self.isconfigured(pin):

            # Export the desired pin (creates virtual folder)
            command = "echo " + \
                      str(pin) + \
                      " | tee /sys/class/gpio/export" + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

        # Configure the type of the pin = IN
        if direction == self.INPUT:
            command = "echo in | sudo tee /sys/class/gpio/gpio" + \
                      str(pin) + \
                      "/direction" + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Configure the type of the pin = OUT
        if direction == self.OUTPUT:
            command = "echo out | sudo tee /sys/class/gpio/gpio" + \
                      str(pin) + \
                      "/direction" + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  cleanup : Deletes the current configuration of the pin 
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def deconfigure(self, pin):
        """
        Delete the sysfs virtual folder for pin manipulation.

        *** Shell : ***
        ```
        echo 14 | tee /sys/class/gpio/unexport
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.deconfigure(14)
        ...
        ```
        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Unexport desired pin (deletes virtual folder)
        command = "echo " + \
                  str(pin) + \
                  " | tee /sys/class/gpio/unexport" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  get : Reads the value of the pin using the file system
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
    """

    def get(self, pin):
        """
        Gets the current status of the given pin by reading the system file.

        *** Shell : ***
        ```shell
        cat /sys/class/gpio/gpio14/value
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.get(14)
        ...
        ```
        """

        command = "cat " + \
                  "/sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/value" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command results
        value = self.read_until(self.EOF.encode('ascii'), self.timeout)
        value = bytes(value).decode()

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return int(value.replace(self.EOF, ""))

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  set : Writes to the pin using the file system
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
    """

    def set(self, pin, value):
        """
        Sets the current value of the given pin by using the system file.

        *** Shell: ***
        ```
        echo 1 | sudo tee /sys/class/gpio/gpio14
        ```


        *** Example: ***
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        led.set(14, 1)
        ...
        ```
        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Write to the desired pin (virtual file "value")
        command = "echo " + \
                  str(value) + \
                  " | sudo tee /sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/value" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  login : sends username and password to the telnet server
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def login(self):
        """
        Performs an automatic login to the remote system using the supplied
        user and password as instance properties.

        !!! Use only when creating an unconnected instance !!!


        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi()
        led.host = '192.168.199.31'
        led.port = 23
        led.user = 'htpio'
        led.password = 'sokotnar'

        led.open(host, port)
        led.login()

        ...
        ```
        """

        # Check if device already registered for use
        if not self._session:

            # Flush buffer and wait for login
            self.read_until(self.login_prompt, self.timeout)
            command = self.user + self.EOF
            self.write(command.encode('ascii'))

            # Flush buffer and wait for password
            self.read_until(self.password_prompt, self.timeout)
            command = self.password + self.EOF
            self.write(command.encode('ascii'))

            # Flush buffer
            result = self.read_until(self.shell_prompt, self.timeout)
            result = bytes(result).decode()

            if any('incorrect' in s for s in result.split()):
                raise InvalidLoginDetails
            else:
                self._session = self.__session()
                self.__makedir()

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  logout : Closes telnet connection
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def logout(self):
        """
        Closes the connection to the target.

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.logout()

        ...
        ```
        """

        # Add additional steps before closing the connection
        self.close()

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  reset : Initializes telnetio
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def reset(self, pin):
        """
        Deletes lock file for pin.

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.reset(14)

        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Delete lock file
        command = "sudo rm " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __islockdir : Creates lock directory if not present
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __islockdir(self):
        """
        Checks if the lock directory exists.

        ```
        [ -d /tmp/htp/locks ] && echo 1 || echo 0
        ```
        """

        command = "[ -d " + \
                  self._lockdir + \
                  " ] " + \
                  "&& echo 1 || echo 0" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command line echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.EOF.encode('ascii'), self.timeout)
        result = bytes(result).decode()
        result = result.replace(self.EOF, "")

        return int(result)

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __makedir : Creates lock directory if not present
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __makedir(self, folder=None):
        """
        Create the lock directory (stores the lock files).

        ```
        sudo mkdir -p /tmp/htp/locks
        ```
        """

        # Define lock folder name
        if folder is None:
            folder = self._lockdir
        else:
            self._lockdir = folder

        # Check and create lock directory
        if not self.__islockdir():

            command = "sudo mkdir -p " + \
                      folder + \
                      self.EOF

            self.write(command.encode('ascii'))

            if not self.__islockdir():
                raise CannotCreateLockDirectory

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        # Mount ram disk
        self.__mount(folder)

        return 0

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __ismounted : Check if ram disk mounted to lock directory
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def __ismounted(self, ramdisk=None):
        """
        Check if ram disk is mounted on lock directory.

        ```
        mount | grep -i tmpfs
        ```
        """

        # Check if ram disk mounted
        command = "mount | grep -i " + \
                  ramdisk + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()

        if any(ramdisk in mounts for mounts in result.split()):
            val = True
        else:
            val = False

        return val

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __mount : Mount ram disk
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def __mount(self, folder=None):
        """
        Mount ram disk to lock folder. This is required to remove the problem
        of frequent read/write operations on the SD card.

        ```
        sudo mount -t tmpfs -o size=16m htp_ramdisk /tmp/htp/locks
        ```
        """

        if not self.__ismounted(folder):

            command = "sudo mount -t tmpfs -o size=16m " + \
                      self._ramdisk + \
                      " " + \
                      self._lockdir + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

            if not self.__ismounted(folder):
                raise CannotMountRamDisk

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  dismount : Ejects RAMDISK used to store the locksfiles
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __dismount(self, folder=None):
        """
        Dismounts htp ramdisk from lock folder directory.

        ```
        sudo umount /tmp/htp/locks
        ```
        """

        if folder is None:
            folder = self._lockdir

        # Unmount ram disk
        command = "sudo umount " + \
                  folder + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  session : Retrieves the current telnet session
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __session(self):
        """
        Gets the socket data for this connection and converts the to one
        unique identification number. This ID is used to lock gpios.
        """

        mysocket = self.sock
        mysocket = mysocket.getsockname()
        result = '.'.join(map(str, mysocket))
        result = result.replace(".", "")

        return result

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  locklist : retries all gpios currently locked by other processes
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __locklist(self):
        """
        Gets a listing of all lock files in the lock directory.

        ```
        ls /tmp/htp/locks
        ```
        """

        # List the content of the lock directory
        command = "ls " + \
                  self._lockdir + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command results
        self._locklist = self.read_until(self.shell_prompt, self.timeout)
        self._locklist = self._locklist.split()

        return self._locklist

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  populate : generate GPIO lock files from 0 to MAX_GPIO
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __populate(self):
        """
        Creates all lock files in the lock directory.

        ```
        touch -a gpio14
        ```
        """

        # Consistent directory name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # Create lock files
        for gpio in range(self.MAX_GPIO):
            iotag = self._iotag + str(gpio)
            lockfile = self._lockdir + iotag

            command = "touch -a " + \
                      lockfile + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

        return 0

Classes

class RaspberryPi (host=None, port=23, user='htp', password='sokotnar', login_prompt='login:', password_prompt='Password:', shell_prompt='$', timeout=20)

RaspberryPi telnet remote i/o access class.

This class provides basic functionality for controlling the GPIO by using a remote telnet session and sending commands to the operating system.

Configuration

The user should be part of the sudo and gpio group and the visudo file should be configured for no password prompt when using the sudo. This is accomplished by executing the following commands :

sudo adduser htp
sudo usermod -a -G gpio htp                
sudo usermod -a -G sudo htp

sudo visudo                
    (add line) htp     ALL=(ALL) NOPASSWD: ALL            
    (add line) %gpio   ALL=(ALL) NOPASSWD: ALL

Class attributes

LOCK_DIR         Location of lock files (ramdisk)
MAX_GPIO         Maximum number of gpio locks ( from 0 .. MAX)
INPUT            GPIO is digital input
OUTPUT           GPIO is digital output
EOF              End of file

Instance attributes

host            : ip v4 address
port            : port (from 0 to 65535)
user            : user
password        : user password
login_prompt    : token to detect when login is expected
password_prompt : token to detect when password is expected
shell_prompt    : token to detect return after command execution
timeout         : timeout time in case of connectivity problems

Public methods

islocked(gpio)              : Check if the gpio is locked
lock(gpio)                  : Locks the gpio
unlock(gpio)                : Unlocks the gpio
isconfigured(gpio)          : Checks if the gpio is configured
configure(gpio, direction)  : Configures the gpio with direction
deconfigure(gpio)           : Restores the default configuration
get(gpio)                   : Reads the gpio status
set(gpio, value)            : Writes new value to gpio
login()                     : Registers to the remote system
logout()                    : Unregisters from the remote system
reset()                     : Deletes all configuration data

Constructor

When called with host address, the constructor creates a telnet connection and performs automatic login:

import htpio.telnetio as telnetio

t = telnetio.RaspberryPi('192.168.199.31')

When called without host address, the constructor creates an unconnected instance. In this case the object might be configured by using the instance attributes:

import htpio.telnetio as telnetio

t = telnetio.RaspberryPi()

t.host = '192.168.199.31'
t.port = 23
t.user = 'user'
t.password = 'password'
t.login_prompt = 'login:'
t.password_prompt = 'Password:'
t.shell_prompt = '$'
t.timeout = 20

After the configuration above the user is required to use the following statements:

t.open(host, port)
t.login()
Source code
class RaspberryPi(Telnet, Device):
    """
    RaspberryPi telnet remote i/o access class.
    
    This class provides basic functionality for controlling the GPIO by
    using a remote telnet session and sending commands to the operating system.

    ## Configuration

    The user should be part of the sudo and gpio group and the visudo file
    should be configured for no password prompt when using the sudo. This is
    accomplished by executing the following commands :

    ```
    sudo adduser htp
    sudo usermod -a -G gpio htp                
    sudo usermod -a -G sudo htp

    sudo visudo                
        (add line) htp     ALL=(ALL) NOPASSWD: ALL            
        (add line) %gpio   ALL=(ALL) NOPASSWD: ALL

    ```

    ## Class attributes

        LOCK_DIR         Location of lock files (ramdisk)
        MAX_GPIO         Maximum number of gpio locks ( from 0 .. MAX)
        INPUT            GPIO is digital input
        OUTPUT           GPIO is digital output
        EOF              End of file


    ## Instance attributes

        host            : ip v4 address
        port            : port (from 0 to 65535)
        user            : user
        password        : user password
        login_prompt    : token to detect when login is expected
        password_prompt : token to detect when password is expected
        shell_prompt    : token to detect return after command execution
        timeout         : timeout time in case of connectivity problems

    ## Public methods

        islocked(gpio)              : Check if the gpio is locked
        lock(gpio)                  : Locks the gpio
        unlock(gpio)                : Unlocks the gpio
        isconfigured(gpio)          : Checks if the gpio is configured
        configure(gpio, direction)  : Configures the gpio with direction
        deconfigure(gpio)           : Restores the default configuration
        get(gpio)                   : Reads the gpio status
        set(gpio, value)            : Writes new value to gpio
        login()                     : Registers to the remote system
        logout()                    : Unregisters from the remote system
        reset()                     : Deletes all configuration data
    """

    LOCKDIR = "/tmp/htp/locks"
    """ Directory containing the lock files """

    RAMDISK = "htp_lockdir"
    """ Label for the ramdisk mounted on the lock directory """

    MAX_GPIO = 128
    """ Maximum number of gpio lock files """

    INPUT = 0
    """ Direction of gpio is input """

    OUTPUT = 1
    """ Direction of gpio is output """

    EOF = "\r\n"
    """ Character used to mark end of line transmission"""

    def __init__(
            self,
            host=None,
            port=23,
            user='htp',
            password='sokotnar',
            login_prompt="login:",
            password_prompt="Password:",
            shell_prompt="$",
            timeout=20
    ):

        """
        ## Constructor

        When called with host address, the constructor creates
        a telnet connection and performs automatic login:

        ```python
        import htpio.telnetio as telnetio

        t = telnetio.RaspberryPi('192.168.199.31')
        ```

        When called without host address, the constructor creates
        an unconnected instance. In this case the object might be
        configured by using the instance attributes:

        ```python
        import htpio.telnetio as telnetio

        t = telnetio.RaspberryPi()

        t.host = '192.168.199.31'
        t.port = 23
        t.user = 'user'
        t.password = 'password'
        t.login_prompt = 'login:'
        t.password_prompt = 'Password:'
        t.shell_prompt = '$'
        t.timeout = 20
        ```

        After the configuration above the user is required to use the
        following statements:

        ```python
        t.open(host, port)
        t.login()
        ```

        """

        Telnet.__init__(self, host, port)

        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.timeout = timeout

        self.login_prompt = login_prompt.encode('ascii')
        self.password_prompt = password_prompt.encode('ascii')
        self.shell_prompt = shell_prompt.encode('ascii')

        self._session = None
        self._locklist = None
        self._iotag = "gpio"

        self._lockdir = self.LOCKDIR
        self._ramdisk = self.RAMDISK

        if host is not None:
            self.login()

    def __del__(self):
        """ # Destructor -- close telnet connection"""

        self.close()

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  islocked : Check if pin is locked and returns the owner
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def islocked(self, pin):
        """
        Check if pin is already locked by an object of this class and returns
        the identification number of the locking process.

        *** Shell: ***
        ```
        sudo cat /tmp/htp/locks/gpio14
        ```

        *** Example: ***
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.lock(14)
        if led.islocked(14) :
            print("LED is locked!!!")
        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = (self._lockdir + iotag)

        # Command to open file
        command = "sudo cat " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()
        result = result.split()
        result = result[0].replace(self.EOF, "")

        # Verify result (should be a number)
        try:
            int(result)
        except ValueError:
            result = None

        return result

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  lock : Checks if pin is used by other processes and creates a lock file
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def lock(self, pin):
        """
        Throws an exception <b>PinLockedByOtherProcess</b> or opens the gpio
        lock file and writes the session id in it.

        ***Shell***:
        ```shell
        echo 1921681993055555 | sudo tee /tmp/htp/gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.lock(14)
        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Create lock file
        lock_owner = self.islocked(pin)
        if lock_owner is not None:
            raise PinLockedByOtherProcess(lock_owner, self._session)
        else:
            command = "echo " + \
                      self._session + \
                      " | sudo tee " + \
                      lockfile + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  unlock : Deltetes the lock file
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def unlock(self, pin, ):
        """
        Unlocks the gpio by deleting the content of the lock file.

        ***Shell***:
        ```shell
        sudo truncate --size=0 /tmp/htp/locks/gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')
        led.unlock(14)
        ...
        ```

        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # GPIO lock file
        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Empty lock file
        command = "sudo truncate --size=0 " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    # isconfigured : Checks for folders with the name gpioXX
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def isconfigured(self, pin):
        """
        This function checks if the sysfs folder /sys/class/gpio/gpioNN exists.

        ***Shell:***
        ```shell
        find /sys/class/gpio -name gpio14
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        if led.isconfigured(14):
            print("LED is configured!!!")
        ...
        ```
        """

        # Dictionary to transform mode strings to integers
        modes = {
            "in": self.INPUT,
            "out": self.OUTPUT,
        }

        # GPIO to check
        iotag = self._iotag + str(pin)

        # Check if pin folder is exported
        # find /sys/class/gpio -name gpio14
        command = "find " + \
                  "/sys/class/gpio " + \
                  "-name gpio[0-9][0-9]" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command response
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()
        result = result.split(self.EOF)

        # Evaluate result in case sysfs folder exists
        if any(iotag in folders for folders in result):

            # Command to open file
            # sudo cat /sys/class/gpio/gpio14/direction
            command = "sudo cat " + \
                       "/sys/class/gpio/" + \
                       iotag + "/" + \
                       "direction" + \
                       self.EOF

            self.write(command.encode('ascii'))

            # Flush command echo
            self.read_until(self.EOF.encode('ascii'), self.timeout)

            # Read command result
            val = self.read_until(self.shell_prompt, self.timeout)
            val = bytes(val).decode()
            val = val.split()
            val = val[0].replace(self.EOF, "")
            val = val.lower()
            val = modes.get(val)

        else:
            val = 0

        return val

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  configure : Configures pin for use through the file system 
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def configure(self, pin, direction):
        """
        Create the sysfs virtual folder for gpio manipulation.

        *** Shell : ***
        ```shell
        echo 14 | tee /sys/class/gpio/export
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        ...
        ```

        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Configure pin
        if not self.isconfigured(pin):

            # Export the desired pin (creates virtual folder)
            command = "echo " + \
                      str(pin) + \
                      " | tee /sys/class/gpio/export" + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

        # Configure the type of the pin = IN
        if direction == self.INPUT:
            command = "echo in | sudo tee /sys/class/gpio/gpio" + \
                      str(pin) + \
                      "/direction" + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Configure the type of the pin = OUT
        if direction == self.OUTPUT:
            command = "echo out | sudo tee /sys/class/gpio/gpio" + \
                      str(pin) + \
                      "/direction" + \
                      self.EOF

            self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  cleanup : Deletes the current configuration of the pin 
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def deconfigure(self, pin):
        """
        Delete the sysfs virtual folder for pin manipulation.

        *** Shell : ***
        ```
        echo 14 | tee /sys/class/gpio/unexport
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.deconfigure(14)
        ...
        ```
        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Unexport desired pin (deletes virtual folder)
        command = "echo " + \
                  str(pin) + \
                  " | tee /sys/class/gpio/unexport" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  get : Reads the value of the pin using the file system
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
    """

    def get(self, pin):
        """
        Gets the current status of the given pin by reading the system file.

        *** Shell : ***
        ```shell
        cat /sys/class/gpio/gpio14/value
        ```

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.get(14)
        ...
        ```
        """

        command = "cat " + \
                  "/sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/value" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command results
        value = self.read_until(self.EOF.encode('ascii'), self.timeout)
        value = bytes(value).decode()

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return int(value.replace(self.EOF, ""))

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  set : Writes to the pin using the file system
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
    """

    def set(self, pin, value):
        """
        Sets the current value of the given pin by using the system file.

        *** Shell: ***
        ```
        echo 1 | sudo tee /sys/class/gpio/gpio14
        ```


        *** Example: ***
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.configure(14, telnetio.RaspberryPi.OUTPUT)
        led.set(14, 1)
        ...
        ```
        """

        # Verify is pin is locked by other process
        lock_owner = self.islocked(pin)
        if lock_owner is not None and lock_owner != self._session:
            raise PinLockedByOtherProcess(lock_owner, self._session)

        # Write to the desired pin (virtual file "value")
        command = "echo " + \
                  str(value) + \
                  " | sudo tee /sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/value" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  login : sends username and password to the telnet server
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def login(self):
        """
        Performs an automatic login to the remote system using the supplied
        user and password as instance properties.

        !!! Use only when creating an unconnected instance !!!


        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi()
        led.host = '192.168.199.31'
        led.port = 23
        led.user = 'htpio'
        led.password = 'sokotnar'

        led.open(host, port)
        led.login()

        ...
        ```
        """

        # Check if device already registered for use
        if not self._session:

            # Flush buffer and wait for login
            self.read_until(self.login_prompt, self.timeout)
            command = self.user + self.EOF
            self.write(command.encode('ascii'))

            # Flush buffer and wait for password
            self.read_until(self.password_prompt, self.timeout)
            command = self.password + self.EOF
            self.write(command.encode('ascii'))

            # Flush buffer
            result = self.read_until(self.shell_prompt, self.timeout)
            result = bytes(result).decode()

            if any('incorrect' in s for s in result.split()):
                raise InvalidLoginDetails
            else:
                self._session = self.__session()
                self.__makedir()

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  logout : Closes telnet connection
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def logout(self):
        """
        Closes the connection to the target.

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.logout()

        ...
        ```
        """

        # Add additional steps before closing the connection
        self.close()

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  reset : Initializes telnetio
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def reset(self, pin):
        """
        Deletes lock file for pin.

        ***Example***:
        ```python
        import htpio.telnetio as telnetio

        led = telnetio.RaspberryPi('192.168.199.31')

        led.reset(14)

        ...
        ```
        """

        # Consistent folder name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        iotag = self._iotag + str(pin)
        lockfile = self._lockdir + iotag

        # Delete lock file
        command = "sudo rm " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __islockdir : Creates lock directory if not present
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __islockdir(self):
        """
        Checks if the lock directory exists.

        ```
        [ -d /tmp/htp/locks ] && echo 1 || echo 0
        ```
        """

        command = "[ -d " + \
                  self._lockdir + \
                  " ] " + \
                  "&& echo 1 || echo 0" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command line echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.EOF.encode('ascii'), self.timeout)
        result = bytes(result).decode()
        result = result.replace(self.EOF, "")

        return int(result)

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __makedir : Creates lock directory if not present
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __makedir(self, folder=None):
        """
        Create the lock directory (stores the lock files).

        ```
        sudo mkdir -p /tmp/htp/locks
        ```
        """

        # Define lock folder name
        if folder is None:
            folder = self._lockdir
        else:
            self._lockdir = folder

        # Check and create lock directory
        if not self.__islockdir():

            command = "sudo mkdir -p " + \
                      folder + \
                      self.EOF

            self.write(command.encode('ascii'))

            if not self.__islockdir():
                raise CannotCreateLockDirectory

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        # Mount ram disk
        self.__mount(folder)

        return 0

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __ismounted : Check if ram disk mounted to lock directory
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def __ismounted(self, ramdisk=None):
        """
        Check if ram disk is mounted on lock directory.

        ```
        mount | grep -i tmpfs
        ```
        """

        # Check if ram disk mounted
        command = "mount | grep -i " + \
                  ramdisk + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()

        if any(ramdisk in mounts for mounts in result.split()):
            val = True
        else:
            val = False

        return val

    """
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  __mount : Mount ram disk
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    """

    def __mount(self, folder=None):
        """
        Mount ram disk to lock folder. This is required to remove the problem
        of frequent read/write operations on the SD card.

        ```
        sudo mount -t tmpfs -o size=16m htp_ramdisk /tmp/htp/locks
        ```
        """

        if not self.__ismounted(folder):

            command = "sudo mount -t tmpfs -o size=16m " + \
                      self._ramdisk + \
                      " " + \
                      self._lockdir + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

            if not self.__ismounted(folder):
                raise CannotMountRamDisk

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  dismount : Ejects RAMDISK used to store the locksfiles
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __dismount(self, folder=None):
        """
        Dismounts htp ramdisk from lock folder directory.

        ```
        sudo umount /tmp/htp/locks
        ```
        """

        if folder is None:
            folder = self._lockdir

        # Unmount ram disk
        command = "sudo umount " + \
                  folder + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

        return 0

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  session : Retrieves the current telnet session
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __session(self):
        """
        Gets the socket data for this connection and converts the to one
        unique identification number. This ID is used to lock gpios.
        """

        mysocket = self.sock
        mysocket = mysocket.getsockname()
        result = '.'.join(map(str, mysocket))
        result = result.replace(".", "")

        return result

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  locklist : retries all gpios currently locked by other processes
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __locklist(self):
        """
        Gets a listing of all lock files in the lock directory.

        ```
        ls /tmp/htp/locks
        ```
        """

        # List the content of the lock directory
        command = "ls " + \
                  self._lockdir + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command results
        self._locklist = self.read_until(self.shell_prompt, self.timeout)
        self._locklist = self._locklist.split()

        return self._locklist

    """
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    #  populate : generate GPIO lock files from 0 to MAX_GPIO
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    """

    def __populate(self):
        """
        Creates all lock files in the lock directory.

        ```
        touch -a gpio14
        ```
        """

        # Consistent directory name
        if not self._lockdir.endswith("/"):
            self._lockdir = self._lockdir + "/"

        # Create lock files
        for gpio in range(self.MAX_GPIO):
            iotag = self._iotag + str(gpio)
            lockfile = self._lockdir + iotag

            command = "touch -a " + \
                      lockfile + \
                      self.EOF

            self.write(command.encode('ascii'))

            # Flush buffer
            self.read_until(self.shell_prompt, self.timeout)

        return 0

Ancestors

Class variables

var EOF

Character used to mark end of line transmission

var LOCKDIR

Directory containing the lock files

var MAX_GPIO

Maximum number of gpio lock files

var RAMDISK

Label for the ramdisk mounted on the lock directory

Methods

def configure(self, pin, direction)

Create the sysfs virtual folder for gpio manipulation.

Shell :

echo 14 | tee /sys/class/gpio/export

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.configure(14, telnetio.RaspberryPi.OUTPUT)
...
Source code
def configure(self, pin, direction):
    """
    Create the sysfs virtual folder for gpio manipulation.

    *** Shell : ***
    ```shell
    echo 14 | tee /sys/class/gpio/export
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.configure(14, telnetio.RaspberryPi.OUTPUT)
    ...
    ```

    """

    # Verify is pin is locked by other process
    lock_owner = self.islocked(pin)
    if lock_owner is not None and lock_owner != self._session:
        raise PinLockedByOtherProcess(lock_owner, self._session)

    # Configure pin
    if not self.isconfigured(pin):

        # Export the desired pin (creates virtual folder)
        command = "echo " + \
                  str(pin) + \
                  " | tee /sys/class/gpio/export" + \
                  self.EOF

        self.write(command.encode('ascii'))

        # Flush buffer
        self.read_until(self.shell_prompt, self.timeout)

    # Configure the type of the pin = IN
    if direction == self.INPUT:
        command = "echo in | sudo tee /sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/direction" + \
                  self.EOF

        self.write(command.encode('ascii'))

    # Configure the type of the pin = OUT
    if direction == self.OUTPUT:
        command = "echo out | sudo tee /sys/class/gpio/gpio" + \
                  str(pin) + \
                  "/direction" + \
                  self.EOF

        self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0
def deconfigure(self, pin)

Delete the sysfs virtual folder for pin manipulation.

Shell :

echo 14 | tee /sys/class/gpio/unexport

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.deconfigure(14)
...
Source code
def deconfigure(self, pin):
    """
    Delete the sysfs virtual folder for pin manipulation.

    *** Shell : ***
    ```
    echo 14 | tee /sys/class/gpio/unexport
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.deconfigure(14)
    ...
    ```
    """

    # Verify is pin is locked by other process
    lock_owner = self.islocked(pin)
    if lock_owner is not None and lock_owner != self._session:
        raise PinLockedByOtherProcess(lock_owner, self._session)

    # Unexport desired pin (deletes virtual folder)
    command = "echo " + \
              str(pin) + \
              " | tee /sys/class/gpio/unexport" + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0
def get(self, pin)

Gets the current status of the given pin by reading the system file.

Shell :

cat /sys/class/gpio/gpio14/value

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.get(14)
...
Source code
def get(self, pin):
    """
    Gets the current status of the given pin by reading the system file.

    *** Shell : ***
    ```shell
    cat /sys/class/gpio/gpio14/value
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.get(14)
    ...
    ```
    """

    command = "cat " + \
              "/sys/class/gpio/gpio" + \
              str(pin) + \
              "/value" + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush command echo
    self.read_until(self.EOF.encode('ascii'), self.timeout)

    # Read command results
    value = self.read_until(self.EOF.encode('ascii'), self.timeout)
    value = bytes(value).decode()

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return int(value.replace(self.EOF, ""))
def isconfigured(self, pin)

This function checks if the sysfs folder /sys/class/gpio/gpioNN exists.

Shell:

find /sys/class/gpio -name gpio14

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.configure(14, telnetio.RaspberryPi.OUTPUT)
if led.isconfigured(14):
    print("LED is configured!!!")
...
Source code
def isconfigured(self, pin):
    """
    This function checks if the sysfs folder /sys/class/gpio/gpioNN exists.

    ***Shell:***
    ```shell
    find /sys/class/gpio -name gpio14
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.configure(14, telnetio.RaspberryPi.OUTPUT)
    if led.isconfigured(14):
        print("LED is configured!!!")
    ...
    ```
    """

    # Dictionary to transform mode strings to integers
    modes = {
        "in": self.INPUT,
        "out": self.OUTPUT,
    }

    # GPIO to check
    iotag = self._iotag + str(pin)

    # Check if pin folder is exported
    # find /sys/class/gpio -name gpio14
    command = "find " + \
              "/sys/class/gpio " + \
              "-name gpio[0-9][0-9]" + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush command echo
    self.read_until(self.EOF.encode('ascii'), self.timeout)

    # Read command response
    result = self.read_until(self.shell_prompt, self.timeout)
    result = bytes(result).decode()
    result = result.split(self.EOF)

    # Evaluate result in case sysfs folder exists
    if any(iotag in folders for folders in result):

        # Command to open file
        # sudo cat /sys/class/gpio/gpio14/direction
        command = "sudo cat " + \
                   "/sys/class/gpio/" + \
                   iotag + "/" + \
                   "direction" + \
                   self.EOF

        self.write(command.encode('ascii'))

        # Flush command echo
        self.read_until(self.EOF.encode('ascii'), self.timeout)

        # Read command result
        val = self.read_until(self.shell_prompt, self.timeout)
        val = bytes(val).decode()
        val = val.split()
        val = val[0].replace(self.EOF, "")
        val = val.lower()
        val = modes.get(val)

    else:
        val = 0

    return val
def islocked(self, pin)

Check if pin is already locked by an object of this class and returns the identification number of the locking process.

Shell:

sudo cat /tmp/htp/locks/gpio14

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')
led.lock(14)
if led.islocked(14) :
    print("LED is locked!!!")
...
Source code
def islocked(self, pin):
    """
    Check if pin is already locked by an object of this class and returns
    the identification number of the locking process.

    *** Shell: ***
    ```
    sudo cat /tmp/htp/locks/gpio14
    ```

    *** Example: ***
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')
    led.lock(14)
    if led.islocked(14) :
        print("LED is locked!!!")
    ...
    ```
    """

    # Consistent folder name
    if not self._lockdir.endswith("/"):
        self._lockdir = self._lockdir + "/"

    # GPIO lock file
    iotag = self._iotag + str(pin)
    lockfile = (self._lockdir + iotag)

    # Command to open file
    command = "sudo cat " + \
              lockfile + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush command echo
    self.read_until(self.EOF.encode('ascii'), self.timeout)

    # Read command result
    result = self.read_until(self.shell_prompt, self.timeout)
    result = bytes(result).decode()
    result = result.split()
    result = result[0].replace(self.EOF, "")

    # Verify result (should be a number)
    try:
        int(result)
    except ValueError:
        result = None

    return result
def lock(self, pin)

Throws an exception PinLockedByOtherProcess or opens the gpio lock file and writes the session id in it.

Shell:

echo 1921681993055555 | sudo tee /tmp/htp/gpio14

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')
led.lock(14)
...
Source code
def lock(self, pin):
    """
    Throws an exception <b>PinLockedByOtherProcess</b> or opens the gpio
    lock file and writes the session id in it.

    ***Shell***:
    ```shell
    echo 1921681993055555 | sudo tee /tmp/htp/gpio14
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')
    led.lock(14)
    ...
    ```
    """

    # Consistent folder name
    if not self._lockdir.endswith("/"):
        self._lockdir = self._lockdir + "/"

    # GPIO lock file
    iotag = self._iotag + str(pin)
    lockfile = self._lockdir + iotag

    # Create lock file
    lock_owner = self.islocked(pin)
    if lock_owner is not None:
        raise PinLockedByOtherProcess(lock_owner, self._session)
    else:
        command = "echo " + \
                  self._session + \
                  " | sudo tee " + \
                  lockfile + \
                  self.EOF

        self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0
def login(self)

Performs an automatic login to the remote system using the supplied user and password as instance properties.

!!! Use only when creating an unconnected instance !!!

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi()
led.host = '192.168.199.31'
led.port = 23
led.user = 'htpio'
led.password = 'sokotnar'

led.open(host, port)
led.login()

...
Source code
def login(self):
    """
    Performs an automatic login to the remote system using the supplied
    user and password as instance properties.

    !!! Use only when creating an unconnected instance !!!


    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi()
    led.host = '192.168.199.31'
    led.port = 23
    led.user = 'htpio'
    led.password = 'sokotnar'

    led.open(host, port)
    led.login()

    ...
    ```
    """

    # Check if device already registered for use
    if not self._session:

        # Flush buffer and wait for login
        self.read_until(self.login_prompt, self.timeout)
        command = self.user + self.EOF
        self.write(command.encode('ascii'))

        # Flush buffer and wait for password
        self.read_until(self.password_prompt, self.timeout)
        command = self.password + self.EOF
        self.write(command.encode('ascii'))

        # Flush buffer
        result = self.read_until(self.shell_prompt, self.timeout)
        result = bytes(result).decode()

        if any('incorrect' in s for s in result.split()):
            raise InvalidLoginDetails
        else:
            self._session = self.__session()
            self.__makedir()

    return 0
def logout(self)

Closes the connection to the target.

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.logout()

...
Source code
def logout(self):
    """
    Closes the connection to the target.

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.logout()

    ...
    ```
    """

    # Add additional steps before closing the connection
    self.close()

    return 0
def reset(self, pin)

Deletes lock file for pin.

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.reset(14)

...
Source code
def reset(self, pin):
    """
    Deletes lock file for pin.

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.reset(14)

    ...
    ```
    """

    # Consistent folder name
    if not self._lockdir.endswith("/"):
        self._lockdir = self._lockdir + "/"

    iotag = self._iotag + str(pin)
    lockfile = self._lockdir + iotag

    # Delete lock file
    command = "sudo rm " + \
              lockfile + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0
def set(self, pin, value)

Sets the current value of the given pin by using the system file.

Shell:

echo 1 | sudo tee /sys/class/gpio/gpio14

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')

led.configure(14, telnetio.RaspberryPi.OUTPUT)
led.set(14, 1)
...
Source code
def set(self, pin, value):
    """
    Sets the current value of the given pin by using the system file.

    *** Shell: ***
    ```
    echo 1 | sudo tee /sys/class/gpio/gpio14
    ```


    *** Example: ***
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')

    led.configure(14, telnetio.RaspberryPi.OUTPUT)
    led.set(14, 1)
    ...
    ```
    """

    # Verify is pin is locked by other process
    lock_owner = self.islocked(pin)
    if lock_owner is not None and lock_owner != self._session:
        raise PinLockedByOtherProcess(lock_owner, self._session)

    # Write to the desired pin (virtual file "value")
    command = "echo " + \
              str(value) + \
              " | sudo tee /sys/class/gpio/gpio" + \
              str(pin) + \
              "/value" + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0
def unlock(self, pin)

Unlocks the gpio by deleting the content of the lock file.

Shell:

sudo truncate --size=0 /tmp/htp/locks/gpio14

Example:

import htpio.telnetio as telnetio

led = telnetio.RaspberryPi('192.168.199.31')
led.unlock(14)
...
Source code
def unlock(self, pin, ):
    """
    Unlocks the gpio by deleting the content of the lock file.

    ***Shell***:
    ```shell
    sudo truncate --size=0 /tmp/htp/locks/gpio14
    ```

    ***Example***:
    ```python
    import htpio.telnetio as telnetio

    led = telnetio.RaspberryPi('192.168.199.31')
    led.unlock(14)
    ...
    ```

    """

    # Verify is pin is locked by other process
    lock_owner = self.islocked(pin)
    if lock_owner is not None and lock_owner != self._session:
        raise PinLockedByOtherProcess(lock_owner, self._session)

    # Consistent folder name
    if not self._lockdir.endswith("/"):
        self._lockdir = self._lockdir + "/"

    # GPIO lock file
    iotag = self._iotag + str(pin)
    lockfile = self._lockdir + iotag

    # Empty lock file
    command = "sudo truncate --size=0 " + \
              lockfile + \
              self.EOF

    self.write(command.encode('ascii'))

    # Flush buffer
    self.read_until(self.shell_prompt, self.timeout)

    return 0

Inherited members