comparison py/params.py @ 293:d15dda1b1f76

merge
author Matt Johnston <matt@ucc.asn.au>
date Sat, 06 Jul 2019 18:29:45 +0800
parents ef3a75128116
children
comparison
equal deleted inserted replaced
292:28eb733cb803 293:d15dda1b1f76
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 import collections 2 import collections
3 import json 3 import json
4 import signal 4 import signal
5 import StringIO 5 import tempfile
6 6 import os
7 import gevent 7 import binascii
8 8
9 import config 9 import config
10 from utils import W,L,E,EX 10 from utils import W,L,E,EX
11 import utils
11 12
12 _FIELD_DEFAULTS = { 13 _FIELD_DEFAULTS = {
13 'fridge_setpoint': 16, 14 'fridge_setpoint': 16,
14 'fridge_difference': 0.2, 15 'fridge_difference': 0.2,
15 'overshoot_delay': 720, # 12 minutes 16 'overshoot_delay': 720, # 12 minutes
24 class Error(Exception): 25 class Error(Exception):
25 pass 26 pass
26 27
27 def __init__(self): 28 def __init__(self):
28 self.update(_FIELD_DEFAULTS) 29 self.update(_FIELD_DEFAULTS)
30 self._set_epoch(None)
29 31
30 def __getattr__(self, k): 32 def __getattr__(self, k):
31 return self[k] 33 return self[k]
32 34
33 def __setattr__(self, k, v): 35 def __setattr__(self, k, v):
34 # fail if we set a bad value 36 # fail if we set a bad value
35 self[k] 37 self[k]
36 self[k] = v 38 self[k] = v
37 39
38 def load(self, f = None): 40 def _set_epoch(self, epoch):
39 if not f: 41 # since __setattr__ is overridden
40 try: 42 object.__setattr__(self, '_epoch', epoch)
41 f = file(config.PARAMS_FILE, 'r') 43
42 except IOError, e: 44 def _do_load(self, f):
43 W("Missing parameter file, using defaults. %s", e)
44 return
45 try: 45 try:
46 u = json.load(f) 46 u = utils.json_load_round_float(f.read())
47 except Exception, e: 47 except Exception as e:
48 raise self.Error(e) 48 raise self.Error(e)
49 49
50 for k in u: 50 for k in u:
51 if k.startswith('_'): 51 if k.startswith('_'):
52 continue 52 continue
53 if k not in self: 53 if k not in self:
54 raise self.Error("Unknown parameter %s=%s in file '%s'" % (str(k), str(u[k]), getattr(f, 'name', '???'))) 54 raise self.Error("Unknown parameter %s=%s in file '%s'" % (str(k), str(u[k]), getattr(f, 'name', '???')))
55 self.update(u) 55 self.update(u)
56 # new epoch, 120 random bits
57 self._set_epoch(binascii.hexlify(os.urandom(15)).decode())
56 58
57 L("Loaded parameters") 59 L("Loaded parameters")
58 L(self.save_string()) 60 L(self.save_string())
59 61
62 def load(self, f = None):
63 if f:
64 return self._do_load(f)
65 else:
66 with open(config.PARAMS_FILE, 'r') as f:
67 try:
68 return self._do_load(f)
69 except IOError as e:
70 W("Missing parameter file, using defaults. %s" % str(e))
71 return
60 72
61 def save(self, f = None): 73 def get_epoch(self):
62 if not f: 74 return self._epoch
63 f = file(config.PARAMS_FILE, 'w') 75
64 json.dump(self, f, sort_keys=True, indent=4) 76 def receive(self, params, epoch):
65 f.write('\n') 77 """ updates parameters from the server. does some validation,
66 f.flush() 78 writes config file to disk.
79 Returns True on success, False failure
80 """
81
82 if epoch != self._epoch:
83 return
84
85 def same_type(a, b):
86 ta = type(a)
87 tb = type(b)
88
89 if ta == int:
90 ta = float
91 if tb == int:
92 tb = float
93
94 return ta == tb
95
96 if self.keys() != params.keys():
97 diff = self.keys() ^ params.keys()
98 E("Mismatching params, %s" % str(diff))
99 return False
100
101 for k, v in params.items():
102 if not same_type(v, self[k]):
103 E("Bad type for %s" % k)
104 return False
105
106 dir = os.path.dirname(config.PARAMS_FILE)
107 try:
108 t = tempfile.NamedTemporaryFile(prefix='config',
109 mode='w+t', # NamedTemporaryFile is binary by default
110 dir = dir,
111 delete = False)
112
113 out = json.dumps(params, sort_keys=True, indent=4)+'\n'
114 t.write(out)
115 name = t.name
116 t.close()
117
118 os.rename(name, config.PARAMS_FILE)
119 except Exception as e:
120 EX("Problem: %s" % e)
121 return False
122
123 self.update(params)
124 L("Received parameters")
125 L(self.save_string())
126 return True
67 127
68 def save_string(self): 128 def save_string(self):
69 s = StringIO.StringIO() 129 return json.dumps(self, sort_keys=True, indent=4)
70 self.save(s)
71 return s.getvalue()