Utility script to get/set AT commands on local/remote zigbee nodes

From Digi Developer

Jump to: navigation, search

Contents

Introduction: A Utility script that gets or sets AT commands on local or associated remote zigbee nodes

This utility script is designed for an easy to use mechanism to query and set a small amount of AT commands on a local or associated remote zigbee node.

Requirements:

  • A Digi Gateway product
  • Command line access to the Digi Gateway product
  • Optional: An associated remote zigbee node

Step 1: Declarations

"""  This utility script is designed to execute AT commands for local or associated remote nodes.
 
It can both 'get' or 'set' the AT commnad, which is determined by the command line arguments 
passed to it.  See print_usage() for more details on how to use.
 
In the application we import a 'hidden' library called _zigbee.  Normally the user would import
zigbee (no leading underscore) which in turn would import the _zigbee file, however this allows 
us fewer requirements when running, as we don't have to have the probable, but not guaranteed
zigbee library to run.
 
The other two libraries used, sys and binascii.  Sys is used for the argv values, binascii is
used to interpret the results from the ddo_get_param commands.  The reason why binascii is used
instead of struct, is that struct would require knowledge of the command and its return value.
"""
 
import _zigbee as zigbee
import sys
import binascii
 
##########################################################################################
# Variable declaration
##########################################################################################
 
val    = None         # Value to set
addr   = None         # Address of the mesh node 
id     = None         # AT command to execute
dowhat = 'get'        # Flag to determine if we are setting or getting

At the start of the script we create a docstring that describes the purpose of the script. We import 3 libraries, 2 are from the standard python.zip, and the final one is a hidden script that we import directly instead of using the 'zigbee.py' wrapper file. We do this to remove the requirement of having zigbee.py present in our filesystem.

We then declare 4 variables that will be used later.

  • val: The value that the AT command will be set to.
  • addr: The 64 bit address of the zigbee node. Expected format is 11:22:33:44:55:66:77:88
  • id: The 2 character AT command code.
  • dowhat: A flag to signal whether we are getting or setting.

Step 2: Procedure Definitions

##########################################################################################
# print usage()
##########################################################################################
 
def print_usage():
  print "python %s -a address -i ID [-v Value] [-th]" %sys.argv[0]
  print ""
  print "Required:"
  print "  -a address"
  print "  -i ID"
  print ""
  print "Optional:"
  print "  -v Value"
  print ""
  print "Example:"
  print "python %s -a 11:22:33:44:55:66:77:88 -i NI -v 'Node Identifier'" %sys.argv[0]
  print ""
  print "Options:"
  print "  -a    64 bit address of the zigbee adapter you want to communicate with"
  print "  -i    ID of the variable you want to interact with"  
  print "  -v    Indicates what you want the value to be"
  print "NOTE:  To set a blank value, use -v ''"
  print ""
  sys.exit(0)

We define the print_usage() procedure, where if the user gives no, or invalid command line arguments, we print the usage of the script. It is important to be very verbose here.

##########################################################################################
# validMeshAddress
##########################################################################################
 
def validMeshAddress(addr):
  """  validMeshAddress validates that the given input matches the same format a 64 bit
  mesh address is in.  
 
  It takes one argument:
     addr - mesh address, expected format is '11:22:33:44:55:66:77:88'
 
  It returns a boolean on whether or not it passed the criteria of after being split by
  the semicolon, it has 8 elements, and each element is in the '0-F' range.
 
  """
 
  split_addr = addr.split(':')
 
  if len(split_addr) != 8:
    return False
 
  for char in split_addr:
    try:
      char = int(char, 16)
    except:
      return False

We define the validMeshAddress procedure here. We use this to determine if the input matches the format of the 64 bit hardware address a zigbee node might have. This does not guarantee that the mesh address is communicable, or exists. Just that it is in the proper format to feed into the zigbee.ddo_get_param(...) or zigbee.ddo_set_param(...) functions.

Step 3: Parsing and Validating command line arguments

##########################################################################################
# Parse Args
##########################################################################################
 
if len(sys.argv) < 2:
  print_usage()  
 
try:
  i = 1
  while i < len(sys.argv):
 
    if sys.argv[i] == '-a':
      i+=1
      addr = sys.argv[i]
 
    elif sys.argv[i] == '-v':
      i+=1
      dowhat = 'set'
      val = sys.argv[i]
 
    elif sys.argv[i] == '-i':
      i+=1
      id = sys.argv[i]
 
    else:
      print "Unrecognized parameter: %s" %sys.argv[i]
      print_usage()      
 
    i+=1
 
except:
  raise ValueError("Invalid set of parameters given: %s" %sys.argv)

The above shows how we are processing the command line arguments in 'sys.argv' list. We don't use the standard 'optparse' library for two reasons. First it doesn't not exist in the standard python.zip. Second, it increases the size of the code base one must understand to use and modify the script.

##########################################################################################
# Verify args
##########################################################################################
 
if validMeshAddress(addr) == False:
  raise ValueError("Invalid mesh address given: %s" %addr)  
else:
  addr = '[%s]!' %addr
 
if len(id) != 2:
  raise ValueError("Invalid ID given, ID must be 2 characters")

We validate the two parameters that are not flags. We verify that the address given is a possible mesh address, and we verify that the id given is of 2 characters in length.

Step 4: Main procedure

##########################################################################################  
# Main section
##########################################################################################
 
if dowhat == 'set':
 
  try:
    val = int(val)    
  except:
    pass  
 
  try:
    zigbee.ddo_set_param(addr, id, val)
  except:
    print "Could not set parameter: %s to value: %s at address: %s" %(id, val, addr)
    print "Command failed!"
    sys.exit(0)
  else:
    try:
      data = zigbee.ddo_get_param(addr, id)
      print "Set parameter: %s to Value: %s at Address: %s" %(id, data, addr)
    except:
      print "Failed to retrieve ID after setting it"

We define the process if the user decided to 'set' the AT command. First we attempt to make the 'val' variable a integer. If it fails, we don't mind. We perform a zigbee.ddo_set_param(...) using the supplied address, id, and value. We catch any exceptions, and print the details and result of the command.

elif dowhat == 'get':
 
  try:
    data = zigbee.ddo_get_param(addr, id)
  except:
    print "Could not get parameter: %s At address: %s" %(id, addr)
    print "command failed!"
  else:
    print "Parameter: %s is Value: [%s] at Address: %s" %(id, data, addr)
    try:
      print "Parameter in hexlify form is: %s" %(int(binascii.hexlify(data), 16))      
    except:
      print "Failed to interpret into Hex form."

We define the process if the user specified to 'get' the AT command. We perform a zigbee.ddo_get_param(...) with the supplied id and address. And we attempt to print it out in two formats: First the raw mode, which will work for strings and second the hexlify mode, which will print out the information as a decimal number.

If the returned value from the command is a complex byte structure, these print statements may appear as gibberish.

Notes and source

The above script is designed as a utility to quickly query and set parameters on various associated nodes from your gateway. It is not designed to replace the functionality of the WebUI or CLI interface to those nodes.

query_param.zip

Personal tools
Wiki Editing