-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfluke.py
131 lines (110 loc) · 3.05 KB
/
fluke.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python
"""Fluke - Fluke multimeter communication tool
Usage:
fluke [options] --port=PORT
fluke --help
fluke --version
Options:
-p PORT --port=PORT Device port name (e.g., COM1, COM11)
-s FACTOR --scale=FACTOR Scale factor for measurement
-r DIGITS --round=DIGITS # of decimal digits to round to (can be negative)
-h --help Show this screen
-v --version Show version
"""
from __future__ import print_function
import serial
import sys
import re
from docopt import docopt
def readline(port):
eol = b'\r'
leneol = len(eol)
line = bytearray()
while True:
c = port.read(1)
if c:
line += c
if line[-leneol:] == eol:
break
else:
break
return bytes(line)
class FlukeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class Fluke:
def __init__(self, portNum, name):
self._port = serial.Serial(portNum, baudrate=115200, timeout=.1, writeTimeout=0)
self._name = name
try:
result = self.__cmd("ID")
except FlukeError as e:
self._port.close()
self._port = serial.Serial(portNum, baudrate=9600, timeout=.1, writeTimeout=0)
result = self.__cmd("ID")
self._model = result.split(',')[0]
#print(name + " is a " + self._model)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self._port.close()
def __readline(self):
eol = b'\r'
leneol = len(eol)
line = bytearray()
while True:
c = self._port.read(1)
if c:
line += c
if line[-leneol:] == eol:
break
else:
break
return bytes(line)
def __cmd(self, command):
cmd_ack = 'no err'
for x in range(0,5):
self._port.write(command + '\r')
cmd_ack = self.__readline().rstrip('\r')
#print("CMD_ACK: '" + str(cmd_ack) + "'")
if (cmd_ack == '0'):
response = self.__readline().rstrip('\r')
return response
raise FlukeError(cmd_ack)
# Poll a Fluke device for current data point
def poll(self):
items = {0:(self._name, '')}
# Query for the current value
result = self.__cmd("QM")
valueIdx = 0
if (self._model == "FLUKE 189"):
# 189 responds with the command repeated first
valueIdx = 1
# Use regex to find number portion of the response
p = re.compile(r'[^\d-]*(-?[\d]+(\.[\d]*)?([eE][+-]?[\d]+)?)')
m = p.match(result.split(',')[valueIdx])
if m:
value = float(m.groups()[0])
items[0] = self._name, value
#print(items)
return items
def getParamNames(self):
return [self._name]
if __name__ == "__main__":
args = docopt(__doc__, version='fluke 1.0')
dev = Fluke(args['--port'], "dev")
value = float(dev.poll()[0][1])
scale = 1.0
if args['--scale'] is not None:
try:
scale = float(args['--scale'])
except ValueError:
print(args['--scale'] + " is not a number", file=sys.stderr)
value = value * scale
if args['--round']:
value = round(value, int(args['--round']))
if int(args['--round']) <= 0:
value = int(value)
sys.stdout.write(str(value))