How to use ret_arg method in avocado

Best Python code snippet using avocado_python

wrapper.py

Source:wrapper.py Github

copy

Full Screen

1"""This script helps you wrap a Fortran subroutine so you2can call it from NCL."""3#4# This script asks you a bunch of questions about a Fortran routine5# that you want wrap and call from NCL. It then creates an interface6# C wrapper routine and a code snippet for registering the routine (this7# code snippet goes in "wrapper.c").8#9# There are some things that need to be added to this program:10# 11# 1. Recognition of work arrays12# 2. Ask if input arrays are not allowed to have missing values13# (this is checked via "contains_missing").14# 3. Needs more testing with variables that don't have leftmost15# dimensions.16# 4. More testing with scalars. I think there's something odd with these.17# 5. Better handling of array dimensions that are fixed. For example18# for an array that is 2 x nx x ny, this program doesn't handle19# the '2' part very well.20#21#22# Initialize some stuff.23#24args = []25farg_names = []26farg_cchar = []27farg_types = []28global_dsizes_names = []29global_var_names = []30global_var_types = []31global_calling_char = []32global_dsizes_names_accum = []33various_var_names = []34various_var_types = []35work_array_names = []36work_array_types = []37index_names = []38debug = True39have_leftmost = False40ntypes = ['numeric','double','float','long','integer','string','logical']41ctypes = [ 'void','double','float','long', 'int','string','logical']42reserved_names = ['i', 'ndims_leftmost', 'size_leftmost', 'size_output']43#44# Set up class that will hold information on NCL input arguments.45#46class Argument:47 def __init__(self,arg_num,name,itype,sets_otype,ndims,dsizes=None,48 min_ndims=0,dsizes_names=None,dsizes_names_str="",49 has_missing=False):50 self.arg_num = arg_num # Number of argument, -1 indicates51 # return value.52 self.name = name53 self.ntype = ntypes[itype]54 self.ctype = ctypes[itype]55 self.sets_otype = sets_otype56 self.ndims = ndims57 self.min_ndims = min_ndims58 if ndims == 1 and dsizes[0] == 1:59 self.is_scalar = True60 else:61 self.is_scalar = False62#63# These are variable names that we use in the C code to hold64# number of dimensions, dimension sizes, types, missing values, and65# temporary names for various input arguments. Note that not all of66# these names will necessarily be used in the code. They are67# conditional on several factors, like whether the type is numeric,68# and whether the array has leftmost dimensions.69#70 self.ndims_name = "ndims_" + name71 self.type_name = "type_" + name72 self.dsizes_name = "dsizes_" + name73 self.has_msg_name = "has_missing_" + name74 self.msg_name = "missing_" + name75 self.msg_dname = "missing_dbl_" + name76 self.msg_fname = "missing_flt_" + name77 self.tmp_name = "tmp_" + name78 self.index_name = "index_" + name79 if dsizes != None:80 self.dsizes = dsizes81 if dsizes_names != None:82 self.dsizes_names = dsizes_names83 self.dsizes_names_str = dsizes_names_str84 self.has_missing = has_missing85#86# Set up instructions on how to print an instance of this class.87#88 def __str__(self):89 if self.arg_num >= 0:90 str1 = "Name of argument " + str(self.arg_num) + " is '" + \91 self.name + "'\n"92 else:93 str1 = "Name of return argument is '" + self.name + "'\n"94 str1 = str1 + " NCL type is " + self.ntype + "\n"95 str1 = str1 + " C type is " + self.ctype + "\n"96 if self.has_missing:97 str1 = str1 + " This variable can contain a missing value.\n"98 if self.ndims > 0:99 if self.is_scalar:100 str1 = str1 + " This variable is a scalar\n"101 else:102 str1 = str1 + " Number of dimensions is " + str(self.ndims) + "\n"103 str1 = str1 + " Name of variable that holds # of dimemsions is " + \104 self.ndims_name + "\n"105 str1 = str1 + " Name of variable that holds dimemsion sizes is " + \106 self.dsizes_name + "\n"107 for i in range(self.ndims):108 if self.dsizes[i] > 1:109 str1 = str1 + " Dimension # " + str(i) + " is length " +\110 str(self.dsizes[i]) + "\n"111 else:112 str1 = str1 + " Dimension # " + str(i) + " is variable\n"113 else:114 str1 = str1 + " Number of dimensions is variable\n"115 if self.min_ndims > 0:116 str1 = str1 + " Number of minimum dimensions is " + \117 str(self.min_ndims) + "\n"118 for j in range(self.min_ndims):119 str1 = str1 + " Dimension " + self.ndims_name + "-" + \120 str(int(self.min_ndims-j)) + " is " + \121 self.dsizes_names[j] + "\n"122 return str1123#124# Import some stuff.125#126import sys127from string import *128#129# Begin asking for input on function/procedure.130#131print "\nIn order to wrap your Fortran subroutine, I need"132print "to ask you a few questions.\n"133#134# Is this a function or procedure?135#136forp = raw_input("Is this going to be a function (f) or procedure (p)? [f] ")137if (lower(forp) == "p"):138 isfunc = False139 wrapper_type = "procedure"140else:141 isfunc = True142 wrapper_type = "function"143#144# Get Fortran, NCL, and wrapper names of function or procedure.145#146valid = False147while not valid:148 ncl_name = raw_input("\nEnter NCL/PyNGL name of your " + wrapper_type + ": ")149 if ncl_name == "":150 print "Invalid name for NCL/PyNGL function or procedure, reenter."151 else:152 valid = True153ncl_nameW = ncl_name + "_W" # Name of wrapper.154valid = False155while not valid:156 fortran_name = raw_input("\nEnter Fortran name of your " + wrapper_type + \157 ": ")158 if fortran_name == "":159 print "Invalid name for Fortran subroutine, reenter."160 else:161 valid = True162valid = False163while not valid:164 wrapper_name = raw_input("\nEnter name you want to give the wrapper C file (without the 'W.c') " +\165 ": ")166 if wrapper_name == "":167 print "Invalid name for wrapper name, reenter."168 else:169 valid = True170fatal_str = ' NhlPError(NhlFATAL,NhlEUNKNOWN,"' + ncl_name + ': '171warn_str = ' NhlPError(NhlWARNING,NhlEUNKNOWN,"' + ncl_name + ': '172return_fatal_str = ' return(NhlFATAL);\n'173#174# How many input arguments are there?175#176valid = False177while not valid:178 rinput = raw_input('\nHow many input arguments will there be for ' + \179 ncl_name + '? ')180 try:181 num_args = int(rinput)182 if num_args < 0:183 print "Invalid number of arguments: ",num_args184 print "Reenter."185 elif num_args == 0:186 print "This script is for routines that contain arguments. Reenter."187 else:188 valid = True189 except:190 print "Must enter an integer > 0, reenter."191print "\nI need to ask you some questions about each input argument."192#193# Loop across the number of input arguments and get information194# about each one.195#196num_input_has_missing = 0 # Counter for how many input197 # variables can have missing values.198for i in range(num_args):199#200# Get name of argument.201#202 valid = False203 while not valid:204 name = raw_input("\nWhat is the name of argument # " + str(i) + "? ")205 if name == "":206 print "Invalid name, reenter."207 elif name in reserved_names or name in global_var_names:208 print "Name already in use, reenter."209 else:210 valid = True211#212# Get type of argument.213#214 print "What type is '" + name + "'? [0]"215 for j in range(len(ntypes)):216 print " ",j,":",ntypes[j]217 218 valid = False219 while not valid:220 rinput = raw_input()221 if rinput == "":222 itype = 0223 valid = True224 else:225 try:226 itype = int(rinput)227 if (itype < 0) or (itype >= len(ntypes)):228 print "Invalid type, reenter."229 else:230 valid = True231 except:232 print "Invalid type, reenter."233#234# Store this variable and its type in a list of variables we are235# keeping track of.236#237 if itype == 0:238 global_var_names.append("tmp_" + name)239 global_var_types.append(ctypes.index('double'))240 else:241 global_var_names.append(name)242 global_var_types.append(itype)243 global_calling_char.append("")244#245# If this input argument is numeric, then ask if its type246# determines the output type of the return value.247#248 if isfunc and itype == 0:249 rinput = raw_input("Does the type of " + name + " determine the type of the output? (y/n) [n] ")250 if (lower(rinput) == "y"):251 sets_otype = True252 else:253 sets_otype = False254#255# Ask about a missing value.256#257 rinput = raw_input("Can " + name + " have a _FillValue attribute? (y/n) [n] ")258 if (lower(rinput) == "y"):259 has_missing = True260 num_input_has_missing += 1261 if itype == 0:262 global_var_names.append("missing_dbl_" + name + ".doubleval")263 global_var_names.append("missing_flt_" + name + ".floatval")264 global_var_types.append(ctypes.index('double'))265 global_var_types.append(ctypes.index('float'))266 global_calling_char.append("&")267 global_calling_char.append("&")268 else:269 global_var_names.append("missing_" + name + "." + ctypes[itype] + "val")270 global_var_types.append(itype)271 global_calling_char.append("&")272 else:273 has_missing = False274#275# Get dimension sizes.276#277 print "How many dimensions does '" + name + "' have?"278 valid = False279 while not valid:280 rinput = raw_input("Enter <return> for variable dimensions: [0] ")281 if rinput == "":282 ndims = 0283 valid = True284 else:285 try:286 ndims = int(rinput)287 if ndims >= 0:288 valid = True289 else:290 print "Invalid number of dimensions, reenter."291 except:292 print "Must enter an integer, reenter."293 dsizes = None294 dsizes_names = None295 min_ndims = 0296 dsizes_names_str = ""297 if ndims > 0:298#299# Our array is a fixed number of dimensions.300#301 print "Enter dimension size of each dimension"302 print "(Hit <return> for variable dimension size)"303 dsizes = []304 for j in range(ndims):305 valid = False306 while not valid:307 rinput = raw_input("Size for dimension # " + str(j) + \308 " of argument '" + name + "': ")309 if rinput == "":310 valid = True311 dsizes.append(0)312 else:313 try:314 if int(rinput) >= 0:315 valid = True316 dsizes.append(int(rinput))317 else:318 print "Invalid size for dimension, reenter."319 except:320 print "Must enter an integer, reenter."321 else:322#323# Our array is a variable number of dimensions. That is, it has324# leftmost dimensions.325#326 have_leftmost = True327 index_names.append("index_" + name)328#329# Get the minimum dimension size required.330#331 valid = False332 while not valid:333 rinput = raw_input("How many dimensions does the Fortran routine expect for this variable? ")334 try:335 min_ndims = int(rinput)336 if min_ndims > 0:337 valid = True338 else:339 print "Invalid number of dimensions, reenter."340 except:341 print "Must enter an integer > 0."342#343# Get the names of each non-leftmost dimension size.344#345 if not (ndims == 1 and dsizes[0] == 1):346 dsizes_names = []347 dsizes_names_str = ""348 print "What are the names of each of these dimensions?" 349 if global_dsizes_names != []:350 print "You can use these existing names if they apply: " + \351 str(global_dsizes_names)352 for j in range(max(ndims,min_ndims)):353 if ndims > 0:354 dsizes_names.append(raw_input("Name of dimension " + str(j) + " : "))355 else:356 dsizes_names.append(raw_input("Name of dimension ndims_" + name + \357 "-" + str(int(min_ndims-j)) + " : "))358 if not dsizes_names[j] in global_dsizes_names: 359 global_dsizes_names.append(dsizes_names[j])360 if not dsizes_names[j] in global_var_names: 361 global_var_names.append(dsizes_names[j])362 global_var_types.append(ctypes.index('int'))363 global_calling_char.append("&")364#365# Create string for variable that will hold the size of these dimensions366# (rightmost dimensions for variables that have leftmost dimensions).367#368# For example, if the dimensions are nx, ny, and nz, then369# a variable called "nxnynz" will be created that is equal to 370# nx * ny * nz. 371#372 dsizes_names_str = dsizes_names_str + dsizes_names[j]373 if not dsizes_names_str in global_dsizes_names: 374 global_dsizes_names.append(dsizes_names_str)375 if not dsizes_names_str in global_var_names: 376 global_var_names.append(dsizes_names_str)377 global_var_types.append(ctypes.index('int'))378 global_calling_char.append("&")379#380# With all this information, create an instance of the Argument class.381#382 args.append(Argument(i,name,itype,sets_otype,ndims,dsizes,min_ndims, \383 dsizes_names,dsizes_names_str,has_missing))384#385# Get information on the return value, if a function.386#387if isfunc:388 valid = False389 while not valid:390 ret_name = raw_input("\nWhat is the name of the return value? ")391 if ret_name == "":392 print "Invalid name, reenter."393 elif ret_name in reserved_names or ret_name in global_var_names:394 print "Name already in use, reenter."395 else:396 valid = True397#398# Get type of argument.399#400 print "What type is '" + ret_name + "'? [0] "401 for j in range(len(ntypes)):402 print " ",j,":",ntypes[j]403 404 valid = False405 while not valid:406 rinput = raw_input()407 if rinput == "":408 ret_itype = 0409 valid = True410 else:411 try:412 ret_itype = int(rinput)413 if (ret_itype < 0) or (ret_itype >= len(ntypes)):414 print "Invalid type, reenter."415 else:416 valid = True417 except:418 print "Must enter an integer, reenter."419 if ret_itype == 0:420 global_var_names.append("tmp_" + ret_name)421 global_var_types.append(ctypes.index('double'))422 else:423 global_var_names.append(ret_name)424 global_var_types.append(ret_itype)425 global_calling_char.append("")426#427# Ask about a return missing value.428#429 rinput = raw_input('Can ' + ret_name + ' contain missing values? (y/n) [n] ')430 if (lower(rinput) == "y"):431 ret_has_missing = True432 else:433 ret_has_missing = False434#435# Find out which (if any) input variable the return value is dependent on.436# Only do this if there's at least one input value that can contain a437# missing value.438#439 if ret_has_missing and (num_input_has_missing > 0):440 rinput = raw_input("Is the return missing value based on any input missing values? (y/n) [y] ")441 if (lower(rinput) == "n"):442 ret_msg_depend_input = False443 else:444 ret_msg_depend_input = True445 if ret_msg_depend_input: 446 print "Select the input variable whose missing value determines"447 print "the missing value for the return variable:"448 449 for j in range(len(args)):450 if(args[j].has_missing):451 print " ",j,":",args[j].name452 453 valid = False454 while not valid:455 rinput = raw_input()456 try:457 ret_msg_depend_index = int(rinput)458 if (ret_msg_depend_index < 0) or \459 (ret_msg_depend_index >= len(args)):460 print "Invalid entry, reenter."461 else:462 valid = True463 except:464 print "Must enter an integer, reenter."465#466# Get dimension sizes.467#468 print "How many dimensions does " + ret_name + " have?"469 valid = False470 while not valid:471 rinput = raw_input("Hit <return> for variable dimensions: ")472 if rinput == "":473 ret_ndims = 0474 valid = True475 else:476 try:477 ret_ndims = int(rinput)478 if ret_ndims < 0:479 print "Invalid number of dimensions, reenter."480 else:481 valid = True482 except:483 print "Must enter an integer >= 0, reenter."484 ret_dsizes = None485 ret_dsizes_names = None486 ret_min_ndims = 0487 ret_dsizes_names_str = ""488 if ret_ndims > 0:489 print "Enter dimension size of each dimension"490 print "(Hit <return> for variable dimension size)"491 ret_dsizes = []492 for j in range(ret_ndims):493 valid = False494 while not valid:495 rinput = raw_input("Size for dimension # " + str(j) + " of return value: ")496 if rinput == "":497 ret_dsizes.append(0)498 valid = True499 else: 500 try: 501 if int(rinput) < 0:502 print "Invalid size for dimension, reenter."503 else:504 ret_dsizes.append(int(rinput))505 valid = True 506 except:507 print "Must enter an integer, reenter."508 else:509 have_leftmost = True510 index_names.append("index_" + ret_name)511#512# Get the minimum dimension size required.513#514 valid = False515 while not valid:516 rinput = raw_input("How many dimensions does the Fortran routine expect for the return value? ")517 try:518 ret_min_ndims = int(rinput)519 if ret_min_ndims <= 0:520 print "Invalid number of dimensions, reenter."521 else:522 valid = True523 except:524 print "Must enter an integer > 0, reenter."525#526# Get the names of each non-leftmost dimension size.527#528 if not (ret_ndims == 1 and ret_dsizes[0] == 1):529 ret_dsizes_names = []530 ret_dsizes_names_str = ""531 print "What are the names of each of these dimensions?" 532 if global_dsizes_names != []:533 print "You can use these existing names if they apply: " + \534 str(global_dsizes_names)535 for j in range(max(ret_ndims,ret_min_ndims)):536 if ret_ndims > 0:537 ret_dsizes_names.append(raw_input("Name of dimension " + str(j) + \538 " : "))539 else:540 ret_dsizes_names.append(raw_input("Name of dimension ndims_" + \541 ret_name + "-" + str(int(ret_min_ndims-j)) + " : "))542 if not ret_dsizes_names[j] in global_dsizes_names: 543 global_dsizes_names.append(ret_dsizes_names[j])544 if not ret_dsizes_names[j] in global_var_names: 545 global_var_names.append(ret_dsizes_names[j])546 global_var_types.append(ctypes.index('int'))547 global_calling_char.append("&")548#549# Create string for variable that will hold the size of these 550# minimum dimensions.551#552 ret_dsizes_names_str = ret_dsizes_names_str + ret_dsizes_names[j]553 if not ret_dsizes_names_str in global_dsizes_names: 554 global_dsizes_names.append(ret_dsizes_names_str)555 if not ret_dsizes_names_str in global_var_names: 556 global_var_names.append(ret_dsizes_names_str)557 global_var_types.append(ctypes.index('int'))558 global_calling_char.append("&")559#560# With this information, create an instance of the Argument class for561# the return value.562#563 ret_arg = Argument(-1,ret_name,ret_itype,False,ret_ndims,ret_dsizes,564 ret_min_ndims,ret_dsizes_names,ret_dsizes_names_str,565 ret_has_missing)566#567# Get information about how Fortran function is to be called and what568# types its input variables are.569#570valid = False571while not valid:572 rinput = raw_input('\nHow many input arguments are there for the Fortran routine ' + fortran_name + '? ')573 try:574 fnum_args = int(rinput)575 if fnum_args <= 0:576 print "Invalid number of dimensions for Fortran routine."577 print "There should be at least one dimension, reenter."578 else:579 valid = True580 except:581 print "Must enter an integer > 0, reenter."582#583# Loop through the Fortran arguments and get the name and type.584#585for i in range(fnum_args):586 print "What is the name of argument # " + str(i) + " ?"587 print "You can select one of these existing names, or supply your own."588 for j in range(len(global_var_names)):589 print " ",j,":",global_var_names[j]590 rinput = raw_input()591 valid = False592 from_list = False593 while not valid:594 try:595 ii = int(rinput)596 if (ii >= 0) or (ii < len(global_var_names)):597 valid = True598 farg_names.append(global_var_names[ii])599 farg_cchar.append(global_calling_char[ii])600 from_list = True601 else:602 print "Invalid integer, reenter."603 except:604 farg_names.append(rinput)605 various_var_names.append(rinput)606 valid = True607 rinput = raw_input("Does an '&' need to be prepended when passing '" +\608 rinput + "' to the Fortran routine? (y/n) [n] ")609 if (lower(rinput) == "y"):610 farg_cchar.append('&')611 else:612 farg_cchar.append('')613 valid = False614 while not valid:615 if from_list:616 farg_types.append(global_var_types[ii])617 valid = True618 else:619 print "What type is '" + farg_names[i] + "'? [1] "620 for j in range(len(ctypes)):621 print " ",j,":",ctypes[j]622 623 rinput = raw_input()624 if rinput == "":625 farg_types.append(1)626 various_var_types.append(1)627 valid = True628 else:629 try:630 if (int(rinput) < 0) or (int(rinput) >= len(ctypes)):631 print "Invalid type, reenter."632 else:633 farg_types.append(int(rinput))634 various_var_types.append(int(rinput))635 valid = True636 except:637 print "Must enter an integer, reenter."638#639# Print information about each argument for debugging purposes.640#641if debug:642 for i in range(len(args)):643 print args[i]644 if isfunc:645 print ret_arg646#647# Open wrapper file and start writing to it, but first648# make sure this is acceptable.649#650print 'I will be creating the files ' + wrapper_name + 'W.c and ' + \651 'wrapper_' + ncl_name + '.c.'652print 'The contents of wrapper_' + ncl_name + '.c should be copied over to wrapper.c.'653okay = raw_input("Is this okay? (y/n) [y] ")654if (lower(okay) == "n"):655 print "Bye!"656 sys.exit()657#658# Open the files. The first one (w1file) is for actually wrapping the659# Fortran code, and the second one (w2file) is for registering the660# function or procedure. The second file is for temporary use only: you661# should copy its contents to "wrapper.c" where all the built-in 662# functions and procedures are registered.663#664w1file = open(wrapper_name+'W.c','w')665w2file = open('wrapper_' + wrapper_name+'.c','w')666#667# Start writing information to the main wrapper code.668#669#---------------------------------------------------------------------670#671# Write out the include files needed.672#673#---------------------------------------------------------------------674w1file.write('#include <stdio.h>\n')675w1file.write('#include "wrapper.h"\n\n')676#---------------------------------------------------------------------677#678# Write out prototype for Fortran routine.679#680#681# extern void NGCALLF(xxx,XXX)(double *, int*, etc *);682#683#---------------------------------------------------------------------684w1file.write("extern void NGCALLF("+ lower(fortran_name) + "," +685 upper(fortran_name) + ")(")686for i in range(len(farg_types)):687 if i == 0:688 w1file.write(ctypes[farg_types[i]] + " *")689 else:690 w1file.write(", " + ctypes[farg_types[i]] + " *")691w1file.write(");\n\n")692#---------------------------------------------------------------------693#694# Write out first line of NCL wrapper routine.695#696# NhlErrorTypes wrf_rh(void) {697#698#---------------------------------------------------------------------699w1file.write("NhlErrorTypes " + ncl_nameW + "( void )\n{\n")700#---------------------------------------------------------------------701#702# Write out the declarations for the input argument variables.703#704#---------------------------------------------------------------------705w1file.write("""706/*707 * Input variables708 */709""")710#---------------------------------------------------------------------711#712# First write code to declare variable itself along with its type.713#714# Variables that are "void" will be converted to double715# precision, so they will have a "tmp_xxx" variable716# associated with them.717#718#---------------------------------------------------------------------719for i in range(len(args)):720 w1file.write("/*\n")721 w1file.write(" * Argument # " + str(i) + "\n")722 w1file.write(" */\n")723 w1file.write(" " + args[i].ctype + " *" + args[i].name + ";\n")724 if args[i].ntype == "numeric":725 w1file.write(" double *" + args[i].tmp_name + " = NULL;\n")726#---------------------------------------------------------------------727#728# Write out dimension information.729#730# int ndims_x, dsizes_x[...];731#732#---------------------------------------------------------------------733 if args[i].ndims == 0:734 w1file.write(" int " + args[i].ndims_name + ";\n")735 w1file.write(" ng_size_t " + args[i].dsizes_name + \736 "[NCL_MAX_DIMENSIONS];\n")737 else:738#739# We only need to include the dimension sizes if one of the sizes740# is unknown (represented by being set to '0').741#742 if 0 in args[i].dsizes:743 w1file.write(" ng_size_t " + args[i].dsizes_name + "[" + str(args[i].ndims) + "];\n")744#---------------------------------------------------------------------745#746# Include missing value variables for each variable that can contain747# missing values. In addition, if the variable is numeric, be sure748# to create variables to hold the double and single versions of749# the missing value.750#751# int has_missing_x;752# NclScalar missing_x, missing_dbl_x, missing_flt_x;753#754#---------------------------------------------------------------------755 if args[i].has_missing:756 w1file.write(" int " + args[i].has_msg_name + ";\n")757 if args[i].ntype == "numeric":758 w1file.write(" NclScalar " + args[i].msg_name + ", " + \759 args[i].msg_fname + ", " + args[i].msg_dname + ";\n")760 else:761 w1file.write(" NclScalar " + args[i].msg_name + ";\n")762#---------------------------------------------------------------------763#764# Include a type variable for each variable that is numeric.765#766# NclBasicDataTypes type_x;767#768#---------------------------------------------------------------------769 if args[i].ntype == "numeric":770 w1file.write(" NclBasicDataTypes " + args[i].type_name + ";\n\n")771if isfunc:772#---------------------------------------------------------------------773#774# Write out declarations for return variable information. Include a775# temporary variable if the output is to be numeric.776#777#---------------------------------------------------------------------778 w1file.write("/*\n")779 w1file.write(" * Return variable\n")780 w1file.write(" */\n")781 w1file.write(" " + ret_arg.ctype + " *" + ret_arg.name + ";\n")782 if ret_arg.ntype == "numeric":783 w1file.write(" double *" + ret_arg.tmp_name + " = NULL;\n")784#---------------------------------------------------------------------785#786# Write out dimension information.787#788#---------------------------------------------------------------------789 w1file.write(" int " + ret_arg.ndims_name + ";\n")790 w1file.write(" ng_size_t " + ret_arg.dsizes_name + ";\n")791#---------------------------------------------------------------------792#793# Include missing value variables for each variable that can contain794# missing values. In addition, if the variable is numeric, be sure795# to create variables to hold the double and single versions of796# the missing value.797#798# int has_missing_x;799# NclScalar missing_x, missing_dbl_x, missing_flt_x;800#801#---------------------------------------------------------------------802 if ret_arg.has_missing:803 w1file.write(" int " + ret_arg.has_msg_name + ";\n")804 if ret_arg.ntype == "numeric":805 w1file.write(" NclScalar " + ret_arg.msg_name + ", " + \806 ret_arg.msg_fname + ", " + ret_arg.msg_dname + ";\n")807 else:808 w1file.write(" NclScalar " + ret_arg.msg_name + ";\n")809#---------------------------------------------------------------------810#811# Include a type variable.812#813# NclBasicDataTypes type_ret_val;814#815#---------------------------------------------------------------------816 w1file.write(" NclBasicDataTypes " + ret_arg.type_name + ";\n\n")817#---------------------------------------------------------------------818#819# Write out code for other randome variables, like dimension sizes.820#821#---------------------------------------------------------------------822w1file.write("""823/*824 * Various825 */826""")827if global_dsizes_names != []:828 w1file.write(" int ")829#830# Write out the various dimension size variables we've been collecting831# into the global_dsizes_names array.832#833 for i in range(len(global_dsizes_names)):834 if i == (len(global_dsizes_names)-1):835 w1file.write(global_dsizes_names[i] + ";\n")836 else:837 w1file.write(global_dsizes_names[i] + ", ")838#---------------------------------------------------------------------839#840# For any variable that has leftmost dimensions, we need a corresponding841# "index_xxx" variable.842#843#---------------------------------------------------------------------844 w1file.write(" int ")845 for i in range(len(index_names)):846 if i == (len(index_names)-1):847 w1file.write(index_names[i] + ";\n")848 else:849 w1file.write(index_names[i] + ", ")850#851# Write out the various work arrays and extra arguments we have to852# pass into Fortran array.853#854if various_var_names != []:855 for i in range(len(various_var_names)):856 w1file.write(" " + ctypes[various_var_types[i]] + " " + \857 various_var_names[i] + ";\n")858if work_array_names != []:859 for i in range(len(work_array_names)):860 w1file.write(" " + ctypes[work_array_types[i]] + " " + \861 work_array_names[i] + ";\n")862#863# Write out integer variables that will hold the size of each work864# array. This will be the same name as the work array, with an "l"865# in front of it.866#867 w1file.write(" int ")868 for i in range(len(work_array_names)):869 if i == (len(work_array_names)-1):870 w1file.write("l" + work_array_names[i] + ";\n")871 else:872 w1file.write("l" + work_array_names[i] + ", ")873#---------------------------------------------------------------------874#875# If any input variable has leftmost dimensions, include that variable876# here.877#878#---------------------------------------------------------------------879if have_leftmost:880 if isfunc:881 w1file.write(" int i, ndims_leftmost, size_leftmost, size_output, ret;\n")882 else:883 w1file.write(" int i, ndims_leftmost, size_leftmost;\n")884else:885 if isfunc: 886 w1file.write(" int size_output;\n")887 888#---------------------------------------------------------------------889#890# Write the NclGetArg code for retrieving each argument from the891# NCL function call.892#893#---------------------------------------------------------------------894w1file.write("""895/*896 * Retrieve parameters.897 *898 * Note any of the pointer parameters can be set to NULL, which899 * implies you don't care about its value.900 */901""")902#903# Loop across input arguments and generate code that will904# retrieve them from the NCL script.905#906for i in range(len(args)):907 w1file.write("/*\n")908 w1file.write(" * Get argument # " + str(i) + "\n")909 w1file.write(" */\n")910 w1file.write(" " + args[i].name + " = (" + args[i].ctype + \911 "*)NclGetArgValue(\n")912 w1file.write(" " + str(i) + ",\n")913 w1file.write(" " + str(len(args)) + ",\n")914 if args[i].ndims == 0:915 w1file.write(" &" + args[i].ndims_name + ",\n")916 else:917 w1file.write(" NULL,\n")918 if (args[i].ndims == 0) or (0 in args[i].dsizes):919 w1file.write(" " + args[i].dsizes_name + ",\n")920 else:921 w1file.write(" NULL,\n")922#923# These are for the missing values.924#925 if args[i].has_missing:926 w1file.write(" &" + args[i].msg_name + ",\n")927 w1file.write(" &" + args[i].has_msg_name + ",\n")928 else:929 w1file.write(" NULL,\n")930 w1file.write(" NULL,\n")931 if args[i].ntype == "numeric":932 w1file.write(" &" + args[i].type_name + ",\n")933 else:934 w1file.write(" NULL,\n")935 w1file.write(" DONT_CARE);\n")936#---------------------------------------------------------------------937#938# Write out code for doing some minimal error checking on input939# variable sizes. We only need to check variable sizes that are 940# not hard-wired to a specific size (like "2 x 3 x 4" versus 941# "nx x ny x nz").942#943#944# Also, if a variable is to contain leftmost dimensions, then we need945# to make sure that it meets the bare minimum requirements for number946# of rightmost dimensions.947#948#---------------------------------------------------------------------949 if args[i].min_ndims > 0:950 w1file.write("""951/*952 * Check dimension sizes.953 */954""")955 w1file.write(" if(" + args[i].ndims_name + " < " + \956 str(args[i].min_ndims) + ") {\n")957 if (args[i].min_ndims == 1):958 w1file.write(fatal_str + 'The ' + args[i].name + \959 ' array must have at least one dimension");\n')960 else:961 w1file.write(fatal_str + 'The ' + args[i].name + \962 ' array must have at least ' + str(args[i].min_ndims) + \963 ' dimensions");\n')964 w1file.write(return_fatal_str)965 w1file.write(' }\n')966#967# Code for coercing missing values to float and/or double.968#969 if args[i].has_missing and args[i].ntype == "numeric":970 w1file.write("""971/*972 * Coerce missing value to double if necessary.973 */974""")975 w1file.write(" coerce_missing(" + args[i].type_name + "," + \976 args[i].has_msg_name + ",&" + args[i].msg_name + \977 ",\n &" + args[i].msg_dname + ",&" + \978 args[i].msg_fname + ");\n\n")979 if not args[i].is_scalar:980 dstr = ""981 for j in range(len(args[i].dsizes_names)):982#983# If we're not dealing with a scalar, then write the code that 984# assigns the size of the rightmost dimensions, and then creates985# a variable that will contain the size of all the rightmost dimensions.986#987# For example, if the rightmost dimensions are nx, ny, and988# nz, then the code will be "nxnynz = nx * ny * nz". 989#990 if not args[i].dsizes_names[j] in global_dsizes_names_accum:991 if args[i].ndims > 0:992 if args[i].dsizes[j] == 0:993 w1file.write(' ' + args[i].dsizes_names[j] + ' = ' + \994 args[i].dsizes_name + '[' + str(j) + '];\n')995 else:996 w1file.write(' ' + args[i].dsizes_names[j] + ' = ' + \997 str(args[i].dsizes[j]) + ';\n')998 else:999 w1file.write(' ' + args[i].dsizes_names[j] + ' = ' + \1000 args[i].dsizes_name + '[' + args[i].ndims_name + '-' + 1001 str(int(args[i].min_ndims-j)) + '];\n')1002 global_dsizes_names_accum.append(args[i].dsizes_names[j])1003 else:1004 if args[i].ndims > 0 and args[i].dsizes[j] == 0:1005 w1file.write(' if(' + args[i].dsizes_name + '[' + str(j) + \1006 '] != ' + args[i].dsizes_names[j] + ') {\n')1007 w1file.write(fatal_str + 'The #' + str(j) + \1008 ' dimension of ' + args[i].name + \1009 ' must be length ' + args[i].dsizes_names[j] + \1010 '");\n')1011 elif args[i].ndims == 0:1012 w1file.write(' if(' + args[i].dsizes_name + '[' + 1013 args[i].ndims_name + '-' + str(args[i].min_ndims-j) + \1014 '] != ' + args[i].dsizes_names[j] + ') {\n')1015 w1file.write(fatal_str + \1016 'The ndims-' + str(int(args[i].min_ndims-j)) + \1017 ' dimension of ' + args[i].name + \1018 ' must be of length ' + args[i].dsizes_names[j] + \1019 '");\n')1020 w1file.write(return_fatal_str)1021 w1file.write(' }\n')1022 if args[i].min_ndims > 1 or args[i].ndims > 1:1023 if j == 0:1024 dstr = " " + args[i].dsizes_names_str + " = " + \1025 args[i].dsizes_names[0]1026 else:1027 dstr = dstr + " * " + args[i].dsizes_names[j]1028 if dstr != "":1029 w1file.write(dstr + ";\n\n")1030#---------------------------------------------------------------------1031#1032# Write out code to calculate size of leftmost dimensions, if any.1033#1034#---------------------------------------------------------------------1035if have_leftmost:1036 first = True1037 name_str = ""1038 w1file.write("""1039/*1040 * Calculate size of leftmost dimensions.1041 */1042""")1043 w1file.write(" size_leftmost = 1;\n")1044 for i in range(len(args)):1045 if args[i].min_ndims > 0:1046 if first:1047 w1file.write(" ndims_leftmost = " + args[i].ndims_name + "-" + 1048 str(args[i].min_ndims) + ";\n");1049 w1file.write(" for(i = 0; i < ndims_leftmost; i++) {\n")1050 first_arg_name = args[i].name # Keep track of this argument1051 prev_arg_name = first_arg_name1052 first = False1053 second = True1054 else:1055 if second:1056 w1file.write(" if(" + args[i].dsizes_name + "[i] != dsizes_" + \1057 first_arg_name + "[i]")1058 name_str = prev_arg_name1059 prev_arg_name = args[i].name1060 second = False1061 else:1062 name_str = name_str + ", " + prev_arg_name1063 w1file.write(" ||\n " + args[i].dsizes_name + \1064 "[i] != dsizes_" + first_arg_name + "[i]")1065 prev_arg_name = args[i].name1066#---------------------------------------------------------------------1067#1068# Write code to close leftmost dimensions loop.1069#1070#---------------------------------------------------------------------1071 if name_str != "":1072 w1file.write(") {\n")1073 w1file.write(' ' + fatal_str + 'The leftmost dimensions of ' + \1074 name_str + ' and ' + prev_arg_name + \1075 ' must be the same");\n')1076 w1file.write(' ' + return_fatal_str)1077 w1file.write(' }\n')1078 if not first:1079 w1file.write(" size_leftmost *= dsizes_" + first_arg_name + "[i];\n")1080 w1file.write(" }\n\n")1081#---------------------------------------------------------------------1082#1083# Write out code to allocate space for coercing input arrays, if any of1084# them are numeric. In addition, if the number of dimensions is unknown,1085# then we need to allocate space for the temporary array, and later1086# it will be coerced.1087#1088#---------------------------------------------------------------------1089first = True1090for i in range(len(args)):1091 name = args[i].name1092 if args[i].ntype == "numeric":1093 if first:1094 first = False1095 if isfunc and ret_arg.ntype == "numeric":1096#---------------------------------------------------------------------1097# While we're here, we can also set the output array type, based1098# on whether any of the input is double or not.1099#---------------------------------------------------------------------1100 w1file.write("""1101/*1102 * The output type defaults to float, unless this input array is double.1103 */1104""")1105 w1file.write(" " + ret_arg.type_name + " = NCL_float;\n")1106 w1file.write("""1107/* 1108 * Allocate space for coercing input arrays. If any of the input1109 * is already double, then we don't need to allocate space for1110 * temporary arrays, because we'll just change the pointer into1111 * the void array appropriately.1112 */1113""")1114#---------------------------------------------------------------------1115# If input is not already double, then we'll need to allocate a1116# temporary array to coerce it to double.1117#---------------------------------------------------------------------1118 w1file.write("/*\n")1119 w1file.write(" * Allocate space for " + args[i].tmp_name + ".\n")1120 w1file.write(" */\n")1121 if args[i].min_ndims > 0:1122#1123# We are dealing with an array that has possible leftmost dimensions.1124#1125 w1file.write(" if(" + args[i].type_name + " != NCL_double) {\n")1126 w1file.write(" " + args[i].tmp_name + " = (double *)calloc(" + \1127 args[i].dsizes_names_str + ",sizeof(double));\n")1128 w1file.write(" if(" + args[i].tmp_name + " == NULL) {\n")1129 w1file.write(' ' + fatal_str + \1130 'Unable to allocate memory for coercing input array to double");\n')1131 w1file.write(" " + return_fatal_str)1132 w1file.write(" }\n")1133 w1file.write(" }\n")1134 else:1135#1136# This array has no leftmost dimensions, so go ahead and coerce it1137# to double here. We have two separate cases, depending on whether1138# the input can contain a missing value.1139#1140 if args[i].is_scalar:1141 size = "1"1142 else:1143 size = args[i].dsizes_names_str1144 if args[i].has_missing:1145 w1file.write(" " + args[i].tmp_name + " = coerce_input_double(" + \1146 name + "," + args[i].type_name + "," + size + "," + \1147 args[i].has_msg_name + ",&" + args[i].msg_name + ",&" + \1148 args[i].msg_dname + ");\n")1149 else:1150 w1file.write(" " + args[i].tmp_name + " = coerce_input_double(" + \1151 name + "," + args[i].type_name + "," + size + "," + \1152 "0,NULL,NULL);\n")1153 w1file.write(" if(" + args[i].tmp_name + " == NULL) {\n")1154 w1file.write(fatal_str + \1155 'Unable to allocate memory for coercing input array to double");\n')1156 w1file.write(return_fatal_str)1157 w1file.write(" }\n")1158 if isfunc and ret_arg.ntype == "numeric" and args[i].sets_otype:1159#---------------------------------------------------------------------1160# If this input argument is numeric, and its one whose type determines1161# the output for the output, then include the code for that here.1162#---------------------------------------------------------------------1163 w1file.write(" else {\n")1164 w1file.write(" " + ret_arg.type_name + " = NCL_double;\n")1165 w1file.write(" }\n")1166#---------------------------------------------------------------------1167# Code to handle allocating space for output array and its dimension1168# sizes. Also, we may have to allocate a temporary array to hold space1169# for a double array, if the return value is not double.1170#---------------------------------------------------------------------1171if isfunc:1172#----------------------------------------------------------------------1173# Code to calculate size of output array.1174#----------------------------------------------------------------------1175 w1file.write("""1176/*1177 * Calculate size of output array.1178 */1179""")1180#1181# Create string that will hold total dimension sizes of rightmost1182# dimensions of return variable.1183#1184 if not ret_arg.is_scalar:1185 if (ret_arg.min_ndims > 0) or (0 in ret_arg.dsizes):1186 if ret_arg.min_ndims > 1 or ret_arg.ndims > 1:1187 for j in range(len(ret_arg.dsizes_names)):1188 if j == 0:1189 ret_dstr = " " + ret_arg.dsizes_names_str + " = " + \1190 ret_arg.dsizes_names[0]1191 else:1192 ret_dstr = ret_dstr + " * " + ret_arg.dsizes_names[j]1193 w1file.write(ret_dstr + ";\n")1194 w1file.write(" size_output = size_leftmost * " + \1195 ret_arg.dsizes_names_str + ";\n")1196 else:1197 w1file.write(" size_output = ...need input here...;\n")1198 w1file.write("""1199/* 1200 * Allocate space for output array.1201 */1202""")1203 if ret_arg.ntype == "numeric":1204 w1file.write(" if(" + ret_arg.type_name + " != NCL_double) {\n")1205 w1file.write(" " + ret_arg.name + " = (void *)calloc(size_output, " + \1206 "sizeof(float));\n")1207 if ret_arg.min_ndims > 0:1208 w1file.write(" " + ret_arg.tmp_name + " = (double *)calloc(" + \1209 ret_arg.dsizes_names_str + ",sizeof(double));\n")1210 else:1211 w1file.write(" " + ret_arg.tmp_name + \1212 " = (double *)calloc(...need input here...,sizeof(double));\n")1213 w1file.write(" if(" + ret_arg.tmp_name + " == NULL) {\n")1214 w1file.write(' ' + fatal_str + \1215 'Unable to allocate memory for temporary output array");\n')1216 w1file.write(" " + return_fatal_str)1217 w1file.write(" }\n")1218 w1file.write(" }\n")1219 w1file.write(" else {\n")1220 w1file.write(" " + ret_arg.name + " = (void *)calloc(size_output, " + \1221 "sizeof(double));\n")1222 w1file.write(" }\n")1223 else :1224 w1file.write(" " + ret_arg.name + " = (" + ret_arg.ctype + \1225 "*)calloc(size_output, sizeof(" + ret_arg.ctype + "));\n")1226 w1file.write(" if(" + ret_arg.name + " == NULL) {\n")1227 w1file.write(fatal_str + 'Unable to allocate memory for output array");\n')1228 w1file.write(return_fatal_str)1229 w1file.write(" }\n")1230#1231# Set the missing value for the output, if any.1232#1233 if ret_has_missing and (num_input_has_missing > 0) and ret_msg_depend_input:1234 w1file.write(" if(" + args[ret_msg_depend_index].has_msg_name + ") {\n")1235 w1file.write(" if(" + ret_arg.type_name + " == NCL_double) " + \1236 ret_arg.msg_name + " = " + \1237 args[ret_msg_depend_index].msg_dname + ";\n")1238 w1file.write(" else " + ret_arg.msg_name + " = " + \1239 args[ret_msg_depend_index].msg_fname + ";\n")1240 w1file.write(" " + ret_arg.msg_dname + " = " + \1241 args[ret_msg_depend_index].msg_dname + ";\n")1242 w1file.write(" }\n")1243 w1file.write("""1244/* 1245 * Allocate space for output dimension sizes and set them.1246 */1247""")1248 if ret_arg.ndims > 0:1249 w1file.write(" " + ret_arg.ndims_name + " = " + str(ret_arg.ndims) + ";\n")1250 else:1251 w1file.write(" " + ret_arg.ndims_name + " = ndims_leftmost + " + \1252 str(ret_arg.min_ndims) + ";\n")1253 w1file.write(" " + ret_arg.dsizes_name + " = (ng_size_t*)calloc(" + \1254 ret_arg.ndims_name + ",sizeof(ng_size_t)); \n")1255 w1file.write(" if( " + ret_arg.dsizes_name + " == NULL ) {\n")1256 w1file.write(fatal_str + \1257 'Unable to allocate memory for holding dimension sizes");\n')1258 w1file.write(return_fatal_str)1259 w1file.write(" }\n")1260 if ret_arg.min_ndims > 0:1261#1262# Loop through input arguments until we find one that has leftmost1263# dimensions, and then use its leftmost dimensions to assign 1264# dimensions to the output array's dimension sizes array.1265#1266 for i in range(len(args)):1267 if args[i].min_ndims > 0:1268 w1file.write(" for(i = 0; i < " + ret_arg.ndims_name + "-" + \1269 str(ret_arg.min_ndims) + "; i++) " + \1270 ret_arg.dsizes_name + "[i] = " + args[i].dsizes_name + "[i];\n")1271 break1272 else:1273 w1file.write(" for(i = 0; i < " + ret_arg.ndims_name + \1274 "; i++)" + ret_arg.dsizes_name + \1275 "[i] = ...need input here;\n")1276 for i in range(ret_arg.min_ndims):1277 w1file.write(" " + ret_arg.dsizes_name + "[" + ret_arg.ndims_name + 1278 "-" + str(ret_min_ndims-i) + "] = " + \1279 ret_dsizes_names[i] + ";\n")1280 else:1281 w1file.write(" for(i = 0; i < " + ret_arg.ndims_name + "; i++)" + \1282 ret_arg.dsizes_name + "[i] = ...need input here;\n")1283#1284# Write out code for the loop across leftmost dimensions (if any).1285#1286if have_leftmost:1287 w1file.write("""1288/*1289 * Loop across leftmost dimensions and call the Fortran routine for each1290 * subsection of the input arrays.1291 */1292""")1293 index_str = " "1294 for i in range(len(index_names)):1295 if i < (len(index_names)-1):1296 index_str = index_str + index_names[i] + " = "1297 else:1298 index_str = index_str + index_names[i] + " = 0;\n"1299 w1file.write(index_str)1300 w1file.write("\n for(i = 0; i < size_leftmost; i++) {\n")1301 for i in range(len(args)):1302 name = args[i].name1303 if args[i].ntype == "numeric" and args[i].ndims == 0:1304 w1file.write("/*\n")1305 w1file.write(" * Coerce subsection of " + name + " (" + \1306 args[i].tmp_name + ") to double if necessary.\n")1307 w1file.write(" */\n")1308 w1file.write(" if(" + args[i].type_name + " != NCL_double) {\n")1309 w1file.write(" coerce_subset_input_double(" + name + "," + \1310 args[i].tmp_name + "," + args[i].index_name + "," + \1311 args[i].type_name + "," + args[i].dsizes_names_str + \1312 ",0,NULL,NULL);\n")1313 w1file.write(" }\n")1314 w1file.write(" else {\n")1315 w1file.write(" " + args[i].tmp_name + " = &((double*)" + name + \1316 ")[" + args[i].index_name + "];\n")1317 w1file.write(" }\n\n")1318#1319# Write out code for pointing temporary output array to appropriate1320# location in output array, if necessary.1321#1322 if isfunc and ret_arg.ntype == "numeric" and ret_arg.ndims == 0:1323 w1file.write("""1324/*1325 * Point temporary output array to void output array if appropriate.1326 */1327""")1328 w1file.write(" if(" + ret_arg.type_name + " == NCL_double) " + \1329 ret_arg.tmp_name + " = &((double*)" + ret_arg.name + \1330 ")[" + ret_arg.index_name + "];\n\n")1331#1332# Write code for calling Fortran routine inside loop.1333#1334 w1file.write("""1335/*1336 * Call the Fortran routine.1337 */1338""")1339 w1file.write(" NGCALLF("+ lower(fortran_name) + "," + \1340 upper(fortran_name) + ")(")1341 for i in range(len(farg_names)):1342 if i == 0:1343 w1file.write(farg_cchar[i] + farg_names[i])1344 else:1345 w1file.write(", " + farg_cchar[i] + farg_names[i])1346 w1file.write(");\n")1347#1348# Code for copying values back to void array, if the output is1349# supposed to be float.1350#1351 if isfunc and ret_arg.ntype == "numeric":1352 w1file.write("""1353/*1354 * Coerce output back to float if necessary.1355 */1356""")1357 w1file.write(" if(" + ret_arg.type_name + " == NCL_float) {\n")1358 w1file.write(" coerce_output_float_only(" + ret_arg.name + \1359 "," + ret_arg.tmp_name + "," + ret_arg.dsizes_names_str + \1360 "," + ret_arg.index_name + ");\n")1361 w1file.write(" }\n")1362#1363# Write out code for incrementing index variables, if any.1364#1365 for i in range(len(args)):1366 if args[i].ntype == "numeric" and args[i].ndims == 0:1367 w1file.write(" " + args[i].index_name + " += " + \1368 args[i].dsizes_names_str + ";\n")1369 if isfunc and ret_arg.ntype == "numeric" and ret_arg.ndims == 0:1370 w1file.write(" " + ret_arg.index_name + " += " + \1371 ret_arg.dsizes_names_str + ";\n")1372 w1file.write(" }\n") # End "for" loop1373else:1374#1375# We are dealing with a function that doesn't have any arguments1376# with leftmost dimensions. This is unusual, but possible.1377#1378# Write code for calling Fortran routine not in a loop.1379#1380 w1file.write("""1381/*1382 * Call the Fortran routine.1383 */1384""")1385 w1file.write(" NGCALLF("+ lower(fortran_name) + "," + \1386 upper(fortran_name) + ")(")1387 for i in range(len(farg_names)):1388 if i == 0:1389 w1file.write(farg_names[i])1390 else:1391 w1file.write(", " + farg_names[i])1392 w1file.write(");\n")1393#1394# Set up code for freeing unneeded memory. Only those input variables1395# that had to be coerced to double precision need to be freed.1396#1397first = True1398for i in range(len(args)):1399 if args[i].ntype == "numeric":1400#1401# Write code for calling Fortran routine not in a loop.1402#1403 if first:1404 w1file.write("""1405/*1406 * Free unneeded memory.1407 */1408""")1409 first = False1410 w1file.write(" if(" + args[i].type_name + \1411 " != NCL_double) NclFree(" + args[i].tmp_name + ");\n")1412if isfunc and ret_arg.ntype == "numeric":1413 w1file.write(" if(" + ret_arg.type_name + \1414 " != NCL_double) NclFree(" + ret_arg.tmp_name + ");\n")1415#1416# Set up code for returning information back to NCL script.1417#1418if isfunc:1419 w1file.write("""1420/*1421 * Return value back to NCL script.1422 */1423""")1424#1425# If the return can have a missing value, account for it here. Also,1426# if the return can be float or double, then we have to return1427# the correct missing value.1428#1429 if ret_has_missing:1430 if ret_arg.ntype == "numeric":1431 w1file.write(" if(" + ret_arg.type_name + " != NCL_double) {\n")1432 w1file.write(" ret = NclReturnValue(" + ret_arg.name + "," + \1433 ret_arg.ndims_name + "," + ret_arg.dsizes_name + \1434 ",&" + ret_arg.msg_fname + "," + \1435 ret_arg.type_name + ",0);\n")1436 w1file.write(" }\n")1437 w1file.write(" else {\n")1438 w1file.write(" ret = NclReturnValue(" + ret_arg.name + "," + \1439 ret_arg.ndims_name + "," + ret_arg.dsizes_name + \1440 ",&" + ret_arg.msg_dname + "," + \1441 ret_arg.type_name + ",0);\n")1442 w1file.write(" }\n")1443 else:1444 w1file.write(" else {\n")1445 w1file.write(" ret = NclReturnValue(" + ret_arg.name + "," + \1446 ret_arg.ndims_name + "," + ret_arg.dsizes_name + "," + \1447 ret_arg.msg_name + "," + ret_arg.type_name + ",0);\n")1448 w1file.write(" }\n")1449 else:1450 w1file.write(" ret = NclReturnValue(" + ret_arg.name + "," + \1451 ret_arg.ndims_name + "," + ret_arg.dsizes_name + ",NULL," + \1452 ret_arg.type_name + ",0);\n")1453 w1file.write(" NclFree(" + ret_arg.dsizes_name + ");\n")1454 w1file.write(" return(ret);\n")1455else:1456 w1file.write("""1457/*1458 * This is a procedure, so no values are returned.1459 */1460""")1461 w1file.write(" return(NhlNOERROR);\n")1462#---------------------------------------------------------------------1463#1464# Write out last line of NCL wrapper routine.1465#1466# }1467#1468#---------------------------------------------------------------------1469w1file.write("}\n")1470#1471# Write the code for registering this function or procedure with NCL.1472# This will be written to a different file, and needs to be copied1473# to "wrapper.c".1474#1475w2file.write('extern NhlErrorTypes ' + ncl_nameW + '(void);\n')1476w2file.write('/*\n * Register "' + ncl_name + '".\n *\n')1477w2file.write(' * Create private argument array\n */\n')1478w2file.write(' nargs = 0;\n')1479w2file.write(' args = NewArgs(' + str(num_args) + ');\n\n')1480for i in range(num_args):1481 if args[i].ndims == 0:1482 w2file.write(' SetArgTemplate(args,nargs,"' + args[i].ntype + \1483 '",0,NclANY);nargs++;\n')1484 else:1485 for j in range(args[i].ndims):1486 w2file.write(' dimsizes[' + str(j) + '] = ' + \1487 str(args[i].dsizes[j]) + ';\n')1488 w2file.write(' SetArgTemplate(args,nargs,"' + args[i].ntype + \1489 '",' + str(args[i].ndims) + ',dimsizes);nargs++;\n')1490if isfunc:1491 w2file.write('\n NclRegisterFunc(' + ncl_nameW + ',args,"' + \1492 ncl_name + '",nargs);\n')1493else:1494 w2file.write('\n NclRegisterProc(' + ncl_nameW + ',args,"' + \1495 ncl_name + '",nargs);\n')1496#1497# Close files.1498#1499w1file.close()...

