-
Notifications
You must be signed in to change notification settings - Fork 11
/
netio2csv.py
executable file
·122 lines (95 loc) · 3.29 KB
/
netio2csv.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
#!/usr/bin/env python3
# Collect metering data from a Netio power sockets into CSV files.
#
# SPDX-FileCopyrightText: © 2020 Georg Sauthoff <[email protected]>
# SPDX-License-Identifier: GPL-3.0-or-later
import argparse
import collections
import configparser
import json
import logging
import os
import requests
import signal
import sys
import time
log = logging.getLogger(__name__)
def parse_args(*xs):
p = argparse.ArgumentParser()
p.add_argument('--config', '-c', default=os.getenv('HOME', '.') + '/.config/netio.ini',
help='config file for netio settings (default: %(default)s)')
p.add_argument('--socket', '-s', dest='sockets', type=int, nargs='*', default=[1],
help='power socket number(s) (default: %(default)s)')
p.add_argument('--interval', '-i', type=int, default=1,
help='collection interval (default: %(default)d)')
p.add_argument('-n', type=int, default=-1,
help='collect n times (default: %(default)d)')
p.add_argument('--output', '-o', default='output.csv',
help='output filename (default: %(default)s)')
args = p.parse_args(*xs)
return args
def parse_conf(filename):
conf = configparser.ConfigParser()
conf.read(filename)
Config = collections.namedtuple('Config', ['user', 'password', 'host'])
return Config(conf['netio'].get('user', None), conf['netio'].get('password', None),
conf['netio']['host'])
def set_proc_name(name):
if not os.path.exists('/proc/self/comm'):
return
with open(f'/proc/self/comm', 'w') as f:
f.write(name)
def measure_one(url, session, auth, args, f):
r = requests.get(url, **auth)
d = json.loads(r.text, parse_float=str, parse_int=str)
xs = [ str(int(time.time())), d['Agent']['DeviceName'] ]
xs.extend(d['GlobalMeasure'][n] for n in ('Voltage', 'Frequency'))
for k in args.sockets:
xs.extend(d['Outputs'][k-1][n] for n in ('State', 'Current', 'PowerFactor'))
print(','.join(xs), file=f)
def measure(url, session, auth, args, f):
i = 0
hs = [ 's', 'name', 'V', 'Hz' ]
for k in args.sockets:
# pf == true power factor -> https://en.wikipedia.org/wiki/Power_factor
hs.extend(f'{n}_{k}' for n in ('state', 'mA', 'pf'))
print(','.join(hs), file=f)
while i != args.n:
try:
measure_one(url, session, auth, args, f)
except Exception as e:
log.error(f'measurement failed: {e}')
time.sleep(args.interval)
if args.n > 0:
i += 1
class Sig_Term(Exception):
pass
class Sig_Hup(Exception):
pass
def terminate(signo, frame):
raise Sig_Term()
def hup(signo, frame):
raise Sig_Hup()
def main():
args = parse_args()
conf = parse_conf(args.config)
set_proc_name('netio2csv')
signal.signal(signal.SIGTERM, terminate)
signal.signal(signal.SIGHUP, hup)
session = requests.Session()
auth = {}
if conf.password:
auth['auth'] = (conf.user, conf.password)
url = f'{conf.host}/netio.json'
while True:
try:
with open(args.output, 'w') as f:
measure(url, session, auth, args, f)
break
except Sig_Hup:
pass
if __name__ == '__main__':
try:
sys.exit(main())
except (KeyboardInterrupt, Sig_Term):
print()