1

我的任务是通过 snmp 从打印机读取错误代码。幸运的是,我有一个有效的 bash 脚本来指导我完成这个神秘的任务。我正在编写一些 python 来做一些与现有脚本不同的工作。现有的代码似乎可以工作,但它非常丑陋,我希望有一种更 Python 的方式来解析位。

首先,解释一下我对当前代码的阅读。snmpwalk查询返回的错误代码hrPrinterDetectedErrorState被编码为八位字节字符串,通常带有引号。所以引号与空格和换行符一起被剥离。错误代码最多可以有四个字节,但如果为零,通常会为第二对发送一个空字节,因此在这种情况下会添加一对零。然后将错误代码转换为十六进制。

现有的 bash 脚本:

parseErrorState()
{
  setUpErrorCodes
  # pull the error state w/o quotes
  errorState=`snmpwalk -Oqvx -c public -v $snmpV $printerIP hrPrinterDetectedErrorState | grep -v "End of MIB" | tr -d '"'`
  # remove spaces
  errorCode=$(echo $errorState | tr -d [:space:])
  errorString=""

  # if we don't have two hex bytes, append a byte of zeros
  if [[ ${#errorCode} == 2 ]]
  then
    errorCode=$errorCode"00"
  fi

  # do hex conversion
 let errorCode=0x$errorCode

 if (( $errorCode & $overduePreventMaint ))
 then
   errorString=$errorString"Overdue Preventative Maintenance; "
 fi
 if (( $errorCode & $inputTrayEmpty ))
 then
   errorString=$errorString"Input Tray Empty; "
 fi
 if (( $errorCode & $outputFull ))
 then
   errorString=$errorString"Output Full; "
 fi
 if (( $errorCode & $outputNearFull ))
 then
 ... and about 12 more if-thens...

这一系列 if-thens 逐位比较 与errorCode其中的每一个,并将相关字符串添加到输出中。

setUpErrorCodes()
  {
  lowPaper=32768
  noPaper=16384
  lowToner=8192
  noToner=4096
  doorOpen=2048
  jammed=1024
  offline=512
  serviceRequested=256

  inputTrayMissing=128
  outputTrayMissing=64
  markerSupplyMissing=32
  outputNearFull=16
  outputFull=8
  inputTrayEmpty=4
  overduePreventMaint=2
  }

我的 python 版本subprocess用于snmpwalk和或多或少地像上面那样进行格式化。然后:

# A dictionary of the errors and bit places
errors = {
    16: "low paper",
    15: "no paper",
    ...etc

# a still very ugly bit parse starting with a hex str like '2A00':
b = bin(int(hexstr, 16))[2:] # hex to int, int to bin, cut off the '0b'
binstr = str(b)
length = len(binstr)
indices = []
for i, '1' in enumerate(binstr):
     # find negative index of all '1's and multiply by -1
     # a hack to get around the binary string not containing leading zeros
     indices.append((i-length)*-1)

然后只需将索引与错误字典进行比较,就完成了。

无论如何,非常丑陋,可能效率很低。什么是更python-y,高级,可读的方式来完成同样的事情?

4

3 回答 3

3

您可以通过一个简单的循环获得设置标志的列表:

errors = {
    15: "low paper",
    14: "no paper",
    ...
}
flags = int(hexstr, 16)
flag_indices = []
for i in range(max(errors)):
    if flags & 1:
        flag_indices.append(i)
    flags >>= 1
于 2013-09-23T14:02:09.157 回答
2

鉴于您可以这样解析字符串:

flags = int(hexstr, 16)

你正在寻找

flag_indices = []
for flag in errors:
    if flags & (2**flag):
        flag_indices.append(flag)

无需构建列表并对其进行索引,您可以直接执行

(flags >> flag) & 1

在整数上会快得多。

于 2013-09-23T13:58:45.957 回答
0

我已经在带有标志枚举的powershell中完成了它。然后,如果我将生成的整数转换为标志枚举类型,它会将所有匹配的位作为字符串吐出。 如何读取 SNMP OID 输出

[hrPrinterDetectedErrorState]37124

inputTrayEmpty, serviceRequested, noToner, lowPaper
于 2019-03-29T15:30:39.900 回答