Skip to content

Commit

Permalink
Merge 36beeb4 into 1847fa9
Browse files Browse the repository at this point in the history
  • Loading branch information
vanstinator committed Apr 17, 2019
2 parents 1847fa9 + 36beeb4 commit b70b165
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 79 deletions.
10 changes: 6 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,13 @@ Usage
# show details from zone1
raincloudy.controller.faucet.zone1
{'auto_watering': True,
'droplet': 'https://wifiaquatimer.com/static/images/blank.gif',
{
'auto_watering': True,
'manual_watering': False
'next_cycle': 'Delayed',
'rain_delay': 1,
'watering_time': 0}
'watering_time': 0
}
# update attributes and show all zones
raincloudy.controller.update()
Expand Down Expand Up @@ -114,7 +116,7 @@ Usage
raincloudy.controller.faucet.zone1.auto_watering = True
# run water for 15 minutes on zone3
raincloudy.controller.faucet.zone3.watering_time = 15
raincloudy.controller.faucet.zone3.manual_watering = 15
# set rain delay for 2 days on zone2
raincloudy.controller.faucet.zone2.rain_delay = 2
Expand Down
45 changes: 21 additions & 24 deletions raincloudy/faucet.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
HOME_ENDPOINT, MANUAL_OP_DATA, MANUAL_WATERING_ALLOWED,
MAX_RAIN_DELAY_DAYS, MAX_WATERING_MINUTES)
from raincloudy.helpers import (
find_controller_or_faucet_name,
find_program_status, find_zone_name)
find_controller_or_faucet_name, find_zone_name)


class RainCloudyFaucetCore(object):
Expand Down Expand Up @@ -199,7 +198,7 @@ def name(self, value):
"""Set a new zone name to faucet."""
self._set_zone_name(self.id, value)

