comparison py/params.py @ 253:0a1b642e3086

long polling config updates
author Matt Johnston <matt@ucc.asn.au>
date Mon, 08 Jun 2015 22:29:46 +0800
parents 19569cb5ed46
children 26eee8591f61
comparison
equal deleted inserted replaced
251:b6079cb0c665 253:0a1b642e3086
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 io 5 import io
6 import tempfile
6 7
7 import config 8 import config
8 from utils import W,L,E,EX 9 from utils import W,L,E,EX
10 import utils
9 11
10 _FIELD_DEFAULTS = { 12 _FIELD_DEFAULTS = {
11 'fridge_setpoint': 16, 13 'fridge_setpoint': 16,
12 'fridge_difference': 0.2, 14 'fridge_difference': 0.2,
13 'overshoot_delay': 720, # 12 minutes 15 'overshoot_delay': 720, # 12 minutes
22 class Error(Exception): 24 class Error(Exception):
23 pass 25 pass
24 26
25 def __init__(self): 27 def __init__(self):
26 self.update(_FIELD_DEFAULTS) 28 self.update(_FIELD_DEFAULTS)
29 self._epoch = None
27 30
28 def __getattr__(self, k): 31 def __getattr__(self, k):
29 return self[k] 32 return self[k]
30 33
31 def __setattr__(self, k, v): 34 def __setattr__(self, k, v):
43 if k.startswith('_'): 46 if k.startswith('_'):
44 continue 47 continue
45 if k not in self: 48 if k not in self:
46 raise self.Error("Unknown parameter %s=%s in file '%s'" % (str(k), str(u[k]), getattr(f, 'name', '???'))) 49 raise self.Error("Unknown parameter %s=%s in file '%s'" % (str(k), str(u[k]), getattr(f, 'name', '???')))
47 self.update(u) 50 self.update(u)
51 self._epoch = utils.hexnonce()
48 52
49 L("Loaded parameters") 53 L("Loaded parameters")
50 L(self.save_string()) 54 L(self.save_string())
51 55
52 def load(self, f = None): 56 def load(self, f = None):
58 return self._do_load(f) 62 return self._do_load(f)
59 except IOError as e: 63 except IOError as e:
60 W("Missing parameter file, using defaults. %s" % str(e)) 64 W("Missing parameter file, using defaults. %s" % str(e))
61 return 65 return
62 66
63 def _do_save(self, f): 67 def get_epoch(self):
64 json.dump(self, f, sort_keys=True, indent=4) 68 return self._epoch
65 f.write('\n')
66 f.flush()
67 69
68 def save(self, f = None): 70 def receive(self, params, epoch):
69 if f: 71 """ updates parameters from the server. does some validation,
70 return self._do_save(f) 72 writes config file to disk.
71 else: 73 Returns True on success, False failure
72 with file(config.PARAMS_FILE, 'w') as f: 74 """
73 return self._do_save(f) 75
76 if epoch != self._epoch:
77 return
78
79 def same_type(a, b):
80 ta = type(a)
81 tb = type(b)
82
83 if ta == int:
84 ta = float
85 if tb == int:
86 tb = float
87
88 return ta == tb
89
90 if self.keys() != new_params.keys():
91 diff = self.keys() ^ new_params.keys()
92 E("Mismatching params, %s" % str(diff))
93 return False
94
95 for k, v in new_params.items():
96 if not same_type(v, self[k]):
97 E("Bad type for %s" % k)
98 return False
99
100 dir = os.path.dirname(config.PARAMS_FILE)
101 try:
102 t = tempfile.NamedTemporaryFile(prefix='config',
103 dir = dir,
104 delete = False)
105
106 t.write(json.dumps(new_params, sort_keys=True, indent=4)+'\n')
107 name = t.name
108 t.close()
109
110 os.rename(name, config.PARAMS_FILE)
111 return True
112 except Exception as e:
113 E("Problem: %s" % e)
114 return False
74 115
75 def save_string(self): 116 def save_string(self):
76 s = io.StringIO() 117 return json.dumps(self, sort_keys=True, indent=4)
77 self.save(s)
78 return s.getvalue()