Mercurial > templog
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() |