docs: def decodeSmsPdu(pdu):
      """ Decodes SMS pdu data and returns a tuple in format (number, text)
      
      :param pdu: PDU data as a hex string, or a bytearray containing PDU octects
      :type pdu: str or bytearray
      
      :raise EncodingError: If the specified PDU data cannot be decoded
      
      :return: The decoded SMS data as a dictionary
      :rtype: dict    
      """ 
      try:
          pdu = toByteArray(pdu)
      except Exception as e:
          # Python 2 raises TypeError, Python 3 raises binascii.Error
          raise EncodingError(e)
      result = {}
      pduIter = iter(pdu)
   
      smscNumber, smscBytesRead = _decodeAddressField(pduIter, smscField=True)
      result['smsc'] = smscNumber
      result['tpdu_length'] = len(pdu) - smscBytesRead
      
      tpduFirstOctet = next(pduIter) 
      
      pduType = tpduFirstOctet & 0x03 # bits 1-0
      if pduType == 0x00: # SMS-DELIVER or SMS-DELIVER REPORT
          result['type'] = 'SMS-DELIVER'
          result['number'] = _decodeAddressField(pduIter)[0]
          result['protocol_id'] = next(pduIter)
          dataCoding = _decodeDataCoding(next(pduIter))
          result['time'] = _decodeTimestamp(pduIter)
          userDataLen = next(pduIter)
          udhPresent = (tpduFirstOctet & 0x40) != 0
          ud = _decodeUserData(pduIter, userDataLen, dataCoding, udhPresent)
          result.update(ud)
      elif pduType == 0x01: # SMS-SUBMIT or SMS-SUBMIT-REPORT
          result['type'] = 'SMS-SUBMIT'
          result['reference'] = next(pduIter) # message reference - we don't really use this
          result['number'] = _decodeAddressField(pduIter)[0]
          result['protocol_id'] = next(pduIter)
          dataCoding = _decodeDataCoding(next(pduIter))
          validityPeriodFormat = (tpduFirstOctet & 0x18) >> 3 # bits 4,3
          if validityPeriodFormat == 0x02: # TP-VP field present and integer represented (relative)
              result['validity'] = _decodeRelativeValidityPeriod(next(pduIter))
          elif validityPeriodFormat == 0x03: # TP-VP field present and semi-octet represented (absolute)            
              result['validity'] = _decodeTimestamp(pduIter)
          userDataLen = next(pduIter)
          udhPresent = (tpduFirstOctet & 0x40) != 0
          ud = _decodeUserData(pduIter, userDataLen, dataCoding, udhPresent)
          result.update(ud)
      elif pduType == 0x02: # SMS-STATUS-REPORT or SMS-COMMAND
          result['type'] = 'SMS-STATUS-REPORT'
          result['reference'] = next(pduIter)
          result['number'] = _decodeAddressField(pduIter)[0]
          result['time'] = _decodeTimestamp(pduIter)
          result['discharge'] = _decodeTimestamp(pduIter)
          result['status'] = next(pduIter)        
      else:
          raise EncodingError('Unknown SMS message type: {0}. First TPDU octet was: {1}'.format(pduType, tpduFirstOctet))
      
      return result