Full Screen

Full Screen

rui.py

Source:rui.py Github

copy

Full Screen

1#this file is the rui script of 5010, inludes bg96 and other sensors.2#use ampy --port /dev/ttyACM0 put rui.py to your board34import time5import math6from machine import Pin7from machine import UART8from machine import I2C910i2c=I2C(1, 13, 14)11uart=UART(0, 115200)1213def get_acceleration(echo=False, ret=True):14 x_l=i2c.readfrom_mem(0x19, 0x28, 1)15 x_h=i2c.readfrom_mem(0x19, 0x29, 1)16 y_l=i2c.readfrom_mem(0x19, 0x2a, 1)17 y_h=i2c.readfrom_mem(0x19, 0x2b, 1)18 z_l=i2c.readfrom_mem(0x19, 0x2c, 1)19 z_h=i2c.readfrom_mem(0x19, 0x2d, 1)20 x= (x_h[0]<<8) | x_l[0]21 y= (y_h[0]<<8) | y_l[0]22 z= (z_h[0]<<8) | z_l[0]23 if x < 0x8000:24 x=x25 else:26 x=x-0x1000027 if y < 0x8000:28 y=y29 else:30 y=y-0x1000031 if z < 0x8000:32 z=z33 else:34 z=z-0x1000035 acc_x=(x*4000)/65536.036 acc_y=(y*4000)/65536.037 acc_z=(z*4000)/65536.038 echo_Arg='lis3dh: acc_x='+str(acc_x)+', acc_y='+str(acc_y)+', acc_z='+str(acc_z)39 ret_Arg={}40 ret_Arg['x']=acc_x41 ret_Arg['y']=acc_y42 ret_Arg['z']=acc_z43 return _answer(echo, ret, echo_Arg, ret_Arg)4445def get_light_strength(echo=False, ret=True):46 buf=i2c.readfrom_mem(0x44, 0x00, 2)47 light=int.from_bytes(buf, 'big')48 m=light & 0x0FFF49 e=(light & 0xF000) >> 1250 h= math.pow(2, e)51 light = m*(0.01 * h)52 echo_Arg='opt3001: Light strength = '+str(light)53 ret_Arg=light54 return _answer(echo, ret, echo_Arg, ret_Arg)5556def get_temperature_humidity(echo=False, ret=True):57 buf=bytearray([0x7C, 0xA2])58 i2c.writeto(0x70, buf)59 buf2=bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00])60 i2c.readfrom_into(0x70, buf2)61 temp = (buf2[1] | (buf2[0] << 8)) * 175 / 65536.0 - 45.062 humi = (buf2[4] | (buf2[3] << 8)) * 100 / 65536.063 echo_Arg='shtc3: Temperature='+str(temp)+', Humidity='+str(humi)64 ret_Arg={}65 ret_Arg['temp']=temp66 ret_Arg['humi']=humi67 return _answer(echo, ret, echo_Arg, ret_Arg)6869def get_pressure(echo=False, ret=True):70 pre_xl=i2c.readfrom_mem(0x5c, 0x28, 1)71 pre_xl=int.from_bytes(pre_xl, 'big')72 pre_l=i2c.readfrom_mem(0x5c, 0x29, 1)73 pre_l=int.from_bytes(pre_l, 'big')74 pre_h=i2c.readfrom_mem(0x5c, 0x2a, 1)75 pre_h=int.from_bytes(pre_h, 'big')76 pre = (pre_h<<16)|(pre_l<<8)|pre_xl77 if pre & 0x00800000:78 pre |= 0xFF00000079 pre = pre/4096.080 echo_Arg='lps22hb: Pressure='+str(pre)+' HPa'81 ret_Arg=pre82 return _answer(echo, ret, echo_Arg, ret_Arg)8384def get_gps(echo=False, ret=True):85 buf=bytearray()86 uart.write('AT+QGPSCFG=\"gpsnmeatype\", 1')87 time.sleep_ms(10)88 bchar=uart.readchar()89 while bchar != -1:90 buf.append(bchar)91 bchar=uart.readchar()92 time.sleep_ms(1)93 buf2=bytearray()94 uart.write('AT+QGPS=1, 1, 1, 1, 1')95 time.sleep_ms(10)96 bchar=uart.readchar()97 while bchar != -1:98 buf2.append(bchar)99 bchar=uart.readchar()100 time.sleep_ms(1)101 buf3=bytearray()102 uart.write('AT+QGPSGNMEA=\"GGA\"')103 time.sleep_ms(10)104 bchar=uart.readchar()105 while bchar != -1:106 buf3.append(bchar)107 bchar=uart.readchar()108 time.sleep_ms(1)109 string = str(buf3, 'utf-8')110 return _answer(echo, ret, string, string)111112#this function is suitable for most AT commands of bg96. Timeout(ms) is what bg96 needs depending on the AT. e.g. rui.cellular_tx('ATI', 500)113def cellular_tx(at, timeout=500, echo=True, ret=False):114 """Improved command. Added two variables:115 . echo: should we print the result?116 . ret: should we return the result as a string?117 This later feature is used by some functions below to display info in a better format."""118 buf3=bytearray()119 uart.write(at)120 time.sleep_ms(10)121 bchar=uart.readchar()122 while (bchar != -1) or (timeout > 0):123 if bchar != -1:124 buf3.append(bchar)125 bchar=uart.readchar()126 timeout=timeout-1127 time.sleep_ms(1)128 string = str(buf3, 'utf-8')129 return _answer(echo, ret, string, string)130 ## Using this string in gnss_get_nmea() for instance, to extract data.131132### Contribution by Kongduino133134_bg96_errors={}135_bg96_errors[0]="Phone failure"136_bg96_errors[1]="No connection to phone"137_bg96_errors[2]="Phone-adaptor link reserved"138_bg96_errors[3]="Operation not allowed"139_bg96_errors[4]="Operation not supported"140_bg96_errors[5]="PH-SIM PIN required"141_bg96_errors[6]="PH-FSIM PIN required"142_bg96_errors[7]="PH-FSIM PUK required"143_bg96_errors[10]="(U)SIM not inserted"144_bg96_errors[11]="(U)SIM PIN required"145_bg96_errors[12]="(U)SIM PUK required"146_bg96_errors[13]="(U)SIM failure"147_bg96_errors[14]="(U)SIM busy"148_bg96_errors[15]="(U)SIM wrong"149_bg96_errors[16]="Incorrect password"150_bg96_errors[17]="(U)SIM PIN2 required"151_bg96_errors[18]="(U)SIM PUK2 required"152_bg96_errors[20]="Memory full"153_bg96_errors[21]="Invalid index"154_bg96_errors[22]="Not found"155_bg96_errors[23]="Memory failure"156_bg96_errors[24]="Text string too long"157_bg96_errors[25]="Invalid characters in text string"158_bg96_errors[26]="Dial string too long"159_bg96_errors[27]="Invalid characters in dial string"160_bg96_errors[30]="No network service"161_bg96_errors[31]="Network timeout"162_bg96_errors[32]="Network not allowed - emergency calls only"163_bg96_errors[40]="Network personalization PIN required"164_bg96_errors[41]="Network personalization PUK required"165_bg96_errors[42]="Network subset personalization PIN required"166_bg96_errors[43]="Network subset personalization PUK required"167_bg96_errors[44]="Service provider personalization PIN required"168_bg96_errors[45]="Service provider personalization PUK required"169_bg96_errors[46]="Corporate personalization PIN required"170_bg96_errors[47]="Corporate personalization PUK required"171_bg96_errors[300]="ME failure"172_bg96_errors[301]="SMS ME reserved"173_bg96_errors[302]="Operation not allowed"174_bg96_errors[303]="Operation not supported"175_bg96_errors[304]="Invalid PDU mode"176_bg96_errors[305]="Invalid text mode"177_bg96_errors[310]="(U)SIM not inserted"178_bg96_errors[311]="(U)SIM pin necessary"179_bg96_errors[312]="PH (U)SIM pin necessary"180_bg96_errors[313]="(U)SIM failure"181_bg96_errors[314]="(U)SIM busy"182_bg96_errors[315]="(U)SIM wrong"183_bg96_errors[316]="(U)SIM PUK required"184_bg96_errors[317]="(U)SIM PIN2 required"185_bg96_errors[318]="(U)SIM PUK2 required"186_bg96_errors[320]="Memory failure"187_bg96_errors[321]="Invalid memory index"188_bg96_errors[322]="Memory full"189_bg96_errors[330]="SMSC address unknown"190_bg96_errors[331]="No network"191_bg96_errors[332]="Network timeout"192_bg96_errors[501]="Invalid parameter"193_bg96_errors[502]="Operation not supported"194_bg96_errors[503]="GNSS subsystem busy"195_bg96_errors[504]="Session is ongoing"196_bg96_errors[505]="Session not active"197_bg96_errors[506]="Operation timeout"198_bg96_errors[507]="Function not enabled"199_bg96_errors[508]="Time information error"200_bg96_errors[509]="XTRA not enabled"201_bg96_errors[512]="Validity time is out of range"202_bg96_errors[513]="Internal resource error"203_bg96_errors[514]="GNSS locked"204_bg96_errors[515]="End by E911"205_bg96_errors[516]="Not fixed now"206_bg96_errors[517]="Geo-fence ID does not exist"207_bg96_errors[549]="Unknown error"208209def _answer(echo, ret, echo_Arg, ret_Arg):210 if(echo):211 print(echo_Arg)212 if(ret):213 return ret_Arg214215def gnss_on(mode=1, fixmaxtime=30, fixmaxdist=50, fixcount=0, fixrate=1, echo=True, ret=False):216 """217 Turns on the GNSS function218 Default parameters219 Checks parameters before sending, or fails.220 """221 if(mode<1) or (mode>4):222 print("GNSS working mode range 1<>4!")223 print("Default is 1.")224 print(""" 1 Stand-alone225 2 MS-based226 3 MS-assisted227 4 Speed-optimal""")228 return229 if(fixmaxtime<1) or (fixmaxtime>255):230 print("Maximum positioning time range 1<>255!")231 print("Default is 30 seconds.")232 return233 if(fixmaxdist<1) or (fixmaxdist>1000):234 print("Accuracy threshold of positioning range 1<>1000!")235 print("Default is 50 meters.")236 return237 if(fixcount>1000):238 print("Number of attempts for positioning range 0<>1000!")239 print("Default is 0 (continuous).")240 return241 if(fixrate<1) or (fixrate>65535):242 print("Interval between first and second positioning range 1<>65535!")243 print("Default is 1 second.")244 return245 result=cellular_tx('AT+QGPS='+str(mode)+','+str(fixmaxtime)+','+str(fixmaxdist)+','+str(fixcount)+','+str(fixrate), 500, False, True).replace('\r', '').strip()246 return _answer(echo, ret, result, result)247248def gnss_off(echo=True, ret=False):249 """Turns off GNSS"""250 result=cellular_tx('AT+QGPSEND', 500, False, True).replace('\r', '').strip()251 return _answer(echo, ret, result, result)252253def gnss_status(echo=True, ret=False):254 """Enquires GNSS status"""255 result=cellular_tx('AT+QGPS?', 500, False, True).replace('\r', '').strip()256 if(result.startswith('AT+QGPS?\n+QGPS: ')):257 #Correct result258 a=result.split(': ')[1].split('\n')[0]259 if(a=='0'):260 echo_Arg="GNSS OFF"261 if(a=='1'):262 echo_Arg="GNSS ON"263 ret_Arg=echo_Arg264 else:265 echo_Arg="Unknown result response:\n "+result266 ret_Arg={}267 return _answer(echo, ret, echo_Arg, ret_Arg)268269def gpsloc(mode=0, echo=False, ret=True):270 """Acquire Positioning Information271 Modes:272 0: <latitude>,<longitude> format: ddmm.mmmm N/S,dddmm.mmmm E/W273 1: <latitude>,<longitude> format: ddmm.mmmmmm N/S,dddmm.mmmmmm E/W274 2: <latitude>,<longitude> format: (-)dd.ddddd,(-)ddd.ddddd275 Checks mode"""276 if(mode<0) or (mode>2):277 print("GPSLOC mode range 0<>2!")278 print("Default is 0.")279 print(""" Modes:280 0: <latitude>,<longitude> format: ddmm.mmmm N/S,dddmm.mmmm E/W281 1: <latitude>,<longitude> format: ddmm.mmmmmm N/S,dddmm.mmmmmm E/W282 2: <latitude>,<longitude> format: (-)dd.ddddd,(-)ddd.ddddd""")283 return284 result=cellular_tx('AT+QGPSLOC='+str(mode), 500, False, True).replace('\r', '').strip()285 if(result.find('\n+CME ERROR: ')>-1):286 #'AT+QGPSLOC=0\n+CME ERROR: 516'287 a=int(result.split(': ')[1].split('\n')[0].split(',')[0])288 ret_Arg={}289 ret_Arg['code']=a290 ret_Arg['text']=_bg96_errors[a]291 if(result.find('\n+QGPSLOC: ')>-1):292 #+QGPSLOC: <UTC>,<latitude>,<longitude>,<hdop>,<altit ude>,<fix>,<cog>,<spkm>,<spkn>,<date>,<nsat>293 #we have a match294 a=result.split(': ')[1].split('\n')[0].split(',')295 ret_Arg={}296 time=a[0].split('.')[0]297 ret_Arg['tof']=time[0:2]+':'+time[2:4]+':'+time[4:]+' UTC'298 NS="N"299 EW="E"300 if(mode==2):301 #long/lat format [-]dd.ddddd302 if(a[1][0:1]=='-'):303 NS="S"304 a[1]=a[1][1:]305 if(a[2][0:1]=='-'):306 EW="W"307 a[2]=a[2][1:]308 else:309 #long/lat format ddmm.mmmm[mm] N/S,dddmm.mmmm[mm] E/W310 NS=a[1][-1]311 a[1]=a[1][:-1]312 EW=a[2][-1]313 a[2]=a[2][:-1]314 long=float(a[1])315 x=int(long/100)316 y=((long/100)-x)*10/6317 long=x+y318 ret_Arg['long']=long319 ret_Arg['NS']=NS320 lat=float(a[2])321 x=int(lat/100)322 y=((lat/100)-x)*10/6323 lat=x+y324 ret_Arg['lat']=lat325 ret_Arg['EW']=EW326 ret_Arg['hdop']=float(a[3])327 ret_Arg['altitude']=float(a[4])328 ret_Arg['fix']=a[5]+"D positioning"329 ret_Arg['cog']=float(a[6])330 ret_Arg['spkm']=float(a[7])331 ret_Arg['spkn']=float(a[8])332 date=a[9]333 ret_Arg['date']="20"+date[4:][0:2]+'/'+date[2:4]+'/'+date[0:2]334 ret_Arg['nsat']=float(a[10])335 ret_Arg['text']=result.split(': ')[1].split('\n')[0]336 return _answer(echo, ret, ret_Arg['text'], ret_Arg)337338def gnss_enable_nmea():339 print(cellular_tx('AT+QGPSCFG="nmeasrc",1', 500, False, True).replace('\r', '').strip())340341def gnss_disable_nmea():342 print(cellular_tx('AT+QGPSCFG="nmeasrc",0', 500, False, True).replace('\r', '').strip())343344def gnss_get_nmea(sentence="GGA"):345 """gets an NMEA sentence.346 Valid sentences are “GGA”,“RMC”,“GSV”,“GSA”,“VTG”,“GNS”347 If the sentence is GGA, the code tries to extract data348 and returns it into an object.349 """350 a=cellular_tx('AT+QGPSGNMEA="'+sentence+'"', 500, False, True)351 b=a.split("\n")352 for x in b:353 if(x.startswith('+QGPSGNMEA: $GPGGA')):354 c=x[12:]355 c=c.split(',')356 result={}357 time=c[1].split('.')358 time=time[0]359 result['tof']=time[0:2]+':'+time[2:4]+':'+time[4:]+' UTC'360 valid=c[6]361 if(valid==0):362 print(" Fix is not valid! Aborting.")363 result['valid']=False364 return result365 result['valid']=True366 SVs=c[7]367 result['SVs']=float(SVs)368 OrthoHeight=c[9]+' '+c[10]369 result['orthoheight']=float(c[9])370 long=float(c[2])371 NS=c[3]372 x=int(long/100)373 y=((long/100)-x)*10/6374 long=x+y375 result['long']=long376 result['NS']=NS377 lat=float(c[4])378 EW=c[5]379 x=int(lat/100)380 y=((lat/100)-x)*10/6381 lat=x+y382 result['lat']=lat383 result['EW']=EW384 return result385386def bg96_PI(echo=False, ret=True):387 """Gets the full Product Information.388 Equivalent to the next three commands plus bg96_IMEI."""389 result=cellular_tx('ATI', 300, False, True).replace('\r', '').strip().split('\n')390 # Since the IMEI is part of the product info, no reason not to get it together.391 IMEI=bg96_IMEI(False, True)392 echo_Arg="Manufacturer: "+result[1]+"\nProduct: "+result[2]+"\n"+result[3]+"\nIMEI: "+IMEI393 a={}394 a['manufacturer']=result[1]395 a['product']=result[2]396 a['revision']=result[3].split(': ')[1]397 a['IMEI']=IMEI398 return _answer(echo, ret, echo_Arg, a)399400def bg96_Manufacturer(echo=False, ret=True):401 """Gets the Manufacturer's Name'"""402 result=cellular_tx('AT+GMI', 300, False, True).replace('\r', '').strip().split('\n')403 return _answer(echo, ret, "Manufacturer: "+result[1], result[1])404405def bg96_Product(echo=False, ret=True):406 """Gets the Product Name"""407 result=cellular_tx('AT+GMM', 300, False, True).replace('\r', '').strip().split('\n')408 return _answer(echo, ret, "Product: "+result[1], result[1])409410def bg96_Revision(echo=False, ret=True):411 """Gets the Software Revision"""412 result=cellular_tx('AT+GMR', 300, False, True).replace('\r', '').strip().split('\n')413 return _answer(echo, ret, "Revision: "+result[1], result[1])414415def bg96_IMEI(echo=False, ret=True):416 """Gets the Device's IMEI'"""417 result=cellular_tx('AT+GSN', 300, False, True).replace('\r', '').strip().split('\n')418 return _answer(echo, ret, "IMEI: "+result[1], result[1])419420def bg96_IMSI(echo=False, ret=True):421 """Query IMSI number of (U)SIM"""422 result=cellular_tx('AT+CIMI', 300, False, True).replace('\r', '').strip().split('\n')423 return _answer(echo, ret, "IMSI: "+result[1], result[1])424425def bg96_ICCID(echo=False, ret=True):426 """Gets the ICCID of the (U)SIM card'"""427 result=cellular_tx('AT+QCCID', 300, False, True).replace('\r', '').strip().split('\n')428 return _answer(echo, ret, "CCID: "+result[1], result[1])429430_insertStatus=[]431_insertStatus.append('(U)SIM card is removed.')432_insertStatus.append('(U)SIM card is inserted.')433_insertStatus.append('(U)SIM card status unknown, before (U)SIM initialization.')434435def bg96_SIM_Insertion(echo=False, ret=True):436 """Query (U)SIM card insertion status."""437 result=cellular_tx('AT+QSIMSTAT?', 300, False, True).replace('\r', '').strip()438 if(result.find('\n+QSIMSTAT: ')>-1):439 #AT+QSIMSTAT?\n+QSIMSTAT: 1,0440 a=result.split('\n')[1].split(': ')[1].split(',')441 if(a[0]=='0'):442 echo_Arg="(U)SIM card insertion status report dis"443 else:444 echo_Arg="(U)SIM card insertion status report en"445 echo_Arg+="abled.\n"+_insertStatus[int(a[1])]446 ret_Arg={}447 ret_Arg['enabled']=(a[0]=='1')448 ret_Arg['statusCode']=int(a[1])449 ret_Arg['status']=_insertStatus[int(a[1])]450 else:451 echo_Arg=result452 ret_Arg=result453 return _answer(echo, ret, echo_Arg, ret_Arg)454455def bg96_FactoryDefault():456 """Resets the device to Factory Default"""457 result=cellular_tx('AT&F', 300, False, True).replace('\r', '').strip()458 print(result)459460def bg96_Config():461 """Gets the Current Configuration"""462 result=cellular_tx('AT&V', 300, False, True).replace('\r', '').strip()463 result=result.replace('\n', '\nAT')464 result=result[:-7]465 print(result)466467def bg96_Save_User_Profile():468 """Saves the Current Configuration to the USer Profile"""469 result=cellular_tx('AT&W', 300, False, True).replace('\r', '').strip()470 print(result)471472def bg96_Load_User_Profile():473 """Loads the User Profile Configuration"""474 result=cellular_tx('ATZ', 300, False, True).replace('\r', '').strip()475 print(result)476477def bg96_Set_Result_Code(code=0):478 """Sets the Result Code Display to ON or OFF"""479 if(code<0) or (code>1):480 print("Use 0 for yes or")481 print("1 for no")482 return483 result=cellular_tx('ATQ'+str(code), 300, False, True).replace('\r', '').strip()484 print(result)485486def bg96_Result_code_On():487 """Sets the Result Code Display to ON"""488 result=cellular_tx('ATQ0', 300, False, True).replace('\r', '').strip()489 print(result)490491def bg96_Result_code_Off():492 """Sets the Result Code Display to OFF"""493 result=cellular_tx('ATQ1', 300, False, True).replace('\r', '').strip()494 print(result)495496def bg96_Set_Result_Code_Verbosity(code=0):497 """Sets the Result Code Verbosity"""498 if(code<0) or (code>1):499 print("Use 0 for non-verbose or")500 print("1 for verbose")501 return502 result=cellular_tx('ATV'+str(code), 300, False, True).replace('\r', '').strip()503 print(result)504505def bg96_Set_Command_Echo(code=0):506 """Sets the Command Echo to ON or OFF"""507 if(code<0) or (code>1):508 print("Use 0 for echo off or")509 print("1 for echo on")510 return511 result=cellular_tx('ATE'+str(code), 300, False, True).replace('\r', '').strip()512 print(result)513514def bg96_Power_Down(code=1):515 """Powers down the device"""516 if(code<0) or (code>1):517 print("Use 0 for immediate power down or")518 print("1 for normal power down")519 return520 result=cellular_tx('AT+QPOWD'+str(code), 300, False, True).replace('\r', '').strip()521 print(result)522523def bg96_Read_Clock(echo=False, ret=True):524 """Gets the time from the RTC525 Returns a dict with two key/value pairs526 date: yy/mm/dd527 time: hh:mm:ss528 """529 result=cellular_tx('AT+CCLK?', 300, False, True).replace('\r', '').strip()530 if(result.find('\n+CCLK: ')>-1):531 #AT+CCLK?\n+CCLK: "80/01/06,01:24:14"532 a=result.split('"')[1]533 echo_Arg=a534 a=a.split(',')535 ret_Arg={}536 ret_Arg['date']=a[0]537 ret_Arg['time']=a[1]538 else:539 echo_Arg=result540 ret_Arg=result541 return _answer(echo, ret, echo_Arg, ret_Arg)542543def bg96_Battery(echo=False, ret=True):544 """Gets the battery charging status545 Returns a dict with four key/value pairs546 code: [012]547 volt: <float>548 charging: True/False549 percent: <float>550 """551 result=cellular_tx('AT+CBC', 300, False, True).replace('\r', '').strip()552 if(result.startswith('AT+CBC\n+CBC: ')):553 a=result.split(': ')[1].split('\n')[0].split(',')554 if(a[0]=='0'):555 echo_Arg="Not charging... ["+a[1]+"% "+str(float(a[2])/1000)+"V]"556 if(a[0]=='1'):557 echo_Arg="Charging: "+a[1]+"% "+str(float(a[2])/1000)+"V"558 if(a[0]=='2'):559 echo_Arg="Done charging: "+a[1]+"% "+str(float(a[2])/1000)+"V"560 ret_Arg={}561 ret_Arg['code']=int(a[0])562 ret_Arg['charging']=(a[0]=='1')563 ret_Arg['percent']=float(a[1])564 ret_Arg['volt']=float(a[2])/1000565 else:566 echo_Arg=result567 ret_Arg={}568 return _answer(echo, ret, echo_Arg, ret_Arg)569570def bg96_Temp(echo=False, ret=True):571 """Gets the temperature for PMIC, XO and PA"""572 result=cellular_tx('AT+QTEMP', 300, False, True).replace('\r', '').strip()573 if(result.startswith('AT+QTEMP\n+QTEMP: ')):574 a=result.split(': ')[1].split('\n')[0].split(',')575 ret_Arg={}576 ret_Arg['PMIC']=float(a[0])577 ret_Arg['XO']=float(a[1])578 ret_Arg['PA']=float(a[2])579 echo_Arg="PMIC: "+a[0]+" C\nXO: "+a[1]+" C\nPA: "+a[2]+" C"580 else:581 echo_Arg="Unknown result code:\n "+result582 ret_Arg={}583 return _answer(echo, ret, echo_Arg, ret_Arg)584585_br9600=9600586_br19200=19200587_br38400=38400588_br57600=57600589_br115200=115200590_br230400=230400591_br460800=460800592_br921600=921600593594def bg96_Set_Baud_Rate(rate=115200, echo=False, ret=True):595 result=cellular_tx('AT+IPR='+str(rate), 300, False, True).replace('\r', '').strip()596 return _answer(echo, ret, result, result)597598_cpasStatus=[]599_cpasStatus.append('Ready')600_cpasStatus.append('Ringing')601_cpasStatus.append('Call in progress or call hold')602603def bg96_Activity_Status(echo=False, ret=True):604 result=cellular_tx('AT+CPAS', 300, False, True).replace('\r', '').strip().split('\n')[1]605 if(result.startswith('+CPAS: ')):606 a=int(result.split(': ')[1])607 ret_Arg={}608 ret_Arg['code']=a609 ret_Arg['text']=_cpasStatus[a]610 echo_Arg=_cpasStatus[a]+" ["+str(a)+"]"611 else:612 ret_Arg=result613 echo_Arg=result ...

