Source code for hydrawiser.core
"""
This is the main library file. It contains the Hydrawiser
object, and its methods. To use this library import it,
and create an object using the api key for your controller.
See the README.md file for more details on the methods and
attributes available.
"""
import time
from hydrawiser.helpers import customer_details, status_schedule, set_zones
[docs]class Hydrawiser():
"""
:param user_token: User account API key
:type user_token: string
:returns: Hydrawiser object.
:rtype: object
"""
def __init__(self, user_token):
self._user_token = user_token
# Attributes that we will be tracking from the controller.
self.controller_info = []
self.controller_status = []
self.current_controller = []
self.status = None
self.controller_id = None
self.customer_id = None
self.num_relays = None
self.relays = []
self.status = None
self.name = None
self.sensors = []
self.running = None
self.update_controller_info()
[docs] def update_controller_info(self):
"""
Pulls controller information.
:returns: True if successfull, otherwise False.
:rtype: boolean
"""
# Read the controller information.
self.controller_info = customer_details(self._user_token)
self.controller_status = status_schedule(self._user_token)
if self.controller_info is None or self.controller_status is None:
return False
# Only supports one controller right now.
# Use the first one from the array.
self.current_controller = self.controller_info['controllers'][0]
self.status = self.current_controller['status']
self.controller_id = self.current_controller['controller_id']
self.customer_id = self.controller_info['customer_id']
self.num_relays = len(self.controller_status['relays'])
self.relays = self.controller_status['relays']
self.name = self.controller_info['controllers'][0]['name']
self.sensors = self.controller_status['sensors']
try:
self.running = self.controller_status['running']
except KeyError:
self.running = None
return True
[docs] def controller(self):
"""
Check if multiple controllers are connected.
:returns: Return the controller_id of the active controller.
:rtype: string
"""
if hasattr(self, 'controller_id'):
if len(self.controller_info['controllers']) > 1:
raise TypeError(
'Only one controller per account is supported.'
)
return self.controller_id
raise AttributeError('No controllers assigned to this account.')
def __repr__(self):
"""
Object representation.
:returns: Object name
:rtype: string
"""
return "<{0}: {1}>".format(self.__class__.__name__,
self.controller_id)
[docs] def relay_info(self, relay, attribute=None):
"""
Return information about a relay.
:param relay: The relay being queried.
:type relay: int
:param attribute: The attribute being queried, or all attributes for
that relay if None is specified.
:type attribute: string or None
:returns: The attribute being queried or None if not found.
:rtype: string or int
"""
# Check if the relay number is valid.
if (relay < 0) or (relay > (self.num_relays - 1)):
# Invalid relay index specified.
return None
else:
if attribute is None:
# Return all the relay attributes.
return self.relays[relay]
else:
try:
return self.relays[relay][attribute]
except KeyError:
# Invalid key specified.
return None
[docs] def suspend_zone(self, days, zone=None):
"""
Suspend or unsuspend a zone or all zones for an amount of time.
:param days: Number of days to suspend the zone(s)
:type days: int
:param zone: The zone to suspend. If no zone is specified then suspend
all zones
:type zone: int or None
:returns: The response from set_zones() or None if there was an error.
:rtype: None or string
"""
if zone is None:
zone_cmd = 'suspendall'
relay_id = None
else:
if zone < 0 or zone > (len(self.relays) - 1):
return None
else:
zone_cmd = 'suspend'
relay_id = self.relays[zone]['relay_id']
# If days is 0 then remove suspension
if days <= 0:
time_cmd = 0
else:
# 1 day = 60 * 60 * 24 seconds = 86400
time_cmd = time.mktime(time.localtime()) + (days * 86400)
return set_zones(self._user_token, zone_cmd, relay_id, time_cmd)
[docs] def run_zone(self, minutes, zone=None):
"""
Run or stop a zone or all zones for an amount of time.
:param minutes: The number of minutes to run.
:type minutes: int
:param zone: The zone number to run. If no zone is specified then run
all zones.
:type zone: int or None
:returns: The response from set_zones() or None if there was an error.
:rtype: None or string
"""
if zone is None:
zone_cmd = 'runall'
relay_id = None
else:
if zone < 0 or zone > (len(self.relays) - 1):
return None
else:
zone_cmd = 'run'
relay_id = self.relays[zone]['relay_id']
if minutes <= 0:
time_cmd = 0
if zone is None:
zone_cmd = 'stopall'
else:
zone_cmd = 'stop'
else:
time_cmd = minutes * 60
return set_zones(self._user_token, zone_cmd, relay_id, time_cmd)
[docs] def list_running_zones(self):
"""
Returns the currently active relay.
:returns: Returns the running relay number or None if no relays are
active.
:rtype: string
"""
self.update_controller_info()
if self.running is None or not self.running:
return None
return int(self.running[0]['relay'])
[docs] def is_zone_running(self, zone):
"""
Returns the state of the specified zone.
:param zone: The zone to check.
:type zone: int
:returns: Returns True if the zone is currently running, otherwise
returns False if the zone is not running.
:rtype: boolean
"""
self.update_controller_info()
if self.running is None or not self.running:
return False
if int(self.running[0]['relay']) == zone:
return True
return False
[docs] def time_remaining(self, zone):
"""
Returns the amount of watering time left in seconds.
:param zone: The zone to check.
:type zone: int
:returns: If the zone is not running returns 0. If the zone doesn't
exist returns None. Otherwise returns number of seconds left
in the watering cycle.
:rtype: None or seconds left in the waterting cycle.
"""
self.update_controller_info()
if zone < 0 or zone > (self.num_relays-1):
return None
if self.is_zone_running(zone):
return int(self.running[0]['time_left'])
return 0