diff --git a/AUTHORS.rst b/AUTHORS.rst index 876a4f9..f7de792 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -11,3 +11,4 @@ Contributors ------------ * mdallaire +* scondas diff --git a/HISTORY.rst b/HISTORY.rst index bc89633..baad778 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,14 @@ ======= History ======= +1.2.0 (2019-11-30) +------------------ +* Add LeavingWaterTemp and WaterFlowRate sensors (Series 7 WF) +* Added features to CLI (for details see --help) + - Added debug flag + - Added option sensor list specification + - Added continous reporting + - Added ability to specify furnace in a multi unit system 1.1.0 (2019-01-07) ------------------ diff --git a/README.rst b/README.rst index 87da936..58471c9 100644 --- a/README.rst +++ b/README.rst @@ -41,6 +41,8 @@ do a data reading at least every 30 seconds otherwise the websocket is closed on the server side for resource constraints. The symphony website does a poll on the websocket every 5 seconds. +The software now supports a CLI. For details, use waterfurnace --help + Known Issues / limitations ========================== diff --git a/setup.cfg b/setup.cfg index 63aca46..6797e95 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.1.0 +current_version = 1.2.0 commit = True tag = True diff --git a/setup.py b/setup.py index 6c3be65..63b79bc 100644 --- a/setup.py +++ b/setup.py @@ -31,11 +31,11 @@ setup( name='waterfurnace', - version='1.1.0', + version='1.2.0', description="Python interface for waterfurnace geothermal systems", entry_points={ 'console_scripts': [ - 'waterfurnace-debug=waterfurnace.cli:main' + 'waterfurnace=waterfurnace.cli:main' ] }, long_description=readme + '\n\n' + history, @@ -43,12 +43,6 @@ author_email='sean@dague.net', url='https://github.com/sdague/waterfurnace', packages=find_packages(include=['waterfurnace']), - # TODO(sdague): bring back when we add a cli - # entry_points={ - # 'console_scripts': [ - # 'waterfurnace=waterfurnace.cli:main' - # ] - # }, include_package_data=True, install_requires=requirements, license="Apache Software License 2.0", diff --git a/tests/test_symphony.py b/tests/test_symphony.py index f873ca6..31f7e66 100644 --- a/tests/test_symphony.py +++ b/tests/test_symphony.py @@ -152,6 +152,8 @@ def test_increment_read_data(self, mock_req, mock_ws_create): "tstatroomtemp": 69.7, "enteringwatertemp": 41.4, "aocenteringwatertemp": 0, + "leavingwatertemp": 36.7, + "waterflowrate": 12.2, "lockoutstatus": {"lockoutstatuscode": 0, "lockedout": 0}, "lastfault": 15, @@ -197,6 +199,8 @@ def test_increment_read_data(self, mock_req, mock_ws_create): assert data.tstathumidsetpoint == 40 assert data.tstatrelativehumidity == 45 assert data.enteringwatertemp == 41.4 + assert data.leavingwatertemp == 36.7 + assert data.waterflowrate == 12.2 assert data.leavingairtemp == 67.7 assert data.tstatactivesetpoint == 69 diff --git a/waterfurnace/__init__.py b/waterfurnace/__init__.py index 1e2082f..953dbaf 100644 --- a/waterfurnace/__init__.py +++ b/waterfurnace/__init__.py @@ -4,4 +4,4 @@ __author__ = """Sean Dague""" __email__ = 'sean@dague.net' -__version__ = '1.1.0' +__version__ = '1.2.0' diff --git a/waterfurnace/cli.py b/waterfurnace/cli.py index fd1be3a..6c583fb 100644 --- a/waterfurnace/cli.py +++ b/waterfurnace/cli.py @@ -4,30 +4,68 @@ import click import logging +import time +import datetime import waterfurnace.waterfurnace logging.basicConfig() logger = logging.getLogger() -logger.setLevel(logging.DEBUG) +logger.setLevel(logging.INFO) @click.command() -@click.option('-u', '--username', 'user', required=True) -@click.option('-p', '--password', 'passwd', required=True) -def main(user, passwd): - click.echo("User: {}, Pass: {}".format(user, passwd)) +@click.option('-u', '--username', 'user', required=True, + help='Symphony username') +@click.option('-p', '--password', 'passwd', required=True, + help='Symphony password') +@click.option('-s', '--sensors', 'sensors', required=False, + help='Comma separated list of sensors. Can be "all"') +@click.option('-c', '--continuous', 'continuous', required=False, + is_flag=True, help='Read sensors every 15 seconds continously') +@click.option('-D', '--device', 'device', required=False, default=0, + show_default=True, + help='Select device in multi-device system (0,1,2...]') +@click.option('-d', '--debug', 'debug', required=False, is_flag=True) +def main(user, passwd, sensors, continuous, device, debug): click.echo("\nStep 1: Login") + if debug: + logger.setLevel(logging.DEBUG) - wf = waterfurnace.waterfurnace.WaterFurnace(user, passwd) + wf = waterfurnace.waterfurnace.WaterFurnace(user, passwd, device=device) wf.login() click.echo("Login Succeeded: session_id = {}".format(wf.sessionid)) - click.echo("Attempting to read data") - data = wf.read() - click.echo(data) + while True: + + dt = datetime.datetime.now() + now = dt.strftime("%Y-%m-%d %H:%M:%S") + + click.echo("") + click.echo("Attempting to read data {}".format(now)) + data = wf.read() + + if sensors is None: + click.echo(data) + else: + if sensors == 'all': + attrs = dir(data) + sensorlist = [] + for attr in attrs: + if not attr.startswith('_'): + sensorlist.append(attr) + else: + sensorlist = list(sensors.split(",")) + + for sensor in sensorlist: + click.echo("{} = {}".format(sensor, getattr(data, sensor))) + + if continuous: + time.sleep(15) + else: + break if __name__ == "__main__": diff --git a/waterfurnace/waterfurnace.py b/waterfurnace/waterfurnace.py index 034b0e8..65e00c5 100644 --- a/waterfurnace/waterfurnace.py +++ b/waterfurnace/waterfurnace.py @@ -61,6 +61,8 @@ "TStatRoomTemp", "EnteringWaterTemp", "AOCEnteringWaterTemp", + "LeavingWaterTemp", + "WaterFlowRate", "lockoutstatus", "lastfault", "lastlockout", @@ -97,9 +99,10 @@ class WFError(WFException): class WaterFurnace(object): - def __init__(self, user, passwd, max_fails=5): + def __init__(self, user, passwd, max_fails=5, device=0): self.user = user self.passwd = passwd + self.device = device self.gwid = None self.sessionid = None self.tid = 0 @@ -148,7 +151,7 @@ def _login_ws(self): recv = self.ws.recv() data = json.loads(recv) _LOGGER.debug("Login response: %s" % data) - self.gwid = data["locations"][0]["gateways"][0]["gwid"] + self.gwid = data["locations"][0]["gateways"][self.device]["gwid"] self.next_tid() def login(self): @@ -253,12 +256,16 @@ def __init__(self, data={}): self.leavingairtemp = data.get('leavingairtemp') self.tstatroomtemp = data.get('tstatroomtemp') self.enteringwatertemp = data.get('enteringwatertemp') + self.leavingwatertemp = data.get('leavingwatertemp') # setpoints (degrees F) self.tstatheatingsetpoint = data.get('tstatheatingsetpoint') self.tstatcoolingsetpoint = data.get('tstatcoolingsetpoint') self.tstatactivesetpoint = data.get('tstatactivesetpoint') + # Loop water flow rate (gallons per minute) + self.waterflowrate = data.get('waterflowrate') + @property def mode(self): return FURNACE_MODE[self.modeofoperation]