-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhayward_api.py
More file actions
206 lines (153 loc) · 6.59 KB
/
hayward_api.py
File metadata and controls
206 lines (153 loc) · 6.59 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import requests
import time
import xmltodict
class HaywardOmniLogic():
requests_templates = {'login': None,
'status': None,
'group_cmd': None,
'filter_cmd': None}
relays = {'5': 'slide_relay',
'6': 'bubbler_relay',
'8': 'uv_relay'}
lights = {'7': 'main_light',
'17': 'baja_light'}
groups = {'15': 'slide_group',
'16': 'bubbler_group'}
def __init__(self, username, password, systemid, verbose=False):
self.username = username
self.password = password
self.systemid = systemid
self.verbose = verbose
self.create_templates()
self.relays_reverse = {v: k for k, v in self.relays.items()}
self.groups_reverse = {v: k for k, v in self.groups.items()}
self.lights_reverse = {v: k for k, v in self.lights.items()}
self.current_status = None
self.logged_in = False
self.last_update = None
def create_templates(self):
for k in self.requests_templates.keys():
with open(f"{k}.xml") as f:
self.requests_templates[k] = ''.join(f.readlines())
def do_request(self, request_type, format_params=None):
url = 'http://www.haywardomnilogic.com:80/MobileInterface/MobileInterface.ashx'
request_xml = self.requests_templates[request_type]
if format_params is None:
format_params = dict()
format_params['username'] = self.username
format_params['password'] = self.password
format_params['systemid'] = self.systemid
if self.logged_in:
format_params['token'] = self.token
if format_params is not None:
request_xml = request_xml.format(**format_params)
if self.verbose:
print(request_xml)
r = requests.post(url, data=request_xml)
if self.verbose:
print(r)
if "xml version" in r.text:
fixed_output = r.text[38:].lower()
else:
fixed_output = r.text.lower()
if "You haven" in fixed_output:
return None
return xmltodict.parse(fixed_output)
def create_status_container(self, root):
d = {}
print(root['status']['backyard'])
r = root['status']['backyard']
d['system'] = {'air_temperature': int(r.get('airtemp')),
'status': int(r.get('status')),
'state': int(r.get('state'))}
r = root.bodyofwater
d['pool'] = {'water_temperature': int(r.get('watertemp')),
'flow': int(r.get('flow'))}
r = root.filter
d['filter'] = {'valve': int(r.get('valveposition')),
'filter_speed': int(r.get('filterspeed')),
'state': int(r.get('filterstate'))}
r = root.heater
d['heater'] = {'state': int(r.get('heaterstate')),
'temp': int(r.get('temp')),
'enabled': True if r.get('enable') == 'yes' else False,
'maintainfor': int(r.get('maintainfor'))}
for relay in root.iterchildren('relay'):
d[self.relays[relay.get('systemid')]] = {'state': int(relay.get('relaystate'))}
for light in root.iterchildren('colorlogic-light'):
d[self.lights[light.get('systemid')]] = {'state': int(light.get('lightstate')),
'show': int(light.get('currentshow'))}
for group in root.iterchildren('group'):
d[self.groups[group.get('systemid')]] = {'state': int(group.get('groupstate'))}
return d
def token_from_login(self, response):
if 'parameters' in response['response'] \
and 'parameter' in response['response']['parameters']:
params = response['response']['parameters']['parameter']
return([t['#text'] for t in params if t['@name'] == 'token'][0])
def connect(self):
login_response = self.do_request('login')
if login_response is None:
return False
self.token = self.token_from_login(login_response)
if self.token is None:
return False
self.logged_in = True
return self.refresh()
def refresh(self):
status_response = self.do_request('status')
if status_response is None:
return False
self.current_status = status_response['status']
self.last_update = time.time()
return True
def get_last_update_time(self):
return self.last_update
def set_filter_percent(self, filter_speed):
if self.current_status is None:
self.connect()
params = {'filter_speed': filter_speed}
response = self.do_request('filter_cmd', params)
time.sleep(3)
self.refresh()
return self.get_filter_percent()
def get_filter_percent(self):
if self.current_status is None:
self.connect()
return int(self.current_status['filter']['@filterspeed'])
def air_temperature(self):
if self.current_status is None:
self.connect()
return int(self.current_status['backyard']['@airtemp'])
def pool_temperature(self):
if self.current_status is None:
self.connect()
return int(self.current_status['bodyofwater']['@watertemp'])
def filter_is_on(self):
return self.current_status['filter']['@filterstate'] == "1"
def _relay_state_as_bool(self, relay):
the_relay = next(d for d in self.current_status["relay"]
if d['@systemid'] == self.relays_reverse[relay])
return the_relay['@relaystate'] == "1"
def slide_is_on(self):
return self._relay_state_as_bool('slide_relay')
def bubbler_is_on(self):
return self._relay_state_as_bool('bubbler_relay')
# def slide_group_is_on(self):
# return self._state_as_bool('slide_group')
#
# def bubbler_group_is_on(self):
# return self._state_as_bool('bubbler_group')
def main_light_is_on(self):
return self._state_as_bool('main_light')
def baja_light_is_on(self):
return self._state_as_bool('baja_light')
def turn_on_slide(self, speed=None):
if self.current_status is None:
self.connect()
params = {'group_id': self.groups_reverse['slide_group'],
'state': 1}
response = self.do_request('group_cmd', params)
# Now we're done so update the status
self.current_status = self.create_status_container(response)
return self.slide_group_is_on()