def _set_watering_time(self, zoneid, value):
def _set_manual_watering_time(self, zoneid, value):
"""Private method to set watering_time per zone."""
if value not in MANUAL_WATERING_ALLOWED:
raise ValueError(
Expand All @@ -223,13 +222,9 @@ def _set_watering_time(self, zoneid, value):
@property
def watering_time(self):
"""Return watering_time from zone."""
# zone starts with index 0
index = self.id - 1
auto_watering_time =\
self._attributes['rain_delay_mode'][index]['auto_watering_time']
auto_watering_time = self.lookup_attr('auto_watering_time')

manual_watering_time =\
self._attributes['rain_delay_mode'][index]['manual_watering_time']
manual_watering_time = self.lookup_attr('manual_watering_time')

if auto_watering_time > manual_watering_time:
watering_time = auto_watering_time
Expand All @@ -238,14 +233,15 @@ def watering_time(self):

return watering_time

@watering_time.setter
def watering_time(self, value):
"""Manually turn on water for X minutes."""
return self._set_watering_time(self.id, value)

@property
def droplet(self):
return None
def manual_watering(self):
"""Return zone manual_mode_on"""
return self.lookup_attr('manual_mode_on')

@manual_watering.setter
def manual_watering(self, value):
"""Manually turn on water for X minutes."""
return self._set_manual_watering_time(self.id, value)

def _set_rain_delay(self, zoneid, value):
"""Generic method to set auto_watering program."""
Expand Down Expand Up @@ -274,8 +270,7 @@ def _set_rain_delay(self, zoneid, value):
@property
def rain_delay(self):
"""Return the rain delay day from zone."""
index = self.id - 1
return self._attributes['rain_delay_mode'][index]['rain_delay_mode']
return self.lookup_attr('rain_delay_mode')

@rain_delay.setter
def rain_delay(self, value):
Expand All @@ -285,8 +280,7 @@ def rain_delay(self, value):
@property
def next_cycle(self):
"""Return the time scheduled for next watering from zone."""
index = self.id - 1
return self._attributes['rain_delay_mode'][index]['next_water_cycle']
return self.lookup_attr('next_water_cycle')

def _set_auto_watering(self, zoneid, value):
"""Private method to set auto_watering program."""
Expand All @@ -308,8 +302,7 @@ def _set_auto_watering(self, zoneid, value):
@property
def auto_watering(self):
"""Return if zone is configured to automatic watering."""
value = "zone{}".format(self.id)
return find_program_status(self._parent.html['home'], value)
return self.lookup_attr('program_mode_on')

@auto_watering.setter
def auto_watering(self, value):
Expand All @@ -321,13 +314,17 @@ def is_watering(self):
"""Return boolean if zone is watering."""
return bool(self.watering_time > 0)

def lookup_attr(self, attr):
"""Returns rain_delay_mode attributes by zone index"""
return self._attributes['rain_delay_mode'][int(self.id) - 1][attr]

def _to_dict(self):
"""Method to build zone dict."""
return {
'auto_watering':
getattr(self, "auto_watering"),
'droplet':
getattr(self, "droplet"),
'manual_watering':
getattr(self, "manual_watering"),
'is_watering':
getattr(self, "is_watering"),
'name':
Expand Down
36 changes: 0 additions & 36 deletions raincloudy/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,42 +54,6 @@ def serial_finder(data):
'Could not find any valid controller or faucet')


def find_program_status(data, zone):
"""
Find on the HTML document if zoneX has the configuration
of the auto-schedule/program (auto_watering) enabled.
# expected result if enabled
#<input checked="checked" class="switch" id="id_zone2_program_toggle" \
name="zone2_program_toggle" onchange="submit()" type="checkbox"/>
# expected result if disabled
#<input class="switch" id="id_zone1_program_toggle" \
name="zone1_program_toggle" onchange="submit()" type="checkbox"/>
:param data: BeautifulSoup object
:param zone: zone name from class='switch'
:return: boolean if zone has program enabled
:rtype: boolean
:raises TypeError: if data is not a BeautifulSoup object
:raises IndexError: if object not found
"""
if not isinstance(data, BeautifulSoup):
raise TypeError("Function requires BeautilSoup HTML element.")

try:
child = data.find_all('input', {'class': 'switch'})
zone_id = 'id_{0}_program_toggle'.format(zone)
for member in child:
if member.get('type') == 'checkbox' and \
member.get('id') == zone_id:
return bool(member.has_attr('checked'))
raise IndexError
except (AttributeError, IndexError, ValueError):
raise RainCloudyException(
'Could not find any valid controller or faucet')


def find_controller_or_faucet_name(data, p_type):
"""
Find on the HTML document the controller name.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def readme():
setup(
name='raincloudy',
packages=['raincloudy'],
version='0.0.8',
version='0.1.0',
description='A Python library to communicate with Melnor' +
' RainCloud Smart Garden Watering Irrigation Timer' +
' (https://wwww.melnor.com/)',
Expand Down
11 changes: 7 additions & 4 deletions tests/test_faucet_zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def test_attributes(self):
# check zone attributes
ZONE_ATTRS = [
'auto_watering',
'manual_watering',
'battery',
'droplet',
'id',
'is_watering',
'name',
Expand All @@ -36,11 +36,15 @@ def test_attributes(self):
objname = "<RainCloudyFaucetZone: {}>".format('Front Yard')
self.assertEquals(faucet.zone1.__repr__(), objname)

self.assertEquals(faucet.zone1.auto_watering, False)
self.assertEquals(faucet.zone1.watering_time, 0)
self.assertEquals(faucet.zone4.rain_delay, 4)
self.assertEquals(faucet.zone3.current_time, CONTROLLER_TIMESTAMP)

self.assertTrue(faucet.zone2.manual_watering)
self.assertTrue(faucet.zone2.auto_watering)
self.assertFalse(faucet.zone1.manual_watering)
self.assertFalse(faucet.zone1.auto_watering)

self.assertIsInstance(faucet.zone2.report(), dict)

def test_private_methods(self):
Expand Down Expand Up @@ -72,7 +76,7 @@ def test_set_watering_time(self):

# verify allowed values
self.assertRaises(ValueError,
faucet.zone1._set_watering_time,
faucet.zone1._set_manual_watering_time,
faucet.zone1.id,
1000)

Expand All @@ -86,7 +90,6 @@ def test_watering_time(self):
# auto time
self.assertEqual(faucet.zone3.watering_time, 60)


def test_errors_or_exceptions(self):
"""Tests for errors or exceptions."""
faucet = self.rdy.controller.faucet
Expand Down
4 changes: 2 additions & 2 deletions tests/test_faucet_zone_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def test_post_actions(self, mock):

self.assertIsNone(setattr(zone, 'name', 'test'))

self.assertIsNone(setattr(zone, 'watering_time', 0))
self.assertIsNone(setattr(zone, 'watering_time', 'on'))
self.assertIsNone(setattr(zone, 'manual_watering', 0))
self.assertIsNone(setattr(zone, 'manual_watering', 'on'))

self.assertIsNone(setattr(zone, 'rain_delay', 0))
self.assertIsNone(setattr(zone, 'rain_delay', 1))
Expand Down
8 changes: 0 additions & 8 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ def test_serial_finder(self):
broken_html = generate_soup_html(load_fixture('home_broken.html'))
self.assertRaises(RainCloudyException, serial_finder, broken_html)

def test_find_program_status(self):
"""Test find_program_status method."""
from raincloudy.helpers import find_program_status

self.assertRaises(TypeError, find_program_status, None, None)
self.assertRaises(RainCloudyException, find_program_status,
self.rdy.html['home'], None)

def test_find_controller_or_faucet_name(self):
"""Test find_controller_or_faucet_name method."""
from raincloudy.helpers import find_controller_or_faucet_name as fcfn
Expand Down

0 comments on commit b70b165

Please sign in to comment.