text:
"""
>> Thread Host Controller Interface
>> Device : OpenThread THCI
>> Class : OpenThread
"""

import re
import time
import socket
import logging
from Queue import Queue

import serial
from IThci import IThci
from GRLLibs.UtilityModules.Test import (
    Thread_Device_Role,
    Device_Data_Requirement,
    MacType,
)
from GRLLibs.UtilityModules.enums import (
    PlatformDiagnosticPacket_Direction,
    PlatformDiagnosticPacket_Type,
)
from GRLLibs.UtilityModules.ModuleHelper import ModuleHelper, ThreadRunner
from GRLLibs.ThreadPacket.PlatformPackets import (
    PlatformDiagnosticPacket,
    PlatformPackets,
)
from GRLLibs.UtilityModules.Plugins.AES_CMAC import Thread_PBKDF2

LINESEPX = re.compile(r'\r\n|\n')
"""regex: used to split lines"""

class OpenThread(IThci):
    LOWEST_POSSIBLE_PARTATION_ID = 0x1
    LINK_QUALITY_CHANGE_TIME = 100

    # Used for reference firmware version control for Test Harness.
    # This variable will be updated to match the OpenThread reference firmware
    # officially released.
    firmwarePrefix = 'OPENTHREAD/'

    # def __init__(self, SerialPort=COMPortName, EUI=MAC_Address):
    def __init__(self, **kwargs):
        """initialize the serial port and default network parameters
        Args:
            **kwargs: Arbitrary keyword arguments
                      Includes 'EUI' and 'SerialPort'
        """
        try:
            self.UIStatusMsg = ''
            self.mac = kwargs.get('EUI')
            self.port = kwargs.get('SerialPort')
            self.handle = None
            self.AutoDUTEnable = False
            self._is_net = False  # whether device is through ser2net
            self.logStatus = {
                'stop': 'stop',
                'running': 'running',
                'pauseReq': 'pauseReq',
                'paused': 'paused',
            }
            self.joinStatus = {
                'notstart': 'notstart',
                'ongoing': 'ongoing',
                'succeed': 'succeed',
                'failed': 'failed',
            }
            self.logThreadStatus = self.logStatus['stop']
            self.intialize()
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('initialize() Error: ' + str(e))

    def __del__(self):
        """close the serial port connection"""
        try:
            self.closeConnection()
            self.deviceConnected = False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('delete() Error: ' + str(e))

    def _expect(self, expected, times=50):
        """Find the `expected` line within `times` trials.

        Args:
            expected    str: the expected string
            times       int: number of trials
        """
        print('[%s] Expecting [%s]' % (self.port, expected))

        retry_times = 10
        while times > 0 and retry_times > 0:
            line = self._readline()
            print('[%s] Got line [%s]' % (self.port, line))

            if line == expected:
                print('[%s] Expected [%s]' % (self.port, expected))
                return

            if not line:
                retry_times -= 1
                time.sleep(0.1)

            times -= 1

        raise Exception('failed to find expected string[%s]' % expected)

    def _read(self, size=512):
        logging.info('%s: reading', self.port)
        if self._is_net:
            return self.handle.recv(size)
        else:
            return self.handle.read(size)

    def _write(self, data):
        logging.info('%s: writing', self.port)
        if self._is_net:
            self.handle.sendall(data)
        else:
            self.handle.write(data)

    def _readline(self):
        """Read exactly one line from the device

        Returns:
            None on no data
        """
        logging.info('%s: reading line', self.port)
        if len(self._lines) > 1:
            return self._lines.pop(0)

        tail = ''
        if len(self._lines):
            tail = self._lines.pop()

        try:
            tail += self._read()
        except socket.error:
            logging.exception('%s: No new data', self.port)
            time.sleep(0.1)

        self._lines += LINESEPX.split(tail)
        if len(self._lines) > 1:
            return self._lines.pop(0)

    def _sendline(self, line):
        """Send exactly one line to the device

        Args:
            line str: data send to device
        """
        logging.info('%s: sending line', self.port)
        # clear buffer
        self._lines = []
        try:
            self._read()
        except socket.error:
            logging.debug('%s: Nothing cleared', self.port)

        print('sending [%s]' % line)
        self._write(line + '\r\n')

        # wait for write to complete
        time.sleep(0.1)

    def __sendCommand(self, cmd):
        """send specific command to reference unit over serial port

        Args:
            cmd: OpenThread CLI string

        Returns:
            Done: successfully send the command to reference unit and parse it
            Value: successfully retrieve the desired value from reference unit
            Error: some errors occur, indicates by the followed specific error number
        """
        logging.info('%s: sendCommand[%s]', self.port, cmd)
        if self.logThreadStatus == self.logStatus['running']:
            self.logThreadStatus = self.logStatus['pauseReq']
            while (
                self.logThreadStatus != self.logStatus['paused']
                and self.logThreadStatus != self.logStatus['stop']
            ):
                pass

        try:
            # command retransmit times
            retry_times = 3
            while retry_times > 0:
                retry_times -= 1
                try:
                    self._sendline(cmd)
                    self._expect(cmd)
                except Exception as e:
                    logging.exception(
                        '%s: failed to send command[%s]: %s',
                        self.port,
                        cmd,
                        str(e),
                    )
                    if retry_times == 0:
                        raise
                else:
                    break

            line = None
            response = []
            retry_times = 10
            while retry_times > 0:
                line = self._readline()
                logging.info('%s: the read line is[%s]', self.port, line)
                if line:
                    response.append(line)
                    if line == 'Done':
                        break
                else:
                    retry_times -= 1
                    time.sleep(0.2)
            if line != 'Done':
                raise Exception(
                    '%s: failed to find end of response' % self.port
                )
            logging.info('%s: send command[%s] done!', self.port, cmd)
            return response
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('sendCommand() Error: ' + str(e))
            raise

    def __setDeviceMode(self, mode):
        """set thread device mode:

        Args:
           mode: thread device mode
           r: rx-on-when-idle
           s: secure IEEE 802.15.4 data request
           d: full thread device
           n: full network data

        Returns:
           True: successful to set the device mode
           False: fail to set the device mode
        """
        print('call __setDeviceMode')
        print(mode)
        try:
            cmd = 'mode %s' % mode
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setDeviceMode() Error: ' + str(e)
            )

    def __setRouterUpgradeThreshold(self, iThreshold):
        """set router upgrade threshold

        Args:
            iThreshold: the number of active routers on the Thread network
                        partition below which a REED may decide to become a Router.

        Returns:
            True: successful to set the ROUTER_UPGRADE_THRESHOLD
            False: fail to set ROUTER_UPGRADE_THRESHOLD
        """
        print('call __setRouterUpgradeThreshold')
        try:
            cmd = 'routerupgradethreshold %s' % str(iThreshold)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setRouterUpgradeThreshold() Error: ' + str(e)
            )

    def __setRouterDowngradeThreshold(self, iThreshold):
        """set router downgrade threshold

        Args:
            iThreshold: the number of active routers on the Thread network
                        partition above which an active router may decide to
                        become a child.

        Returns:
            True: successful to set the ROUTER_DOWNGRADE_THRESHOLD
            False: fail to set ROUTER_DOWNGRADE_THRESHOLD
        """
        print('call __setRouterDowngradeThreshold')
        try:
            cmd = 'routerdowngradethreshold %s' % str(iThreshold)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setRouterDowngradeThreshold() Error: ' + str(e)
            )

    def __setRouterSelectionJitter(self, iRouterJitter):
        """set ROUTER_SELECTION_JITTER parameter for REED to upgrade to Router

        Args:
            iRouterJitter: a random period prior to request Router ID for REED

        Returns:
            True: successful to set the ROUTER_SELECTION_JITTER
            False: fail to set ROUTER_SELECTION_JITTER
        """
        print('call _setRouterSelectionJitter')
        try:
            cmd = 'routerselectionjitter %s' % str(iRouterJitter)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setRouterSelectionJitter() Error: ' + str(e)
            )

    def __setAddressfilterMode(self, mode):
        """set address filter mode

        Returns:
            True: successful to set address filter mode.
            False: fail to set address filter mode.
        """
        print('call setAddressFilterMode() ' + mode)
        try:
            cmd = 'macfilter addr ' + mode
            if self.__sendCommand(cmd)[-1] == 'Done':
                return True
            return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                '__setAddressFilterMode() Error: ' + str(e)
            )

    def __startOpenThread(self):
        """start OpenThread stack

        Returns:
            True: successful to start OpenThread stack and thread interface up
            False: fail to start OpenThread stack
        """
        print('call startOpenThread')
        try:
            if self.hasActiveDatasetToCommit:
                if self.__sendCommand('dataset commit active')[0] != 'Done':
                    raise Exception('failed to commit active dataset')
                else:
                    self.hasActiveDatasetToCommit = False

            # restore whitelist/blacklist address filter mode if rejoin after
            # reset
            if self.isPowerDown:
                if self._addressfilterMode == 'whitelist':
                    if self.__setAddressfilterMode('whitelist'):
                        for addr in self._addressfilterSet:
                            self.addAllowMAC(addr)
                elif self._addressfilterMode == 'blacklist':
                    if self.__setAddressfilterMode('blacklist'):
                        for addr in self._addressfilterSet:
                            self.addBlockedMAC(addr)

            if self.deviceRole in [
                Thread_Device_Role.Leader,
                Thread_Device_Role.Router,
                Thread_Device_Role.REED,
            ]:
                self.__setRouterSelectionJitter(1)

            if self.__sendCommand('ifconfig up')[-1] == 'Done':
                if self.__sendCommand('thread start')[-1] == 'Done':
                    self.isPowerDown = False
                    return True
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'startOpenThread() Error: ' + str(e)
            )

    def __stopOpenThread(self):
        """stop OpenThread stack

        Returns:
            True: successful to stop OpenThread stack and thread interface down
            False: fail to stop OpenThread stack
        """
        print('call stopOpenThread')
        try:
            if self.__sendCommand('thread stop')[-1] == 'Done':
                return self.__sendCommand('ifconfig down')[-1] == 'Done'
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'stopOpenThread() Error: ' + str(e)
            )

    def __isOpenThreadRunning(self):
        """check whether or not OpenThread is running

        Returns:
            True: OpenThread is running
            False: OpenThread is not running
        """
        print('call isOpenThreadRunning')
        return self.__sendCommand('state')[0] != 'disabled'

    # rloc16 might be hex string or integer, need to return actual allocated
    # router id
    def __convertRlocToRouterId(self, xRloc16):
        """mapping Rloc16 to router id

        Args:
            xRloc16: hex rloc16 short address

        Returns:
            actual router id allocated by leader
        """
        routerList = []
        routerList = self.__sendCommand('router list')[0].split()
        print(routerList)
        print(xRloc16)

        for index in routerList:
            router = []
            cmd = 'router %s' % index
            router = self.__sendCommand(cmd)

            for line in router:
                if 'Done' in line:
                    break
                elif 'Router ID' in line:
                    routerid = line.split()[2]
                elif 'Rloc' in line:
                    rloc16 = line.split()[1]
                else:
                    pass

            # process input rloc16
            if isinstance(xRloc16, str):
                rloc16 = '0x' + rloc16
                if rloc16 == xRloc16:
                    return routerid
            elif isinstance(xRloc16, int):
                if int(rloc16, 16) == xRloc16:
                    return routerid
            else:
                pass

        return None

    def __convertIp6PrefixStringToIp6Address(self, strIp6Prefix):
        """convert IPv6 prefix string to IPv6 dotted-quad format
           for example:
           2001000000000000 -> 2001:0000:0000:0000::

        Args:
            strIp6Prefix: IPv6 address string

        Returns:
            IPv6 address dotted-quad format
        """
        prefix1 = strIp6Prefix.rstrip('L')
        prefix2 = prefix1.lstrip('0x')
        hexPrefix = str(prefix2).ljust(16, '0')
        hexIter = iter(hexPrefix)
        finalMac = ':'.join(
            a + b + c + d
            for a, b, c, d in zip(hexIter, hexIter, hexIter, hexIter)
        )
        prefix = str(finalMac)
        strIp6Prefix = prefix[:19]
        return strIp6Prefix + '::'

    def __convertLongToHex(self, iValue, fillZeros=None):
        """convert a long hex integer to string
           remove '0x' and 'L' return string

        Args:
            iValue: long integer in hex format
            fillZeros: pad string with zeros on the left to specified width

        Returns:
            string of this long integer without '0x' and 'L'
        """
        fmt = '%x'
        if fillZeros is not None:
            fmt = '%%0%dx' % fillZeros

        return fmt % iValue

    def __readCommissioningLogs(self, durationInSeconds):
        """read logs during the commissioning process

        Args:
            durationInSeconds: time duration for reading commissioning logs

        Returns:
            Commissioning logs
        """
        self.logThreadStatus = self.logStatus['running']
        logs = Queue()
        t_end = time.time() + durationInSeconds
        while time.time() < t_end:
            time.sleep(0.3)

            if self.logThreadStatus == self.logStatus['pauseReq']:
                self.logThreadStatus = self.logStatus['paused']

            if self.logThreadStatus != self.logStatus['running']:
                continue

            try:
                line = self._readline()
                if line:
                    print(line)
                    logs.put(line)

                    if 'Join success' in line:
                        self.joinCommissionedStatus = self.joinStatus[
                            'succeed'
                        ]
                        break
                    elif 'Join failed' in line:
                        self.joinCommissionedStatus = self.joinStatus['failed']
                        break

            except Exception:
                pass

        self.logThreadStatus = self.logStatus['stop']
        return logs

    def __convertChannelMask(self, channelsArray):
        """convert channelsArray to bitmask format

        Args:
            channelsArray: channel array (i.e. [21, 22])

        Returns:
            bitmask format corresponding to a given channel array
        """
        maskSet = 0

        for eachChannel in channelsArray:
            mask = 1 << eachChannel
            maskSet = maskSet | mask

        return maskSet

    def __setChannelMask(self, channelMask):
        print('call _setChannelMask')
        try:
            cmd = 'dataset channelmask %s' % channelMask
            self.hasActiveDatasetToCommit = True
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setChannelMask() Error: ' + str(e)
            )

    def __setSecurityPolicy(self, securityPolicySecs, securityPolicyFlags):
        print('call _setSecurityPolicy')
        try:
            cmd = 'dataset securitypolicy %s %s' % (
                str(securityPolicySecs),
                securityPolicyFlags,
            )
            self.hasActiveDatasetToCommit = True
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setSecurityPolicy() Error: ' + str(e)
            )

    def __setKeySwitchGuardTime(self, iKeySwitchGuardTime):
        """ set the Key switch guard time

        Args:
            iKeySwitchGuardTime: key switch guard time

        Returns:
            True: successful to set key switch guard time
            False: fail to set key switch guard time
        """
        print('%s call setKeySwitchGuardTime' % self.port)
        print(iKeySwitchGuardTime)
        try:
            cmd = 'keysequence guardtime %s' % str(iKeySwitchGuardTime)
            if self.__sendCommand(cmd)[-1] == 'Done':
                time.sleep(1)
                return True
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setKeySwitchGuardTime() Error; ' + str(e)
            )

    def __getCommissionerSessionId(self):
        """ get the commissioner session id allocated from Leader """
        print('%s call getCommissionerSessionId' % self.port)
        return self.__sendCommand('commissioner sessionid')[0]

    def _connect(self):
        print('My port is %s' % self.port)
        if self.port.startswith('COM'):
            self.handle = serial.Serial(self.port, 115200, timeout=0)
            time.sleep(1)
            self.handle.write('\r\n')
            time.sleep(0.1)
            self._is_net = False
        elif ':' in self.port:
            host, port = self.port.split(':')
            self.handle = socket.create_connection((host, port))
            self.handle.setblocking(0)
            self._is_net = True
        else:
            raise Exception('Unknown port schema')
        self.UIStatusMsg = self.getVersionNumber()

    def closeConnection(self):
        """close current serial port connection"""
        print('%s call closeConnection' % self.port)
        try:
            if self.handle:
                self.handle.close()
                self.handle = None
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'closeConnection() Error: ' + str(e)
            )

    def intialize(self):
        """initialize the serial port with baudrate, timeout parameters"""
        print('%s call intialize' % self.port)
        try:
            self.deviceConnected = False

            # init serial port
            self._connect()

            if self.firmwarePrefix in self.UIStatusMsg:
                self.deviceConnected = True
            else:
                self.UIStatusMsg = (
                    'Firmware Not Matching Expecting '
                    + self.firmwarePrefix
                    + ' Now is '
                    + self.UIStatusMsg
                )
                ModuleHelper.WriteIntoDebugLogger(
                    'Err: OpenThread device Firmware not matching..'
                )

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('intialize() Error: ' + str(e))
            self.deviceConnected = False

    def setNetworkName(self, networkName='GRL'):
        """set Thread Network name

        Args:
            networkName: the networkname string to be set

        Returns:
            True: successful to set the Thread Networkname
            False: fail to set the Thread Networkname
        """
        print('%s call setNetworkName' % self.port)
        print(networkName)
        try:
            cmd = 'networkname %s' % networkName
            datasetCmd = 'dataset networkname %s' % networkName
            self.hasActiveDatasetToCommit = True
            return (
                self.__sendCommand(cmd)[-1] == 'Done'
                and self.__sendCommand(datasetCmd)[-1] == 'Done'
            )
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setNetworkName() Error: ' + str(e)
            )

    def setChannel(self, channel=11):
        """set channel of Thread device operates on.

        Args:
            channel:
                    (0  - 10: Reserved)
                    (11 - 26: 2.4GHz channels)
                    (27 - 65535: Reserved)

        Returns:
            True: successful to set the channel
            False: fail to set the channel
        """
        print('%s call setChannel' % self.port)
        print(channel)
        try:
            cmd = 'channel %s' % channel
            datasetCmd = 'dataset channel %s' % channel
            self.hasActiveDatasetToCommit = True
            return (
                self.__sendCommand(cmd)[-1] == 'Done'
                and self.__sendCommand(datasetCmd)[-1] == 'Done'
            )
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setChannel() Error: ' + str(e))

    def getChannel(self):
        """get current channel"""
        print('%s call getChannel' % self.port)
        return self.__sendCommand('channel')[0]

    def setMAC(self, xEUI):
        """set the extended addresss of Thread device

        Args:
            xEUI: extended address in hex format

        Returns:
            True: successful to set the extended address
            False: fail to set the extended address
        """
        print('%s call setMAC' % self.port)
        print(xEUI)
        address64 = ''
        try:
            if not xEUI:
                address64 = self.mac

            if not isinstance(xEUI, str):
                address64 = self.__convertLongToHex(xEUI, 16)
            else:
                address64 = xEUI

            cmd = 'extaddr %s' % address64
            print(cmd)
            if self.__sendCommand(cmd)[-1] == 'Done':
                self.mac = address64
                return True
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setMAC() Error: ' + str(e))

    def getMAC(self, bType=MacType.RandomMac):
        """get one specific type of MAC address
           currently OpenThread only supports Random MAC address

        Args:
            bType: indicate which kind of MAC address is required

        Returns:
            specific type of MAC address
        """
        print('%s call getMAC' % self.port)
        print(bType)
        # if power down happens, return extended address assigned previously
        if self.isPowerDown:
            macAddr64 = self.mac
        else:
            if bType == MacType.FactoryMac:
                macAddr64 = self.__sendCommand('eui64')[0]
            elif bType == MacType.HashMac:
                macAddr64 = self.__sendCommand('joiner id')[0]
            else:
                macAddr64 = self.__sendCommand('extaddr')[0]
        print(macAddr64)

        return int(macAddr64, 16)

    def getLL64(self):
        """get link local unicast IPv6 address"""
        print('%s call getLL64' % self.port)
        return self.__sendCommand('ipaddr linklocal')[0]

    def getRloc16(self):
        """get rloc16 short address"""
        print('%s call getRloc16' % self.port)
        rloc16 = self.__sendCommand('rloc16')[0]
        return int(rloc16, 16)

    def getRloc(self):
        """get router locator unicast Ipv6 address"""
        print('%s call getRloc' % self.port)
        return self.__sendCommand('ipaddr rloc')[0]

    def __getGlobal(self):
        """get global unicast IPv6 address set
           if configuring multiple entries
        """
        print('%s call getGlobal' % self.port)
        globalAddrs = []
        rlocAddr = self.getRloc()

        addrs = self.__sendCommand('ipaddr')

        # take rloc address as a reference for current mesh local prefix,
        # because for some TCs, mesh local prefix may be updated through
        # pending dataset management.
        for ip6Addr in addrs:
            if ip6Addr == 'Done':
                break

            fullIp = ModuleHelper.GetFullIpv6Address(ip6Addr).lower()

            print('address %s' % fullIp)

            if fullIp.startswith('fe80'):
                print('link local')
                continue

            if fullIp.startswith(rlocAddr[0:19]):
                print('mesh local')
                continue

            globalAddrs.append(fullIp)
            print('global')

        return globalAddrs

    def setNetworkKey(self, key):
        """set Thread Network master key

        Args:
            key: Thread Network master key used in secure the MLE/802.15.4 packet

        Returns:
            True: successful to set the Thread Network master key
            False: fail to set the Thread Network master key
        """
        masterKey = ''
        print('%s call setNetworkKey' % self.port)
        print(key)
        try:
            if not isinstance(key, str):
                masterKey = self.__convertLongToHex(key, 32)
                cmd = 'masterkey %s' % masterKey
                datasetCmd = 'dataset masterkey %s' % masterKey
            else:
                masterKey = key
                cmd = 'masterkey %s' % masterKey
                datasetCmd = 'dataset masterkey %s' % masterKey

            self.networkKey = masterKey
            self.hasActiveDatasetToCommit = True
            return (
                self.__sendCommand(cmd)[-1] == 'Done'
                and self.__sendCommand(datasetCmd)[-1] == 'Done'
            )
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setNetworkkey() Error: ' + str(e)
            )

    def addBlockedMAC(self, xEUI):
        """add a given extended address to the blacklist entry

        Args:
            xEUI: extended address in hex format

        Returns:
            True: successful to add a given extended address to the blacklist entry
            False: fail to add a given extended address to the blacklist entry
        """
        print('%s call addBlockedMAC' % self.port)
        print(xEUI)
        if isinstance(xEUI, str):
            macAddr = xEUI
        else:
            macAddr = self.__convertLongToHex(xEUI)

        try:
            # if blocked device is itself
            if macAddr == self.mac:
                print('block device itself')
                return True

            if self._addressfilterMode != 'blacklist':
                if self.__setAddressfilterMode('blacklist'):
                    self._addressfilterMode = 'blacklist'

            cmd = 'macfilter addr add %s' % macAddr
            print(cmd)
            ret = self.__sendCommand(cmd)[-1] == 'Done'

            self._addressfilterSet.add(macAddr)
            print('current blacklist entries:')
            for addr in self._addressfilterSet:
                print(addr)

            return ret
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'addBlockedMAC() Error: ' + str(e)
            )

    def addAllowMAC(self, xEUI):
        """add a given extended address to the whitelist addressfilter

        Args:
            xEUI: a given extended address in hex format

        Returns:
            True: successful to add a given extended address to the whitelist entry
            False: fail to add a given extended address to the whitelist entry
        """
        print('%s call addAllowMAC' % self.port)
        print(xEUI)
        if isinstance(xEUI, str):
            macAddr = xEUI
        else:
            macAddr = self.__convertLongToHex(xEUI)

        try:
            if self._addressfilterMode != 'whitelist':
                if self.__setAddressfilterMode('whitelist'):
                    self._addressfilterMode = 'whitelist'

            cmd = 'macfilter addr add %s' % macAddr
            print(cmd)
            ret = self.__sendCommand(cmd)[-1] == 'Done'

            self._addressfilterSet.add(macAddr)
            print('current whitelist entries:')
            for addr in self._addressfilterSet:
                print(addr)
            return ret

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('addAllowMAC() Error: ' + str(e))

    def clearBlockList(self):
        """clear all entries in blacklist table

        Returns:
            True: successful to clear the blacklist
            False: fail to clear the blacklist
        """
        print('%s call clearBlockList' % self.port)

        # remove all entries in blacklist
        try:
            print('clearing blacklist entries:')
            for addr in self._addressfilterSet:
                print(addr)

            # disable blacklist
            if self.__setAddressfilterMode('disable'):
                self._addressfilterMode = 'disable'
                # clear ops
                cmd = 'macfilter addr clear'
                if self.__sendCommand(cmd)[-1] == 'Done':
                    self._addressfilterSet.clear()
                    return True
            return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'clearBlockList() Error: ' + str(e)
            )

    def clearAllowList(self):
        """clear all entries in whitelist table

        Returns:
            True: successful to clear the whitelist
            False: fail to clear the whitelist
        """
        print('%s call clearAllowList' % self.port)

        # remove all entries in whitelist
        try:
            print('clearing whitelist entries:')
            for addr in self._addressfilterSet:
                print(addr)

            # disable whitelist
            if self.__setAddressfilterMode('disable'):
                self._addressfilterMode = 'disable'
                # clear ops
                cmd = 'macfilter addr clear'
                if self.__sendCommand(cmd)[-1] == 'Done':
                    self._addressfilterSet.clear()
                    return True
            return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'clearAllowList() Error: ' + str(e)
            )

    def getDeviceRole(self):
        """get current device role in Thread Network"""
        print('%s call getDeviceRole' % self.port)
        return self.__sendCommand('state')[0]

    def joinNetwork(self, eRoleId):
        """make device ready to join the Thread Network with a given role

        Args:
            eRoleId: a given device role id

        Returns:
            True: ready to set Thread Network parameter for joining desired Network
        """
        print('%s call joinNetwork' % self.port)
        print(eRoleId)

        self.deviceRole = eRoleId
        mode = ''
        try:
            if ModuleHelper.LeaderDutChannelFound:
                self.channel = ModuleHelper.Default_Channel

            # FIXME: when Harness call setNetworkDataRequirement()?
            # only sleep end device requires stable networkdata now
            if eRoleId == Thread_Device_Role.Leader:
                print('join as leader')
                mode = 'rsdn'
                if self.AutoDUTEnable is False:
                    # set ROUTER_DOWNGRADE_THRESHOLD
                    self.__setRouterDowngradeThreshold(33)
            elif eRoleId == Thread_Device_Role.Router:
                print('join as router')
                mode = 'rsdn'
                if self.AutoDUTEnable is False:
                    # set ROUTER_DOWNGRADE_THRESHOLD
                    self.__setRouterDowngradeThreshold(33)
            elif eRoleId == Thread_Device_Role.SED:
                print('join as sleepy end device')
                mode = 's'
                self.__setPollPeriod(self.__sedPollPeriod)
            elif eRoleId == Thread_Device_Role.EndDevice:
                print('join as end device')
                mode = 'rsn'
            elif eRoleId == Thread_Device_Role.REED:
                print('join as REED')
                mode = 'rsdn'
                # set ROUTER_UPGRADE_THRESHOLD
                self.__setRouterUpgradeThreshold(0)
            elif eRoleId == Thread_Device_Role.EndDevice_FED:
                # always remain an ED, never request to be a router
                print('join as FED')
                mode = 'rsdn'
                # set ROUTER_UPGRADE_THRESHOLD
                self.__setRouterUpgradeThreshold(0)
            elif eRoleId == Thread_Device_Role.EndDevice_MED:
                print('join as MED')
                mode = 'rsn'
            else:
                pass

            # set Thread device mode with a given role
            self.__setDeviceMode(mode)
            self.__setKeySwitchGuardTime(0)

            # start OpenThread
            self.__startOpenThread()
            time.sleep(3)

            return True
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('joinNetwork() Error: ' + str(e))

    def getNetworkFragmentID(self):
        """get current partition id of Thread Network Partition from LeaderData

        Returns:
            The Thread network Partition Id
        """
        print('%s call getNetworkFragmentID' % self.port)
        if not self.__isOpenThreadRunning():
            print('OpenThread is not running')
            return None

        leaderData = []
        leaderData = self.__sendCommand('leaderdata')
        return int(leaderData[0].split()[2], 16)

    def getParentAddress(self):
        """get Thread device's parent extended address and rloc16 short address

        Returns:
            The extended address of parent in hex format
        """
        print('%s call getParentAddress' % self.port)
        parentInfo = []
        parentInfo = self.__sendCommand('parent')

        for line in parentInfo:
            if 'Done' in line:
                break
            elif 'Ext Addr' in line:
                eui = line.split()[2]
                print(eui)
            # elif 'Rloc' in line:
            #    rloc16 = line.split()[1]
            #    print(rloc16)
            else:
                pass

        return int(eui, 16)

    def powerDown(self):
        """power down the Thread device"""
        print('%s call powerDown' % self.port)
        self._sendline('reset')
        self.isPowerDown = True

    def powerUp(self):
        """power up the Thread device"""
        print('%s call powerUp' % self.port)
        if not self.handle:
            self._connect()

        self.isPowerDown = False

        if not self.__isOpenThreadRunning():
            self.__startOpenThread()

    def reboot(self):
        """reset and rejoin to Thread Network without any timeout

        Returns:
            True: successful to reset and rejoin the Thread Network
            False: fail to reset and rejoin the Thread Network
        """
        print('%s call reboot' % self.port)
        try:
            self._sendline('reset')
            self.isPowerDown = True
            time.sleep(3)

            self.__startOpenThread()
            time.sleep(3)

            if self.__sendCommand('state')[0] == 'disabled':
                print('[FAIL] reboot')
                return False
            else:
                return True
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('reboot() Error: ' + str(e))

    def ping(self, destination, length=20):
        """ send ICMPv6 echo request with a given length to a unicast destination
            address

        Args:
            destination: the unicast destination address of ICMPv6 echo request
            length: the size of ICMPv6 echo request payload
        """
        print('%s call ping' % self.port)
        print('destination: %s' % destination)
        try:
            cmd = 'ping %s %s' % (destination, str(length))
            print(cmd)
            self._sendline(cmd)
            self._expect(cmd)
            # wait echo reply
            time.sleep(1)
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('ping() Error: ' + str(e))

    def multicast_Ping(self, destination, length=20):
        """send ICMPv6 echo request with a given length to a multicast destination
           address

        Args:
            destination: the multicast destination address of ICMPv6 echo request
            length: the size of ICMPv6 echo request payload
        """
        print('%s call multicast_Ping' % self.port)
        print('destination: %s' % destination)
        try:
            cmd = 'ping %s %s' % (destination, str(length))
            print(cmd)
            self._sendline(cmd)
            self._expect(cmd)
            # wait echo reply
            time.sleep(1)
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'multicast_ping() Error: ' + str(e)
            )

    def getVersionNumber(self):
        """get OpenThread stack firmware version number"""
        print('%s call getVersionNumber' % self.port)
        return self.__sendCommand('version')[0]

    def setPANID(self, xPAN):
        """set Thread Network PAN ID

        Args:
            xPAN: a given PAN ID in hex format

        Returns:
            True: successful to set the Thread Network PAN ID
            False: fail to set the Thread Network PAN ID
        """
        print('%s call setPANID' % self.port)
        print(xPAN)
        panid = ''
        try:
            if not isinstance(xPAN, str):
                panid = str(hex(xPAN))
                print(panid)

            cmd = 'panid %s' % panid
            datasetCmd = 'dataset panid %s' % panid
            self.hasActiveDatasetToCommit = True
            return (
                self.__sendCommand(cmd)[-1] == 'Done'
                and self.__sendCommand(datasetCmd)[-1] == 'Done'
            )
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setPANID() Error: ' + str(e))

    def reset(self):
        """factory reset"""
        print('%s call reset' % self.port)
        try:
            self._sendline('factoryreset')
            self._read()
            time.sleep(0.5)

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('reset() Error: ' + str(e))

    def removeRouter(self, xRouterId):
        """kickoff router with a given router id from the Thread Network

        Args:
            xRouterId: a given router id in hex format

        Returns:
            True: successful to remove the router from the Thread Network
            False: fail to remove the router from the Thread Network
        """
        print('%s call removeRouter' % self.port)
        print(xRouterId)
        routerId = ''
        routerId = self.__convertRlocToRouterId(xRouterId)
        print(routerId)

        if routerId is None:
            print('no matched xRouterId')
            return False

        try:
            cmd = 'releaserouterid %s' % routerId
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'removeRouter() Error: ' + str(e)
            )

    def setDefaultValues(self):
        """set default mandatory Thread Network parameter value"""
        print('%s call setDefaultValues' % self.port)

        # initialize variables
        self.networkName = ModuleHelper.Default_NwkName
        self.networkKey = ModuleHelper.Default_NwkKey
        self.channel = ModuleHelper.Default_Channel
        self.channelMask = '0x7fff800'  # (0xffff << 11)
        self.panId = ModuleHelper.Default_PanId
        self.xpanId = ModuleHelper.Default_XpanId
        self.meshLocalPrefix = ModuleHelper.Default_MLPrefix
        # OT only accept hex format PSKc for now
        self.pskc = '00000000000000000000000000000000'
        self.securityPolicySecs = ModuleHelper.Default_SecurityPolicy
        self.securityPolicyFlags = 'onrcb'
        self.activetimestamp = ModuleHelper.Default_ActiveTimestamp
        # self.sedPollingRate = ModuleHelper.Default_Harness_SED_Polling_Rate
        self.__sedPollPeriod = 3 * 1000  # in milliseconds
        self.deviceRole = None
        self.provisioningUrl = ''
        self.hasActiveDatasetToCommit = False
        self.logThread = Queue()
        self.logThreadStatus = self.logStatus['stop']
        self.joinCommissionedStatus = self.joinStatus['notstart']
        # indicate Thread device requests full or stable network data
        self.networkDataRequirement = ''
        # indicate if Thread device experiences a power down event
        self.isPowerDown = False
        # indicate AddressFilter mode ['disable', 'whitelist', 'blacklist']
        self._addressfilterMode = 'disable'
        self._addressfilterSet = set()  # cache filter entries
        # indicate if Thread device is an active commissioner
        self.isActiveCommissioner = False
        self._lines = None  # buffered lines read from device

        # initialize device configuration
        try:
            self.setMAC(self.mac)
            self.__setChannelMask(self.channelMask)
            self.__setSecurityPolicy(
                self.securityPolicySecs, self.securityPolicyFlags
            )
            self.setChannel(self.channel)
            self.setPANID(self.panId)
            self.setXpanId(self.xpanId)
            self.setNetworkName(self.networkName)
            self.setNetworkKey(self.networkKey)
            self.setMLPrefix(self.meshLocalPrefix)
            self.setPSKc(self.pskc)
            self.setActiveTimestamp(self.activetimestamp)
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setDefaultValue() Error: ' + str(e)
            )

    def getDeviceConncetionStatus(self):
        """check if serial port connection is ready or not"""
        print('%s call getDeviceConnectionStatus' % self.port)
        return self.deviceConnected

    def setPollingRate(self, iPollingRate):
        """set data polling rate for sleepy end device

        Args:
            iPollingRate: data poll period of sleepy end device (in seconds)

        Returns:
            True: successful to set the data polling rate for sleepy end device
            False: fail to set the data polling rate for sleepy end device
        """
        print('%s call setPollingRate' % self.port)

        iPollingRate = int(iPollingRate * 1000)
        print(iPollingRate)

        if self.__sedPollPeriod != iPollingRate:
            self.__sedPollPeriod = iPollingRate

            # apply immediately
            if self.__isOpenThreadRunning():
                return self.__setPollPeriod(self.__sedPollPeriod)

        return True

    def __setPollPeriod(self, iPollPeriod):
        """set data poll period for sleepy end device

        Args:
            iPollPeriod: data poll period of sleepy end device (in milliseconds)

        Returns:
            True: successful to set the data poll period for sleepy end device
            False: fail to set the data poll period for sleepy end device
        """
        try:
            cmd = 'pollperiod %d' % iPollPeriod
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                '__setPollPeriod() Error: ' + str(e)
            )

    def setLinkQuality(self, EUIadr, LinkQuality):
        """set custom LinkQualityIn for all receiving messages from the specified EUIadr

        Args:
            EUIadr: a given extended address
            LinkQuality: a given custom link quality
                         link quality/link margin mapping table
                         3: 21 - 255 (dB)
                         2: 11 - 20 (dB)
                         1: 3 - 9 (dB)
                         0: 0 - 2 (dB)

        Returns:
            True: successful to set the link quality
            False: fail to set the link quality
        """
        print('%s call setLinkQuality' % self.port)
        print(EUIadr)
        print(LinkQuality)
        try:
            # process EUIadr
            euiHex = hex(EUIadr)
            euiStr = str(euiHex)
            euiStr = euiStr.rstrip('L')
            address64 = ''
            if '0x' in euiStr:
                address64 = euiStr.lstrip('0x')
                # prepend 0 at the beginning
                if len(address64) < 16:
                    address64 = address64.zfill(16)
                    print(address64)

            cmd = 'macfilter rss add-lqi %s %s' % (address64, str(LinkQuality))
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setLinkQuality() Error: ' + str(e)
            )

    def setOutBoundLinkQuality(self, LinkQuality):
        """set custom LinkQualityIn for all receiving messages from the any address

        Args:
            LinkQuality: a given custom link quality
                         link quality/link margin mapping table
                         3: 21 - 255 (dB)
                         2: 11 - 20 (dB)
                         1: 3 - 9 (dB)
                         0: 0 - 2 (dB)

        Returns:
            True: successful to set the link quality
            False: fail to set the link quality
        """
        print('%s call setOutBoundLinkQuality' % self.port)
        print(LinkQuality)
        try:
            cmd = 'macfilter rss add-lqi * %s' % str(LinkQuality)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setOutBoundLinkQuality() Error: ' + str(e)
            )

    def removeRouterPrefix(self, prefixEntry):
        """remove the configured prefix on a border router

        Args:
            prefixEntry: a on-mesh prefix entry

        Returns:
            True: successful to remove the prefix entry from border router
            False: fail to remove the prefix entry from border router
        """
        print('%s call removeRouterPrefix' % self.port)
        print(prefixEntry)
        prefix = self.__convertIp6PrefixStringToIp6Address(str(prefixEntry))
        try:
            prefixLen = 64
            cmd = 'prefix remove %s/%d' % (prefix, prefixLen)
            print(cmd)
            if self.__sendCommand(cmd)[-1] == 'Done':
                # send server data ntf to leader
                return self.__sendCommand('netdataregister')[-1] == 'Done'
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'removeRouterPrefix() Error: ' + str(e)
            )

    def resetAndRejoin(self, timeout):
        """reset and join back Thread Network with a given timeout delay

        Args:
            timeout: a timeout interval before rejoin Thread Network

        Returns:
            True: successful to reset and rejoin Thread Network
            False: fail to reset and rejoin the Thread Network
        """
        print('%s call resetAndRejoin' % self.port)
        print(timeout)
        try:
            self._sendline('reset')
            self.isPowerDown = True
            time.sleep(timeout)

            if self.deviceRole == Thread_Device_Role.SED:
                self.__setPollPeriod(self.__sedPollPeriod)

            self.__startOpenThread()
            time.sleep(3)

            if self.__sendCommand('state')[0] == 'disabled':
                print('[FAIL] reset and rejoin')
                return False
            return True
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'resetAndRejoin() Error: ' + str(e)
            )

    def configBorderRouter(
        self,
        P_Prefix,
        P_stable=1,
        P_default=1,
        P_slaac_preferred=0,
        P_Dhcp=0,
        P_preference=0,
        P_on_mesh=1,
        P_nd_dns=0,
    ):
        """configure the border router with a given prefix entry parameters

        Args:
            P_Prefix: IPv6 prefix that is available on the Thread Network
            P_stable: true if the default router is expected to be stable network data
            P_default: true if border router offers the default route for P_Prefix
            P_slaac_preferred: true if allowing auto-configure address using P_Prefix
            P_Dhcp: is true if border router is a DHCPv6 Agent
            P_preference: is two-bit signed integer indicating router preference
            P_on_mesh: is true if P_Prefix is considered to be on-mesh
            P_nd_dns: is true if border router is able to supply DNS information obtained via ND

        Returns:
            True: successful to configure the border router with a given prefix entry
            False: fail to configure the border router with a given prefix entry
        """
        print('%s call configBorderRouter' % self.port)
        prefix = self.__convertIp6PrefixStringToIp6Address(str(P_Prefix))
        print(prefix)
        try:
            parameter = ''
            prf = ''

            if P_slaac_preferred == 1:
                parameter += 'p'
                parameter += 'a'

            if P_stable == 1:
                parameter += 's'

            if P_default == 1:
                parameter += 'r'

            if P_Dhcp == 1:
                parameter += 'd'

            if P_on_mesh == 1:
                parameter += 'o'

            if P_preference == 1:
                prf = 'high'
            elif P_preference == 0:
                prf = 'med'
            elif P_preference == -1:
                prf = 'low'
            else:
                pass

            cmd = 'prefix add %s/64 %s %s' % (prefix, parameter, prf)
            print(cmd)
            if self.__sendCommand(cmd)[-1] == 'Done':
                # if prefix configured before starting OpenThread stack
                # do not send out server data ntf pro-actively
                if not self.__isOpenThreadRunning():
                    return True
                else:
                    # send server data ntf to leader
                    return self.__sendCommand('netdataregister')[-1] == 'Done'
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'configBorderRouter() Error: ' + str(e)
            )

    def setNetworkIDTimeout(self, iNwkIDTimeOut):
        """set networkid timeout for Thread device

        Args:
            iNwkIDTimeOut: a given NETWORK_ID_TIMEOUT

        Returns:
            True: successful to set NETWORK_ID_TIMEOUT
            False: fail to set NETWORK_ID_TIMEOUT
        """
        print('%s call setNetworkIDTimeout' % self.port)
        print(iNwkIDTimeOut)
        iNwkIDTimeOut /= 1000
        try:
            cmd = 'networkidtimeout %s' % str(iNwkIDTimeOut)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setNetworkIDTimeout() Error: ' + str(e)
            )

    def setKeepAliveTimeOut(self, iTimeOut):
        """set keep alive timeout for device
           has been deprecated and also set SED polling rate

        Args:
            iTimeOut: data poll period for sleepy end device

        Returns:
            True: successful to set the data poll period for SED
            False: fail to set the data poll period for SED
        """
        print('%s call setKeepAliveTimeOut' % self.port)
        iTimeOut *= 1000
        print(int(iTimeOut))
        try:
            cmd = 'pollperiod %d' % int(iTimeOut)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setKeepAliveTimeOut() Error: ' + str(e)
            )

    def setKeySequenceCounter(self, iKeySequenceValue):
        """ set the Key sequence counter corresponding to Thread Network master key

        Args:
            iKeySequenceValue: key sequence value

        Returns:
            True: successful to set the key sequence
            False: fail to set the key sequence
        """
        print('%s call setKeySequenceCounter' % self.port)
        print(iKeySequenceValue)
        try:
            cmd = 'keysequence counter %s' % str(iKeySequenceValue)
            if self.__sendCommand(cmd)[-1] == 'Done':
                time.sleep(1)
                return True
            else:
                return False
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setKeySequenceCounter() Error; ' + str(e)
            )

    def getKeySequenceCounter(self):
        """get current Thread Network key sequence"""
        print('%s call getKeySequenceCounter' % self.port)
        keySequence = ''
        keySequence = self.__sendCommand('keysequence counter')[0]
        return keySequence

    def incrementKeySequenceCounter(self, iIncrementValue=1):
        """increment the key sequence with a given value

        Args:
            iIncrementValue: specific increment value to be added

        Returns:
            True: successful to increment the key sequence with a given value
            False: fail to increment the key sequence with a given value
        """
        print('%s call incrementKeySequenceCounter' % self.port)
        print(iIncrementValue)
        currentKeySeq = ''
        try:
            currentKeySeq = self.getKeySequenceCounter()
            keySequence = int(currentKeySeq, 10) + iIncrementValue
            print(keySequence)
            return self.setKeySequenceCounter(keySequence)
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'incrementKeySequenceCounter() Error: ' + str(e)
            )

    def setNetworkDataRequirement(self, eDataRequirement):
        """set whether the Thread device requires the full network data
           or only requires the stable network data

        Args:
            eDataRequirement: is true if requiring the full network data

        Returns:
            True: successful to set the network requirement
        """
        print('%s call setNetworkDataRequirement' % self.port)
        print(eDataRequirement)

        if eDataRequirement == Device_Data_Requirement.ALL_DATA:
            self.networkDataRequirement = 'n'
        return True

    def configExternalRouter(self, P_Prefix, P_stable, R_Preference=0):
        """configure border router with a given external route prefix entry

        Args:
            P_Prefix: IPv6 prefix for the route
            P_Stable: is true if the external route prefix is stable network data
            R_Preference: a two-bit signed integer indicating Router preference
                          1: high
                          0: medium
                         -1: low

        Returns:
            True: successful to configure the border router with a given external route prefix
            False: fail to configure the border router with a given external route prefix
        """
        print('%s call configExternalRouter' % self.port)
        print(P_Prefix)
        stable = ''
        prefix = self.__convertIp6PrefixStringToIp6Address(str(P_Prefix))
        try:
            if R_Preference == 1:
                prf = 'high'
            elif R_Preference == 0:
                prf = 'med'
            elif R_Preference == -1:
                prf = 'low'
            else:
                pass

            if P_stable:
                stable += 's'
                cmd = 'route add %s/64 %s %s' % (prefix, stable, prf)
            else:
                cmd = 'route add %s/64 %s' % (prefix, prf)
            print(cmd)

            if self.__sendCommand(cmd)[-1] == 'Done':
                # send server data ntf to leader
                return self.__sendCommand('netdataregister')[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'configExternalRouter() Error: ' + str(e)
            )

    def getNeighbouringRouters(self):
        """get neighboring routers information

        Returns:
            neighboring routers' extended address
        """
        print('%s call getNeighbouringRouters' % self.port)
        try:
            routerInfo = []
            routerList = []
            routerList = self.__sendCommand('router list')[0].split()
            print(routerList)

            if 'Done' in routerList:
                print('no neighbouring routers')
                return None

            for index in routerList:
                router = []
                cmd = 'router %s' % index
                router = self.__sendCommand(cmd)

                for line in router:
                    if 'Done' in line:
                        break
                    # elif 'Rloc' in line:
                    #    rloc16 = line.split()[1]
                    elif 'Ext Addr' in line:
                        eui = line.split()[2]
                        routerInfo.append(int(eui, 16))
                    # elif 'LQI In' in line:
                    #    lqi_in = line.split()[1]
                    # elif 'LQI Out' in line:
                    #    lqi_out = line.split()[1]
                    else:
                        pass

            print(routerInfo)
            return routerInfo
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'getNeighbouringDevice() Error: ' + str(e)
            )

    def getChildrenInfo(self):
        """get all children information

        Returns:
            children's extended address
        """
        print('%s call getChildrenInfo' % self.port)
        try:
            childrenInfoAll = []
            childrenInfo = {'EUI': 0, 'Rloc16': 0, 'MLEID': ''}
            childrenList = self.__sendCommand('child list')[0].split()
            print(childrenList)

            if 'Done' in childrenList:
                print('no children')
                return None

            for index in childrenList:
                cmd = 'child %s' % index
                child = []
                child = self.__sendCommand(cmd)

                for line in child:
                    if 'Done' in line:
                        break
                    elif 'Rloc' in line:
                        rloc16 = line.split()[1]
                    elif 'Ext Addr' in line:
                        eui = line.split()[2]
                    # elif 'Child ID' in line:
                    #    child_id = line.split()[2]
                    # elif 'Mode' in line:
                    #    mode = line.split()[1]
                    else:
                        pass

                childrenInfo['EUI'] = int(eui, 16)
                childrenInfo['Rloc16'] = int(rloc16, 16)
                # children_info['MLEID'] = self.getMLEID()

                childrenInfoAll.append(childrenInfo['EUI'])
                # childrenInfoAll.append(childrenInfo)

            print(childrenInfoAll)
            return childrenInfoAll
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'getChildrenInfo() Error: ' + str(e)
            )

    def setXpanId(self, xPanId):
        """set extended PAN ID of Thread Network

        Args:
            xPanId: extended PAN ID in hex format

        Returns:
            True: successful to set the extended PAN ID
            False: fail to set the extended PAN ID
        """
        xpanid = ''
        print('%s call setXpanId' % self.port)
        print(xPanId)
        try:
            if not isinstance(xPanId, str):
                xpanid = self.__convertLongToHex(xPanId, 16)
                cmd = 'extpanid %s' % xpanid
                datasetCmd = 'dataset extpanid %s' % xpanid
            else:
                xpanid = xPanId
                cmd = 'extpanid %s' % xpanid
                datasetCmd = 'dataset extpanid %s' % xpanid

            self.xpanId = xpanid
            self.hasActiveDatasetToCommit = True
            return (
                self.__sendCommand(cmd)[-1] == 'Done'
                and self.__sendCommand(datasetCmd)[-1] == 'Done'
            )
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setXpanId() Error: ' + str(e))

    def getNeighbouringDevices(self):
        """gets the neighboring devices' extended address to compute the DUT
           extended address automatically

        Returns:
            A list including extended address of neighboring routers, parent
            as well as children
        """
        print('%s call getNeighbouringDevices' % self.port)
        neighbourList = []

        # get parent info
        parentAddr = self.getParentAddress()
        if parentAddr != 0:
            neighbourList.append(parentAddr)

        # get ED/SED children info
        childNeighbours = self.getChildrenInfo()
        if childNeighbours is not None and len(childNeighbours) > 0:
            for entry in childNeighbours:
                neighbourList.append(entry)

        # get neighboring routers info
        routerNeighbours = self.getNeighbouringRouters()
        if routerNeighbours is not None and len(routerNeighbours) > 0:
            for entry in routerNeighbours:
                neighbourList.append(entry)

        print(neighbourList)
        return neighbourList

    def setPartationId(self, partationId):
        """set Thread Network Partition ID

        Args:
            partitionId: partition id to be set by leader

        Returns:
            True: successful to set the Partition ID
            False: fail to set the Partition ID
        """
        print('%s call setPartationId' % self.port)
        print(partationId)

        cmd = 'leaderpartitionid %s' % (str(hex(partationId)).rstrip('L'))
        print(cmd)
        return self.__sendCommand(cmd)[-1] == 'Done'

    def getGUA(self, filterByPrefix=None):
        """get expected global unicast IPv6 address of Thread device

        note: existing filterByPrefix are string of in lowercase. e.g.
        '2001' or '2001:0db8:0001:0000".

        Args:
            filterByPrefix: a given expected global IPv6 prefix to be matched

        Returns:
            a global IPv6 address
        """
        print('%s call getGUA' % self.port)
        print(filterByPrefix)
        globalAddrs = []
        try:
            # get global addrs set if multiple
            globalAddrs = self.__getGlobal()

            if filterByPrefix is None:
                return globalAddrs[0]
            else:
                for fullIp in globalAddrs:
                    if fullIp.startswith(filterByPrefix):
                        print('target global %s' % fullIp)
                        return fullIp
                print('no global address matched')
                return str(globalAddrs[0])
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('getGUA() Error: ' + str(e))

    def getShortAddress(self):
        """get Rloc16 short address of Thread device"""
        print('%s call getShortAddress' % self.port)
        return self.getRloc16()

    def getULA64(self):
        """get mesh local EID of Thread device"""
        print('%s call getULA64' % self.port)
        return self.__sendCommand('ipaddr mleid')[0]

    def setMLPrefix(self, sMeshLocalPrefix):
        """set mesh local prefix"""
        print('%s call setMLPrefix' % self.port)
        try:
            cmd = 'dataset meshlocalprefix %s' % sMeshLocalPrefix
            self.hasActiveDatasetToCommit = True
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setMLPrefix() Error: ' + str(e))

    def getML16(self):
        """get mesh local 16 unicast address (Rloc)"""
        print('%s call getML16' % self.port)
        return self.getRloc()

    def downgradeToDevice(self):
        pass

    def upgradeToRouter(self):
        pass

    def forceSetSlaac(self, slaacAddress):
        """force to set a slaac IPv6 address to Thread interface

        Args:
            slaacAddress: a slaac IPv6 address to be set

        Returns:
            True: successful to set slaac address to Thread interface
            False: fail to set slaac address to Thread interface
        """
        print('%s call forceSetSlaac' % self.port)
        print(slaacAddress)
        try:
            cmd = 'ipaddr add %s' % str(slaacAddress)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'forceSetSlaac() Error: ' + str(e)
            )

    def setSleepyNodePollTime(self):
        pass

    def enableAutoDUTObjectFlag(self):
        """set AutoDUTenable flag"""
        print('%s call enableAutoDUTObjectFlag' % self.port)
        self.AutoDUTEnable = True

    def getChildTimeoutValue(self):
        """get child timeout"""
        print('%s call getChildTimeoutValue' % self.port)
        childTimeout = self.__sendCommand('childtimeout')[0]
        return int(childTimeout)

    def diagnosticGet(self, strDestinationAddr, listTLV_ids=[]):
        if not listTLV_ids:
            return

        if not len(listTLV_ids):
            return

        cmd = 'networkdiagnostic get %s %s' % (
            strDestinationAddr,
            ' '.join([str(tlv) for tlv in listTLV_ids]),
        )
        print(cmd)

        return self._sendline(cmd)

    def diagnosticReset(self, strDestinationAddr, listTLV_ids=[]):
        if not listTLV_ids:
            return

        if not len(listTLV_ids):
            return

        cmd = 'networkdiagnostic reset %s %s' % (
            strDestinationAddr,
            ' '.join([str(tlv) for tlv in listTLV_ids]),
        )
        print(cmd)

        return self.__sendCommand(cmd)

    def diagnosticQuery(self, strDestinationAddr, listTLV_ids=[]):
        self.diagnosticGet(strDestinationAddr, listTLV_ids)

    def startNativeCommissioner(self, strPSKc='GRLpassWord'):
        # TODO: Support the whole Native Commissioner functionality
        # Currently it only aims to trigger a Discovery Request message to pass
        # Certification test 5.8.4
        print('%s call startNativeCommissioner' % self.port)
        self.__sendCommand('ifconfig up')
        cmd = 'joiner start %s' % (strPSKc)
        print(cmd)
        if self.__sendCommand(cmd)[-1] == 'Done':
            return True
        else:
            return False

    def startCollapsedCommissioner(self):
        """start Collapsed Commissioner

        Returns:
            True: successful to start Commissioner
            False: fail to start Commissioner
        """
        print('%s call startCollapsedCommissioner' % self.port)
        if self.__startOpenThread():
            time.sleep(20)
            cmd = 'commissioner start'
            print(cmd)
            if self.__sendCommand(cmd)[-1] == 'Done':
                self.isActiveCommissioner = True
                time.sleep(20)  # time for petition process
                return True
        return False

    def setJoinKey(self, strPSKc):
        pass

    def scanJoiner(self, xEUI='*', strPSKd='threadjpaketest'):
        """scan Joiner

        Args:
            xEUI: Joiner's EUI-64
            strPSKd: Joiner's PSKd for commissioning

        Returns:
            True: successful to add Joiner's steering data
            False: fail to add Joiner's steering data
        """
        print('%s call scanJoiner' % self.port)

        # long timeout value to avoid automatic joiner removal (in seconds)
        timeout = 500

        if not isinstance(xEUI, str):
            eui64 = self.__convertLongToHex(xEUI, 16)
        else:
            eui64 = xEUI

        cmd = 'commissioner joiner add %s %s %s' % (
            eui64,
            strPSKd,
            str(timeout),
        )
        print(cmd)
        if self.__sendCommand(cmd)[-1] == 'Done':
            if self.logThreadStatus == self.logStatus['stop']:
                self.logThread = ThreadRunner.run(
                    target=self.__readCommissioningLogs, args=(120,)
                )
            return True
        else:
            return False

    def setProvisioningUrl(self, strURL='grl.com'):
        """set provisioning Url

        Args:
            strURL: Provisioning Url string

        Returns:
            True: successful to set provisioning Url
            False: fail to set provisioning Url
        """
        print('%s call setProvisioningUrl' % self.port)
        self.provisioningUrl = strURL
        if self.deviceRole == Thread_Device_Role.Commissioner:
            cmd = 'commissioner provisioningurl %s' % (strURL)
            return self.__sendCommand(cmd)[-1] == 'Done'
        return True

    def allowCommission(self):
        """start commissioner candidate petition process

        Returns:
            True: successful to start commissioner candidate petition process
            False: fail to start commissioner candidate petition process
        """
        print('%s call allowCommission' % self.port)
        try:
            cmd = 'commissioner start'
            print(cmd)
            if self.__sendCommand(cmd)[-1] == 'Done':
                self.isActiveCommissioner = True
                # time for petition process and at least one keep alive
                time.sleep(40)
                return True
            else:
                return False
        except Exception as e:
            ModuleHelper.writeintodebuglogger(
                'allowcommission() error: ' + str(e)
            )

    def joinCommissioned(self, strPSKd='threadjpaketest', waitTime=20):
        """start joiner

        Args:
            strPSKd: Joiner's PSKd

        Returns:
            True: successful to start joiner
            False: fail to start joiner
        """
        print('%s call joinCommissioned' % self.port)
        self.__sendCommand('ifconfig up')
        cmd = 'joiner start %s %s' % (strPSKd, self.provisioningUrl)
        print(cmd)
        if self.__sendCommand(cmd)[-1] == 'Done':
            maxDuration = 150  # seconds
            self.joinCommissionedStatus = self.joinStatus['ongoing']

            if self.logThreadStatus == self.logStatus['stop']:
                self.logThread = ThreadRunner.run(
                    target=self.__readCommissioningLogs, args=(maxDuration,)
                )

            t_end = time.time() + maxDuration
            while time.time() < t_end:
                if self.joinCommissionedStatus == self.joinStatus['succeed']:
                    break
                elif self.joinCommissionedStatus == self.joinStatus['failed']:
                    return False

                time.sleep(1)

            self.__sendCommand('thread start')
            time.sleep(30)
            return True
        else:
            return False

    def getCommissioningLogs(self):
        """get Commissioning logs

        Returns:
           Commissioning logs
        """
        rawLogs = self.logThread.get()
        ProcessedLogs = []
        payload = []
        while not rawLogs.empty():
            rawLogEach = rawLogs.get()
            print(rawLogEach)
            if '[THCI]' not in rawLogEach:
                continue

            EncryptedPacket = PlatformDiagnosticPacket()
            infoList = rawLogEach.split('[THCI]')[1].split(']')[0].split('|')
            for eachInfo in infoList:
                print(eachInfo)
                info = eachInfo.split('=')
                infoType = info[0].strip()
                infoValue = info[1].strip()
                if 'direction' in infoType:
                    EncryptedPacket.Direction = (
                        PlatformDiagnosticPacket_Direction.IN
                        if 'recv' in infoValue
                        else PlatformDiagnosticPacket_Direction.OUT
                        if 'send' in infoValue
                        else PlatformDiagnosticPacket_Direction.UNKNOWN
                    )
                elif 'type' in infoType:
                    EncryptedPacket.Type = (
                        PlatformDiagnosticPacket_Type.JOIN_FIN_req
                        if 'JOIN_FIN.req' in infoValue
                        else PlatformDiagnosticPacket_Type.JOIN_FIN_rsp
                        if 'JOIN_FIN.rsp' in infoValue
                        else PlatformDiagnosticPacket_Type.JOIN_ENT_req
                        if 'JOIN_ENT.ntf' in infoValue
                        else PlatformDiagnosticPacket_Type.JOIN_ENT_rsp
                        if 'JOIN_ENT.rsp' in infoValue
                        else PlatformDiagnosticPacket_Type.UNKNOWN
                    )
                elif 'len' in infoType:
                    bytesInEachLine = 16
                    EncryptedPacket.TLVsLength = int(infoValue)
                    payloadLineCount = (
                        int(infoValue) + bytesInEachLine - 1
                    ) / bytesInEachLine
                    while payloadLineCount > 0:
                        payloadLineCount = payloadLineCount - 1
                        payloadLine = rawLogs.get()
                        payloadSplit = payloadLine.split('|')
                        for block in range(1, 3):
                            payloadBlock = payloadSplit[block]
                            payloadValues = payloadBlock.split(' ')
                            for num in range(1, 9):
                                if '..' not in payloadValues[num]:
                                    payload.append(int(payloadValues[num], 16))

                    EncryptedPacket.TLVs = (
                        PlatformPackets.read(EncryptedPacket.Type, payload)
                        if payload != []
                        else []
                    )

            ProcessedLogs.append(EncryptedPacket)
        return ProcessedLogs

    def MGMT_ED_SCAN(
        self,
        sAddr,
        xCommissionerSessionId,
        listChannelMask,
        xCount,
        xPeriod,
        xScanDuration,
    ):
        """send MGMT_ED_SCAN message to a given destinaition.

        Args:
            sAddr: IPv6 destination address for this message
            xCommissionerSessionId: commissioner session id
            listChannelMask: a channel array to indicate which channels to be scaned
            xCount: number of IEEE 802.15.4 ED Scans (milliseconds)
            xPeriod: Period between successive IEEE802.15.4 ED Scans (milliseconds)
            xScanDuration: ScanDuration when performing an IEEE 802.15.4 ED Scan (milliseconds)

        Returns:
            True: successful to send MGMT_ED_SCAN message.
            False: fail to send MGMT_ED_SCAN message
        """
        print('%s call MGMT_ED_SCAN' % self.port)
        channelMask = ''
        channelMask = '0x' + self.__convertLongToHex(
            self.__convertChannelMask(listChannelMask)
        )
        try:
            cmd = 'commissioner energy %s %s %s %s %s' % (
                channelMask,
                xCount,
                xPeriod,
                xScanDuration,
                sAddr,
            )
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.writeintodebuglogger(
                'MGMT_ED_SCAN() error: ' + str(e)
            )

    def MGMT_PANID_QUERY(
        self, sAddr, xCommissionerSessionId, listChannelMask, xPanId
    ):
        """send MGMT_PANID_QUERY message to a given destination

        Args:
            xPanId: a given PAN ID to check the conflicts

        Returns:
            True: successful to send MGMT_PANID_QUERY message.
            False: fail to send MGMT_PANID_QUERY message.
        """
        print('%s call MGMT_PANID_QUERY' % self.port)
        panid = ''
        channelMask = ''
        channelMask = '0x' + self.__convertLongToHex(
            self.__convertChannelMask(listChannelMask)
        )

        if not isinstance(xPanId, str):
            panid = str(hex(xPanId))

        try:
            cmd = 'commissioner panid %s %s %s' % (panid, channelMask, sAddr)
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.writeintodebuglogger(
                'MGMT_PANID_QUERY() error: ' + str(e)
            )

    def MGMT_ANNOUNCE_BEGIN(
        self, sAddr, xCommissionerSessionId, listChannelMask, xCount, xPeriod
    ):
        """send MGMT_ANNOUNCE_BEGIN message to a given destination

        Returns:
            True: successful to send MGMT_ANNOUNCE_BEGIN message.
            False: fail to send MGMT_ANNOUNCE_BEGIN message.
        """
        print('%s call MGMT_ANNOUNCE_BEGIN' % self.port)
        channelMask = ''
        channelMask = '0x' + self.__convertLongToHex(
            self.__convertChannelMask(listChannelMask)
        )
        try:
            cmd = 'commissioner announce %s %s %s %s' % (
                channelMask,
                xCount,
                xPeriod,
                sAddr,
            )
            print(cmd)
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.writeintodebuglogger(
                'MGMT_ANNOUNCE_BEGIN() error: ' + str(e)
            )

    def MGMT_ACTIVE_GET(self, Addr='', TLVs=[]):
        """send MGMT_ACTIVE_GET command

        Returns:
            True: successful to send MGMT_ACTIVE_GET
            False: fail to send MGMT_ACTIVE_GET
        """
        print('%s call MGMT_ACTIVE_GET' % self.port)
        try:
            cmd = 'dataset mgmtgetcommand active'

            if Addr != '':
                cmd += ' address '
                cmd += Addr

            if len(TLVs) != 0:
                tlvs = ''.join(hex(tlv).lstrip('0x').zfill(2) for tlv in TLVs)
                cmd += ' binary '
                cmd += tlvs

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_ACTIVE_GET() Error: ' + str(e)
            )

    def MGMT_ACTIVE_SET(
        self,
        sAddr='',
        xCommissioningSessionId=None,
        listActiveTimestamp=None,
        listChannelMask=None,
        xExtendedPanId=None,
        sNetworkName=None,
        sPSKc=None,
        listSecurityPolicy=None,
        xChannel=None,
        sMeshLocalPrefix=None,
        xMasterKey=None,
        xPanId=None,
        xTmfPort=None,
        xSteeringData=None,
        xBorderRouterLocator=None,
        BogusTLV=None,
        xDelayTimer=None,
    ):
        """send MGMT_ACTIVE_SET command

        Returns:
            True: successful to send MGMT_ACTIVE_SET
            False: fail to send MGMT_ACTIVE_SET
        """
        print('%s call MGMT_ACTIVE_SET' % self.port)
        try:
            cmd = 'dataset mgmtsetcommand active'

            if listActiveTimestamp is not None:
                cmd += ' activetimestamp '
                cmd += str(listActiveTimestamp[0])

            if xExtendedPanId is not None:
                cmd += ' extpanid '
                xpanid = self.__convertLongToHex(xExtendedPanId, 16)

                cmd += xpanid

            if sNetworkName is not None:
                cmd += ' networkname '
                cmd += str(sNetworkName)

            if xChannel is not None:
                cmd += ' channel '
                cmd += str(xChannel)

            if sMeshLocalPrefix is not None:
                cmd += ' localprefix '
                cmd += str(sMeshLocalPrefix)

            if xMasterKey is not None:
                cmd += ' masterkey '
                key = self.__convertLongToHex(xMasterKey, 32)

                cmd += key

            if xPanId is not None:
                cmd += ' panid '
                cmd += str(xPanId)

            if listChannelMask is not None:
                cmd += ' channelmask '
                cmd += '0x' + self.__convertLongToHex(
                    self.__convertChannelMask(listChannelMask)
                )

            if (
                sPSKc is not None
                or listSecurityPolicy is not None
                or xCommissioningSessionId is not None
                or xTmfPort is not None
                or xSteeringData is not None
                or xBorderRouterLocator is not None
                or BogusTLV is not None
            ):
                cmd += ' binary '

            if sPSKc is not None:
                cmd += '0410'
                stretchedPskc = Thread_PBKDF2.get(
                    sPSKc,
                    ModuleHelper.Default_XpanId,
                    ModuleHelper.Default_NwkName,
                )
                pskc = hex(stretchedPskc).rstrip('L').lstrip('0x')

                if len(pskc) < 32:
                    pskc = pskc.zfill(32)

                cmd += pskc

            if listSecurityPolicy is not None:
                cmd += '0c03'

                rotationTime = 0
                policyBits = 0

                # previous passing way listSecurityPolicy=[True, True, 3600,
                # False, False, True]
                if len(listSecurityPolicy) == 6:
                    rotationTime = listSecurityPolicy[2]

                    # the last three reserved bits must be 1
                    policyBits = 0b00000111

                    if listSecurityPolicy[0]:
                        policyBits = policyBits | 0b10000000
                    if listSecurityPolicy[1]:
                        policyBits = policyBits | 0b01000000
                    if listSecurityPolicy[3]:
                        policyBits = policyBits | 0b00100000
                    if listSecurityPolicy[4]:
                        policyBits = policyBits | 0b00010000
                    if listSecurityPolicy[5]:
                        policyBits = policyBits | 0b00001000
                else:
                    # new passing way listSecurityPolicy=[3600, 0b11001111]
                    rotationTime = listSecurityPolicy[0]
                    policyBits = listSecurityPolicy[1]

                policy = str(hex(rotationTime))[2:]

                if len(policy) < 4:
                    policy = policy.zfill(4)

                cmd += policy

                cmd += str(hex(policyBits))[2:]

            if xCommissioningSessionId is not None:
                cmd += '0b02'
                sessionid = str(hex(xCommissioningSessionId))[2:]

                if len(sessionid) < 4:
                    sessionid = sessionid.zfill(4)

                cmd += sessionid

            if xBorderRouterLocator is not None:
                cmd += '0902'
                locator = str(hex(xBorderRouterLocator))[2:]

                if len(locator) < 4:
                    locator = locator.zfill(4)

                cmd += locator

            if xSteeringData is not None:
                steeringData = self.__convertLongToHex(xSteeringData)
                cmd += '08' + str(len(steeringData) / 2).zfill(2)
                cmd += steeringData

            if BogusTLV is not None:
                cmd += '8202aa55'

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_ACTIVE_SET() Error: ' + str(e)
            )

    def MGMT_PENDING_GET(self, Addr='', TLVs=[]):
        """send MGMT_PENDING_GET command

        Returns:
            True: successful to send MGMT_PENDING_GET
            False: fail to send MGMT_PENDING_GET
        """
        print('%s call MGMT_PENDING_GET' % self.port)
        try:
            cmd = 'dataset mgmtgetcommand pending'

            if Addr != '':
                cmd += ' address '
                cmd += Addr

            if len(TLVs) != 0:
                tlvs = ''.join(hex(tlv).lstrip('0x').zfill(2) for tlv in TLVs)
                cmd += ' binary '
                cmd += tlvs

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_PENDING_GET() Error: ' + str(e)
            )

    def MGMT_PENDING_SET(
        self,
        sAddr='',
        xCommissionerSessionId=None,
        listPendingTimestamp=None,
        listActiveTimestamp=None,
        xDelayTimer=None,
        xChannel=None,
        xPanId=None,
        xMasterKey=None,
        sMeshLocalPrefix=None,
        sNetworkName=None,
    ):
        """send MGMT_PENDING_SET command

        Returns:
            True: successful to send MGMT_PENDING_SET
            False: fail to send MGMT_PENDING_SET
        """
        print('%s call MGMT_PENDING_SET' % self.port)
        try:
            cmd = 'dataset mgmtsetcommand pending'

            if listPendingTimestamp is not None:
                cmd += ' pendingtimestamp '
                cmd += str(listPendingTimestamp[0])

            if listActiveTimestamp is not None:
                cmd += ' activetimestamp '
                cmd += str(listActiveTimestamp[0])

            if xDelayTimer is not None:
                cmd += ' delaytimer '
                cmd += str(xDelayTimer)
                # cmd += ' delaytimer 3000000'

            if xChannel is not None:
                cmd += ' channel '
                cmd += str(xChannel)

            if xPanId is not None:
                cmd += ' panid '
                cmd += str(xPanId)

            if xMasterKey is not None:
                cmd += ' masterkey '
                key = self.__convertLongToHex(xMasterKey, 32)

                cmd += key

            if sMeshLocalPrefix is not None:
                cmd += ' localprefix '
                cmd += str(sMeshLocalPrefix)

            if sNetworkName is not None:
                cmd += ' networkname '
                cmd += str(sNetworkName)

            if xCommissionerSessionId is not None:
                cmd += ' binary '
                cmd += '0b02'
                sessionid = str(hex(xCommissionerSessionId))[2:]

                if len(sessionid) < 4:
                    sessionid = sessionid.zfill(4)

                cmd += sessionid

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_PENDING_SET() Error: ' + str(e)
            )

    def MGMT_COMM_GET(self, Addr='ff02::1', TLVs=[]):
        """send MGMT_COMM_GET command

        Returns:
            True: successful to send MGMT_COMM_GET
            False: fail to send MGMT_COMM_GET
        """
        print('%s call MGMT_COMM_GET' % self.port)
        try:
            cmd = 'commissioner mgmtget'

            if len(TLVs) != 0:
                tlvs = ''.join(hex(tlv).lstrip('0x').zfill(2) for tlv in TLVs)
                cmd += ' binary '
                cmd += tlvs

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_COMM_GET() Error: ' + str(e)
            )

    def MGMT_COMM_SET(
        self,
        Addr='ff02::1',
        xCommissionerSessionID=None,
        xSteeringData=None,
        xBorderRouterLocator=None,
        xChannelTlv=None,
        ExceedMaxPayload=False,
    ):
        """send MGMT_COMM_SET command

        Returns:
            True: successful to send MGMT_COMM_SET
            False: fail to send MGMT_COMM_SET
        """
        print('%s call MGMT_COMM_SET' % self.port)
        try:
            cmd = 'commissioner mgmtset'

            if xCommissionerSessionID is not None:
                # use assigned session id
                cmd += ' sessionid '
                cmd += str(xCommissionerSessionID)
            elif xCommissionerSessionID is None:
                # use original session id
                if self.isActiveCommissioner is True:
                    cmd += ' sessionid '
                    cmd += self.__getCommissionerSessionId()
                else:
                    pass

            if xSteeringData is not None:
                cmd += ' steeringdata '
                cmd += str(hex(xSteeringData)[2:])

            if xBorderRouterLocator is not None:
                cmd += ' locator '
                cmd += str(hex(xBorderRouterLocator))

            if xChannelTlv is not None:
                cmd += ' binary '
                cmd += '000300' + hex(xChannelTlv).lstrip('0x').zfill(4)

            print(cmd)

            return self.__sendCommand(cmd)[-1] == 'Done'

        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'MGMT_COMM_SET() Error: ' + str(e)
            )

    def setActiveDataset(self, listActiveDataset=[]):
        print('%s call setActiveDataset' % self.port)

    def setCommisionerMode(self):
        print('%s call setCommissionerMode' % self.port)

    def setPSKc(self, strPSKc):
        print('%s call setPSKc' % self.port)
        try:
            cmd = 'dataset pskc %s' % strPSKc
            self.hasActiveDatasetToCommit = True
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger('setPSKc() Error: ' + str(e))

    def setActiveTimestamp(self, xActiveTimestamp):
        print('%s call setActiveTimestamp' % self.port)
        try:
            self.activetimestamp = xActiveTimestamp
            cmd = 'dataset activetimestamp %s' % str(xActiveTimestamp)
            self.hasActiveDatasetToCommit = True
            return self.__sendCommand(cmd)[-1] == 'Done'
        except Exception as e:
            ModuleHelper.WriteIntoDebugLogger(
                'setActiveTimestamp() Error: ' + str(e)
            )

    def setUdpJoinerPort(self, portNumber):
        """set Joiner UDP Port

        Args:
            portNumber: Joiner UDP Port number

        Returns:
            True: successful to set Joiner UDP Port
            False: fail to set Joiner UDP Port
        """
        print('%s call setUdpJoinerPort' % self.port)
        cmd = 'joinerport %d' % portNumber
        print(cmd)
        return self.__sendCommand(cmd)[-1] == 'Done'

    def commissionerUnregister(self):
        """stop commissioner

        Returns:
            True: successful to stop commissioner
            False: fail to stop commissioner
        """
        print('%s call commissionerUnregister' % self.port)
        cmd = 'commissioner stop'
        print(cmd)
        return self.__sendCommand(cmd)[-1] == 'Done'

    def sendBeacons(
        self, sAddr, xCommissionerSessionId, listChannelMask, xPanId
    ):
        print('%s call sendBeacons' % self.port)
        self._sendline('scan')
        return True

    def updateRouterStatus(self):
        """force update to router as if there is child id request"""
        print('%s call updateRouterStatus' % self.port)
        cmd = 'state'
        while True:
            state = self.__sendCommand(cmd)[0]
            if state == 'detached':
                continue
            elif state == 'child':
                break
            else:
                return False

        cmd = 'state router'
        return self.__sendCommand(cmd)[-1] == 'Done'

    def setRouterThresholdValues(self, upgradeThreshold, downgradeThreshold):
        print('%s call setRouterThresholdValues' % self.port)
        self.__setRouterUpgradeThreshold(upgradeThreshold)
        self.__setRouterDowngradeThreshold(downgradeThreshold)

    def setMinDelayTimer(self, iSeconds):
        print('%s call setMinDelayTimer' % self.port)
        cmd = 'delaytimermin %s' % iSeconds
        print(cmd)
        return self.__sendCommand(cmd)[-1] == 'Done'

    def ValidateDeviceFirmware(self):
        print('%s call ValidateDeviceFirmware' % self.port)
        if 'OPENTHREAD' in self.UIStatusMsg:
            return True
        else:
            return False


text:
import nltk
from nltk.tokenize import TweetTokenizer

class Analyzer():
    """Implements sentiment analysis."""

    def __init__(self, positives, negatives):
        """Initialize Analyzer."""
        self.positives = set()
        self.negatives = set()

        # For each line in positive doc, remove white space and add each non-comment line
        for line in open('positive-words.txt'):
            word = line.strip()
            if not line.startswith(';') and not line.startswith('\n'):
                self.positives.add(word)

        # For each line in negative doc, remove white space and add each non-comment line
        for line in open('negative-words.txt'):
            word = line.strip()
            if not line.startswith(';') and not line.startswith('\n'):
                self.negatives.add(word)

    def analyze(self, text):
        """Analyze text for sentiment, returning its score."""

        # Separate text into list of individual words and make lower-case
        tokenizer = TweetTokenizer()
        tokens = tokenizer.tokenize(text)
        tokens = [str.lower() for str in tokens]

        # For each token, check if in self.positives or self.negatives
        score = 0
        for i in range(len(tokens)):
            if tokens[i] in self.positives:
                score += 1
            elif tokens[i] in self.negatives:
                score -= 1
        return score

redpajama_set_name: RedPajamaGithub