Full Screen

Full Screen

CommandRemind.py

Source:CommandRemind.py Github

copy

Full Screen

1import SQLiteInterface as SQI2import re3import datetime4logtag = 'CommandRemind: '5async def entry(cmdArgs, message):6 if len(cmdArgs) < 2:7 await message.channel.send('Invalid format, give at least [hh:mm time to wait] [reminder text]')8 return 9 valid_ret = validate_command(cmdArgs)10 if valid_ret[0]:11 pass12 else:13 print(valid_ret[1])14 # date [date] [clock time]15 # eg >remind date 09/15/2021 15:30 smack Sam16 # the reminder will go out on 9/15/2021 at 15:3017 # time [clock time]18 # eg >remind 15:30 smack Sam19 # the next time 15:30 rolls around the reminder will go out20 # [time in hr:min]21 # eg >remind 4:30 smack Sam22 # Timer, runs for the amount of time given23def validate_command(args):24 cmd_type = args[0]25 cmd_args = args[1:]26 date_err = '''Invalid format. Use "remind date [mm/dd/yyyy] [hh:mm] [reminder text]"'''27 time_err = '''Invalid format. Use "remind time [hh:mm] [reminder text]"'''28 if cmd_type == 'date':29 if len(cmd_args) < 3:30 return [False, date_err]31 date_arg_str = cmd_args[0]32 time_arg_str = cmd_args[1]33 msg_arg = cmd_args[2]34 date_arg = split_date_arg(date_arg_str)35 if date_arg[3]:36 return [False, date_err]37 if not is_valid_date(date_arg):38 return [False, date_err]39 time_arg = split_time_arg(time_arg_str)40 if time_arg[2]:41 return [False, date_err]42 if not is_valid_time(time_arg):43 return [False, date_err]44 # Set the reminder45 return [True, create_reminder(date_arg[:-1] + time_arg[:-1], msg_arg)]46 elif cmd_type == 'time':47 if len(cmd_args) < 2:48 return [False, time_err]49 time_arg_str = cmd_args[0]50 msg_arg = cmd_args[1]51 time_arg = split_time_arg(time_arg_str)52 if time_arg[2]:53 return [False, time_err]54 if not is_valid_time(time_arg):55 return [False, time_err]56 ct = datetime.datetime.now()57 current_datetime = [ct.month, ct.day, ct.year, ct.hour, ct.minute]58 if time_is_after(time_arg[:-1], [ct.hour, ct.minute]):59 return [True, create_reminder(current_datetime[0:3] + time_arg[:-1], msg_arg)]60 else:61 new_date = add_date_args(current_datetime[0:3], [0, 1, 0])62 return [True, create_reminder(new_date + time_arg[:-1], msg_arg)]63 else: # No command type, just set a timer for the given duration64 pass65# Takes datetime styled argument - [month, day, year, hour, minute] and the msg_arg66def create_reminder(datetime_arg, msg_arg):67 pass68# Adds date_args together, returns the total date_arg69# The second date arg is added literally, and is not interpreted as an actual date70def add_date_args(a, b):71 ret_arg = a72 ret_arg[0] += b[0]73 ret_arg[1] += b[1]74 ret_arg[2] += b[2]75 # Correct days/months76 valid = False77 while not valid:78 if ret_arg[0] in [1, 3, 5, 7, 8, 10, 12]:79 if ret_arg[1] > 31:80 ret_arg[1] -= 3181 ret_arg[0] += 182 else:83 valid = True84 elif ret_arg[0] in [4, 6, 9, 11]:85 if ret_arg[1] > 30:86 ret_arg[1] -= 3087 ret_arg[0] += 188 else:89 valid = True90 else:91 if is_leap_year(ret_arg[2]):92 if ret_arg[1] > 29:93 ret_arg[1] -= 2994 ret_arg[0] += 195 else:96 valid = True97 else:98 if ret_arg[1] > 28:99 ret_arg[1] -= 28100 ret_arg[0] += 1101 else:102 valid = True103 # Correct months/years104 while ret_arg[0] > 12:105 ret_arg[2] += 1106 ret_arg[0] -= 12107 while ret_arg[0] < 1:108 ret_arg[2] -= 1109 ret_arg[0] += 12110 return ret_arg111# Takes 2 time_args and returns if the first is after the second112def time_is_after(a, b):113 if a[0] == b[0]:114 return a[1] > b[1]115 return a[0] > b[0]116# Splits the given time string into 2 parts, all ints117# Returns [h, m, err] - h, m are 0 when err == True118def split_time_arg(arg):119 split_arg = re.split(':', arg)120 if len(split_arg) != 2:121 return [0, 0, True]122 else:123 return [int(split_arg[0]), int(split_arg[1]), False]124# Splits the given date string into 3 parts, all ints125# Returns [m, d, y, err] - m, d, and y are 0 when err == True126def split_date_arg(arg):127 split_arg = re.split('/|-', arg)128 if len(split_arg) != 3:129 return [0, 0, 0, True]130 else:131 return [int(split_arg[0]), int(split_arg[1]), int(split_arg[2]), False]132# Check that the given time, in int format, is a valid time133def is_valid_time(v):134 h = v[0]135 m = v[0]136 if h > 23 or h < 0:137 return False138 if m > 59 or m < 0:139 return False140 return True141# Check that the given date, in int format, is a valid date142def is_valid_date(v):143 m = v[0]144 d = v[1]145 y = v[2]146 if m > 12 or m < 1:147 return False148 if d < 1:149 return False150 if m in [1, 3, 5, 7, 8, 10, 12]:151 return d <= 31152 elif m in [4, 6, 9, 11]:153 return d <= 30154 else:155 if is_leap_year(y):156 return d <= 29157 else:158 return d <= 28159def is_leap_year(y):160 if y % 2000:161 return False...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run avocado automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful