From e1b893069fc5d539180b955b2310e331335ac989 Mon Sep 17 00:00:00 2001 From: gmcgrath Date: Fri, 12 Dec 2014 12:22:08 -0500 Subject: [PATCH 1/5] started work on adding invokable helper app to interface file, also have begun altering returns for interface to be more end user friendly, get_relays now returns a dictionary of the statuses of all requested relays. --- iboot/iboot.py | 97 +++++++++++++++++++++++++++++++++++++++++++++++--- setup.py | 4 +++ 2 files changed, 96 insertions(+), 5 deletions(-) mode change 100644 => 100755 iboot/iboot.py mode change 100644 => 100755 setup.py diff --git a/iboot/iboot.py b/iboot/iboot.py old mode 100644 new mode 100755 index 97e34f2..74e2293 --- a/iboot/iboot.py +++ b/iboot/iboot.py @@ -4,8 +4,19 @@ import socket import struct + + HELLO_STR = 'hello-000' +"""struct format: +little-endian +unsigned char +21 char array +21 char array +unsigned char +unsigned char +unsigned short +""" HEADER_STRUCT = struct.Struct(' Date: Fri, 19 Dec 2014 14:34:58 -0500 Subject: [PATCH 2/5] code logging now functional, continuing with debugging the code itself. Currently believe the sequence number tracking is the root of the problem. --- iboot/iboot.py | 141 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 37 deletions(-) diff --git a/iboot/iboot.py b/iboot/iboot.py index 74e2293..517203a 100755 --- a/iboot/iboot.py +++ b/iboot/iboot.py @@ -4,18 +4,18 @@ import socket import struct - +logging.getLogger('iBootInterface').addHandler(logging.NullHandler()) HELLO_STR = 'hello-000' """struct format: little-endian -unsigned char -21 char array -21 char array -unsigned char -unsigned char -unsigned short +unsigned char command +21 char array username +21 char array password +unsigned char description +unsigned char parameters (should be padding byte or 'B' as unused) +unsigned short sequence number (uint16) - was H-2byte, set to I-4byte """ HEADER_STRUCT = struct.Struct(' Date: Mon, 22 Dec 2014 17:47:57 -0500 Subject: [PATCH 3/5] basic program now working, toggling, status, on, off. code cleanup, notification reductions and functionality expansion (quiet mode for integrating into tesla) need to be rounded out and tested --- iboot/iboot.py | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/iboot/iboot.py b/iboot/iboot.py index 517203a..9afafc4 100755 --- a/iboot/iboot.py +++ b/iboot/iboot.py @@ -83,6 +83,7 @@ def _get_boolean_response(self): return self._parse_bool(response) def _parse_bool(self, string): + self.logger.debug('dxpcommand.parsebool: string: ' + str(string)) return not struct.unpack('?', string)[0] def do_request(self): @@ -119,8 +120,8 @@ class IOCommand(DXPCommand): class RelayCommand(IOCommand): STATE_MAP = { True: 1, - False: 2, - 'NO_CHANGE': 0 + False: 0, + 'NO_CHANGE': 2 } def _get_response(self): @@ -187,16 +188,10 @@ def _get_response(self): response = struct.unpack(" Date: Wed, 24 Dec 2014 13:30:47 -0500 Subject: [PATCH 4/5] All critical sections of code now work, readme has been added, interfaces have been cleaned up a bit, quiet and debug modes now work --- README.md | 60 ++++++++++++++++++++++++ dist/iboot-0.1.0-py3.3.egg | Bin 0 -> 11538 bytes iboot/iboot.py | 93 ++++++++++++++++++++++++------------- setup.py | 9 ++-- 4 files changed, 126 insertions(+), 36 deletions(-) create mode 100644 README.md create mode 100644 dist/iboot-0.1.0-py3.3.egg diff --git a/README.md b/README.md new file mode 100644 index 0000000..c04a403 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# IBOOTPY +A simple tool that to replace the perl script provided with first generation iboot devices. Has been tested with an iBoot G2 and demonstrated to work. + +## Installation +In a virtual env, anaconda env, or other Python 3.x install you can simply run `python setup.py install`. + +This will add a iboot module to the site-packages as well as an ibootpy binary to the path + +### Files Created + * ibootpy - located in python environments 'bin' directory. + * iboot-0.1.0-py.egg - located (for anaconda) inside the environments lib/pythonX/site-packages/ folder. + + +## Inspiration +During an expansion of our lab management infrastructure we discovered the older perl script no longer functioned due to the move to the DxP protocol on newer devices. Fortunately the basic infrastructure for making DxP work via python existed, since the provided C libraries rely on winsock and are windows only. This expands the original library to provide a full tool for ease of use. + +## Usage +This update provides a basic command-line tool for using the DxP protocol allowing status checks, toggling relays, and setting all relays to on or off. It can be run using the command `ibootpy`. + +``` +ibootpy [-h] [--port PORT] [-v] [-q] [--debug] IP USER PASSWORD ACTION + +ibootpy - iBoot DxP Tool + +positional arguments: + IP IP you wish to interact with + USER User Name + PASSWORD Device Password + ACTION Action to perform on list of iBoot Devices (default status) + +optional arguments: + -h, --help show this help message and exit + --port PORT Port to communicate with device + -v, --verbose verbose output + -q, --quiet silence output, simply return success or failure. + --debug Enable Debug Output + +``` + +## Alterations From Base Package + +### Python Version +This module is now adjusted to be compliant with Python 3. + +### Get Relays +This now returns a dictionary of the relays correctly formatted for toggling and setting updates by updating the individual relay entries and feeding the dictionary back to the interface. + +### Logging +No longer institutes default DEBUG output, simply provides a logger called 'iBootInterface', when running ibootpy this defaults to INFO level output with flags to enable DEBUG or silence all output. + +### iBootDevice Interface Setup +The interface will now directly accept strings for username and password instead of requiring you to use str.encode() on them. It does this by simply checking for string types and converting them during `__init__` of the interface. + +### Normalization of Indexing +I've tried to step through the system and make sure that ranges are used the same everywhere, the relays are 1 indexed (this is not documented in the protocol sheet) so I've tried to make sure all indexing is done correctly vs. a 1 index instead of having to manipulate relay numbers mid code. + +## Future Work + * Properly formatted output instead of relying solely on log output. + * This may actually be easiest to do with a second logger that just handles formatted standard output, this would allow quiet to work relatively trivially. + * Refactoring of seq_num updates to easily readable code paths. There's updates in some odd places, they work but they make following code flow difficult. diff --git a/dist/iboot-0.1.0-py3.3.egg b/dist/iboot-0.1.0-py3.3.egg new file mode 100644 index 0000000000000000000000000000000000000000..df97ad29877b00c522c3e88cd52e2917ef6a3fae GIT binary patch literal 11538 zcmaia1yCH_)-CP?clY4#?(R;4+u%0ANpN>}cY?dy;2zxFf9?=! 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 VL;sb3U Date: Wed, 14 Jan 2015 15:58:53 -0500 Subject: [PATCH 5/5] added a legacy output mode for testing purposes and integrating with an older package using the gen 1 iboot interface --- .gitignore | 57 +++++++++++++++++++++++++++++++++++++ dist/iboot-0.1.0-py3.3.egg | Bin 11538 -> 0 bytes iboot/iboot.py | 12 ++++++-- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 .gitignore delete mode 100644 dist/iboot-0.1.0-py3.3.egg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb12ee7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# Created by https://www.gitignore.io + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ \ No newline at end of file diff --git a/dist/iboot-0.1.0-py3.3.egg b/dist/iboot-0.1.0-py3.3.egg deleted file mode 100644 index df97ad29877b00c522c3e88cd52e2917ef6a3fae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11538 zcmaia1yCH_)-CP?clY4#?(R;4+u%0ANpN>}cY?dy;2zxFf9?=! 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 VL;sb3U