diff --git a/.gitignore b/.gitignore index d3588184..1bfc589d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.o *.pyc *.log +.idea /openzwave/ build/ dists/ @@ -50,6 +51,7 @@ debian/debhelper-build-stamp debian/python3-openzwave/ pybind lib.txt +log.txt pyozw.sqlite venv2/ venv3/ @@ -65,3 +67,4 @@ docs/joomla/ libopenzwave*.so .pipcache options.xml +dynamic.dockerfile diff --git a/.travis.yml b/.travis.yml index b89934aa..0b787937 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,39 @@ -language: cpp - +language: python sudo: required - +python: +- '3.5' env: matrix: - - DOCKER_BASE=ubuntu:latest - - DOCKER_BASE=debian:latest - + - DOCKER_BASE=ubuntu:latest + - DOCKER_BASE=debian:latest + - DOCKER_BASE=i386/ubuntu:xenial + #~ - DOCKER_BASE=arm32v7/ubuntu:xenial + #~ - DOCKER_BASE=arm64v8/ubuntu:xenial + #~ - DOCKER_BASE=resin/rpi-raspbian:latest + - DOCS="true" + global: + - secure: "LdXdleVnh5s6HRPWLh3LcYo+s2IpvxwjFOQSJdMM1/svpstBu+pqAy6y6ivn4u7RUgG1Hva+iImMmqoBw4MUl+CTvK1RTLsOFFa0z37XSdWJbHSA+SmH9Dith1iHjaHTnkMNRaJugfJoLm2RXsii4ksMZcncm0gQLChyH+kxzX+ytoz8ofKk6f8zKqa+8YYhTlsV+BtnaEJOli22FKmLI8glOYiJpJj9UG8xQkwzNlIxR0PNZxvXnfVLeIw4sF9R3h6fkM/PZGbEfn1roZYDsdepl6SwumfmY+gOB74Ze7oObeJjmXA1HC8NSrsivIDB+gfAzKE01Jk2LyNZ+T2u7Zlqjf9pV0HhkYuBhc38BkpeBKkMKliJwuSIwEdsGWR71rC7VmegSbKp/I3Ev3oWy3h0k/J/W4SIxhN4mc8DAhaIC5TPdMHHTBSWyh494PEjX5zrinq4w6K7qjWpUB6rEUpHTHIE/F5f46QRTwFb5bhusIH8Hjo7GceEtYy1h8vGJ16GnAqvvrBJBU5QKCSfJicMiOUPELl3iD86vOdrJyYiiU+jALvgQH70D7KA9igIGRjmOdv71D09bEOVAYSNOaBsiCtyZqyx8kDMSETJ92VwhLO/aKazoGqlgiI8bEqSHA7Tjah6vyeTdnZeWRg7Fh2RM4W1T7lkXqzICNbUdW0=" services: - - docker - +- docker before_install: - - docker pull ${DOCKER_BASE} - +- if [[ "${DOCKER_BASE}x" != "x" ]]; then + docker pull ${DOCKER_BASE}; + fi +- if [[ "${DOCS}" == "true" ]]; then + sudo apt-get update; + sudo make common-deps; + fi script: - - cat Dockerfile|sed -e "s#ubuntu:latest#${DOCKER_BASE}#" >dynamic.dockerfile && docker build -f dynamic.dockerfile . +- if [[ "${DOCKER_BASE}x" != "x" ]]; then + sed -e "s#ubuntu:latest#${DOCKER_BASE}#" Dockerfile > dynamic.dockerfile && docker build -t python-openzwave -f dynamic.dockerfile .; + fi +- if [[ "${DOCS}" == "true" ]]; then + set -e; + make doc-deps; + make install-api; + cd docs; + make html; + cd ..; + pip3 install doctr; + doctr deploy --built-docs docs/_build/html .; + fi diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9a925290..1b504fd0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,7 +1,77 @@ - Changelog ********* +python_openzwave 0.4.18.x: + * Fix python 2.7/appveyor + + * Add serial port auto-detection + +python_openzwave 0.4.17.x: + * Add wheels for Windows + +python_openzwave 0.4.16.x: + * Fix appveyor build for windows + +python_openzwave 0.4.15.x: + * Update embeded package + +python_openzwave 0.4.14.x: + * Use Cython 0.28.6 + + * Update embeded package + +python_openzwave 0.4.12.x: + * Improve support Windows + + * COMMAND_CLASS_ZWAVE_PLUS_INFO renamed to + COMMAND_CLASS_ZWAVEPLUS_INFO + + * Update thermostat + + * Update embeded package + +python_openzwave 0.4.11.x: + * Update embeded package + +python_openzwave 0.4.10.x: + * Improve support Windows in pip + + * Improve tests Windows + + * Update contructors for scenes and groups + +python_openzwave 0.4.9.x: + * Improve support Windows in pip + + * Update tests + +python_openzwave 0.4.6.x: + * First try to support Windows in pip + +python_openzwave 0.4.5.x: + * Fix bug in node statistics and add test. + + * Update Makefile to build flavor dev + + * Update pyozw_check. + + * Update default flavor : check cython is here before choosing + shared + + * Fix controller.update_ozw_config when directory isn't writable + +python_openzwave 0.4.4.x: + * Add new options to pyozw_check to list nodes on network. + +python_openzwave 0.4.3.x: + * Fix bug in default flavor. + +python_openzwave 0.4.1.x: + * Update the default flavor : try to use a precompiled library. + If can't find one, use the embeded package. + + * Add method to controller to get new config from github. + python_openzwave 0.4.0.x: * New installation process via pip @@ -46,6 +116,12 @@ python_openzwave 0.4.0.x: * Add tests for c++ library sync + * Add door locks helpers + + * Add helpers for config parameters + + * Add data_items to value's dict + python-openzwave 0.3.3: * Openzwave update diff --git a/DEVEL.txt b/DEVEL.txt index bd172b8c..f2d8f06b 100644 --- a/DEVEL.txt +++ b/DEVEL.txt @@ -1,4 +1,3 @@ - Developers information ********************** @@ -6,88 +5,44 @@ Developers information How to develop for python-openzwave =================================== -Get the sources +Fork the project on Github. + +Get the sources : - git clone https://github.com/OpenZWave/python-openzwave + git clone https://github.com/yourname/python-openzwave You can install all the dependances to develop for python-openzwave using the command : - sudo make developper-deps + sudo make developer-deps + +You must now install python-openzwave in develop mode. Depending on +which python version you prefer, use : + + make venv2-dev -You must now install python-openzwave in develop mode +or - make develop + make venv2-dev -Your password will be asked (by sudo) for installing eggs in your -local directory. +Keep in mind that your updates must be python 2 / python 3 compatible. Develop, test, debug, test, ... :) Update the documentation if needed. You surely found the documentation useful, so please keep it up to date. -You can create an account on travis or docker to run the tests. - -At last but not least, submit your request. - - -How to develop for libopenzwave (was python-openzwave-lib) -========================================================== - -After updating the pyx, you need to reinstall it. Otherwise, your -changes will not be applied : - - make develop - - -Tests -===== - -First, install the dependances : - - sudo make tests-deps +It a good idea to add automatic tests. -To launch all the tests suite (about 140 tests), use the followind -command : +Launch the full test suite (for python 2 and python 3) : - make tests + make venv-tests -To launch on ly some tests : +At last but not least, submit your request with the result of tests in +the comment. - nosetests --verbosity=2 tests/api/test_controller_command.py - -Some tests need manual operations (ie to add a node, to remove one, -...). For example, to test the remove node, use : - - export MANUALSKIP='False' && nosetests --verbosity=2 tests/api/test_controller_command.py -m test_150 && unset MANUALSKIP - test_150_command_remove_node_and_wait_for_user (tests.api.test_controller_command.TestControllerCommand) ... ok - - ---------------------------------------------------------------------- - Ran 1 test in 16.031s - - OK - -You should push the inclusion button of the node before the end of the -test. - -Some tests don't need a ZWave Stick to be launched, so they can be run -on the autobuilders (travis, docker, ...). Place them in the autobuild -directory. - -Travis-ci, Docker Hub, nosetests and pylint are used to test quality -of code. There reports are here : - - * Docker : https://registry.hub.docker.com/u/bibi21000/python- - openzwave/ - - * Travis : https://travis-ci.org/bibi21000/python-openzwave - - * Nosetests report - - * Coverage report - - * Pylint report +If you don't follow the previous steps, your PR will be refused or +letting in pending state until I've got time to test it. Documentation @@ -97,97 +52,7 @@ First, install the dependances : sudo make doc-deps -Documentation is managed with sphinx. Don't utpdate txt files (README, -INSTALL, ...), update the RST sources in docs. Use the following -commands to generate all docs files (txt, html and joomla) - -You need to have installed python-openzwave (in either develop or -install mode) before generating the documentation. - - make docs - - -Static vs dynamic (or shared) -============================= - -The openzwave (c++) lib needs to run as a singleton : it means that it -MUST have only one instance of the manager running on your computer. - -There is 2 ways of linking libraries with a program : - - * static : includes a copy of the library in your binary program. - This means that your program has its own instance of the library. - This the way the install.sh runs. So you CAN'T have another - program (like the control-panel) running when using the python- - openzwave library - - * dynamic or shared : includes a link to the library in your - binary program. This means that your program share the library - with other programs. In this case, the instance is owned directly - by the library. This the way the debian package works. So you CAN - have another program running when using the python-openzwave - library. Of course, this program MUST use the shared library too. - - -About sudo -========== - -If you are like me and don't like root (and sudo), you can use the -following tip to install packages via pip : - -Look at your python local library, it should looks like : - - ls -lisa /usr/local/lib/python2.7/dist-packages/ - total 2428 - 1445174 12 drwxrwsr-x 115 root staff 12288 avril 9 21:35 . - 1445172 4 drwxrwsr-x 4 root staff 4096 mai 2 2014 .. - 1457164 4 drwxr-sr-x 5 root staff 4096 nov. 26 2013 actdiag - 1715480 4 drwxr-sr-x 2 root staff 4096 nov. 26 2013 actdiag-0.5.1.egg-info - 1457163 4 -rw-r--r-- 1 root staff 1004 nov. 26 2013 actdiag_sphinxhelper.py - 1457172 4 -rw-r--r-- 1 root staff 620 nov. 26 2013 actdiag_sphinxhelper.pyc - .... - -So, add your common user to the staff group : - - sudo usermod -a -G staff userName - -Add the write right to the group staff - - sudo chmod -Rf g+w /usr/local/lib/python2.7/dist-packages/ - -And now, it's time log off and log on. Groups are checked when you -open the session. - -You can now install your packages without sudo. - - -Python3 and virtualenv -====================== - -Python 3 is actually not supported. - -A branch (python3) has been created with a special Dockerfile. It -build python-openzwave and launch some tests. This branch is -automatically merged from master at "make commit". - -So please, do not directly push under python3 branch. Make your -developments under master or another branch. - -It's important for me have python2/python3 compatibilty in the master -branch. cython can help for this : -http://docs.cython.org/src/tutorial/strings.html - -The Makefile sill try to automatically configure your version of -python (running python --version). - -If you want to install python-openzwave in a python virtual -environnement, you should use something like : - - make VIRTUAL_ENV=/path/to/my/venv ... - -If you use python 3 and your python executable is called python3 : - - make PYTHON_EXEC=python3 ... +Documentation is managed with sphinx. -You can also put these variables in a CONFIG.make file instead of -passing them to the command line +Don't update txt and rst files (README, INSTALL, ...) in the root +directory, update the RST sources in docs. diff --git a/Dockerfile b/Dockerfile index 34dc4a8e..0fa0cc47 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,15 @@ FROM ubuntu:latest MAINTAINER bibi21000 ENV PYOZW_DOCKER 1 +RUN apt-get update && apt-get dist-upgrade -y >/dev/null +RUN apt-get install -y --no-install-recommends make sudo apt-utils >/dev/null ADD . /home/pyozw WORKDIR /home/pyozw -RUN apt-get update && \ - apt-get dist-upgrade -y && \ - apt-get install -y make sudo -RUN ls -WORKDIR /home/pyozw/ -RUN make docker-deps -RUN make openzwave.gzip +RUN make docker-deps >/dev/null +RUN make openzwave.gzip >/dev/null RUN make venv-dev-autobuild-tests #RUN make venv-pypi-autobuild-tests +#RUN apt-get install --force-yes -y pkg-config >/dev/null +#RUN make venv-git_shared-autobuild-tests +#RUN apt-get remove --force-yes -y pkg-config >/dev/null RUN make venv-pypilive-autobuild-tests diff --git a/EXAMPLES.txt b/EXAMPLES.txt index 9c9f881e..a219c666 100644 --- a/EXAMPLES.txt +++ b/EXAMPLES.txt @@ -1,4 +1,3 @@ - python-openzwave **************** diff --git a/INSTALL_WIN.rst b/INSTALL_WIN.rst index 8c102ef1..6ced83fc 100755 --- a/INSTALL_WIN.rst +++ b/INSTALL_WIN.rst @@ -5,51 +5,183 @@ Installing python-openzwave on Windows ====================================== -This HOW-TO is for 0.4.X. +Install Microsoft tools +======================= -It should be possible to make it pip friendly. Need a command line to build openzwave c++ lib. +This package use MSBuild.exe to build openzwave code. -How To Build python-openzwave on Windows with VS2015 -==================================================== +You can find it in Visual Studio 2017 or Visual Studio 2015. -Assuming Python 3.5 is set in PATH -Assuming your python environment has pip, cython, setuptools +It's also possible to get it as a separate package. +Only release 14.0 and 15.0 of Microsft Build Tools are tested. -Get sources ------------ +You nust use the C++ compiler used to build your version of python : https://wiki.python.org/moin/WindowsCompilers -.. code-block:: bash - git clone https://github.com/openzwave/python-openzwave.git +Install other tools +=================== - cd python-openzwave - git clone git://github.com/OpenZWave/open-zwave.git openzwave +You need git to clone the repository and python (32 bits or 64 bits). Add it to your PATH. + +Install dependencies : + + - for python 2.7 : - cd openzwave - git checkout Dev - cd .. - git checkout + .. code-block:: bash + (venvX) pip install Cython six Louie -Build open-zwave ----------------- + - for python 3 : -Open openzwave/cpp/build/windows/vs2010/OpenZWave.sln in Visual Studio + .. code-block:: bash -When asked, accept the project upgrade to VS2015 + (venvX) pip install Cython six PyDispatcher -Build Win32|Release +clone repositories +================== +Clone python-openzwave: + + +.. code-block:: bash -Build python_openzwave ----------------------- + git clone https://github.com/OpenZWave/python-openzwave.git -From a Command Prompt, install it : +And clone open-zwave inside python-openzwave : .. code-block:: bash - python setup install --dev + cd python-openzwave + git clone https://github.com/OpenZWave/open-zwave.git openzwave + +It's mandatory to clone the previous repository in a directory called openzwave (not open-zwave) + +Visual studio +============= + +Copy vs2010 in a new directory vs2017 (or vs2015 depending of which Visual Studio you use) : + +.. code-block:: bash -Reference for 0.3.X : https://github.com/OpenZWave/python-openzwave/issues/53 + xcopy openzwave\cpp\build\windows\vs2010 openzwave\cpp\build\windows\vs2017 /s /e /h + +Open the project (openzwave\cpp\build\windows\vs2017\OpenZWave.sln) in your Visual Studio. +If you want to build for 64bits, add a new target for it. And finally close it. + +Python-openzwave +================ + +Build and install python-openzwave : + + .. code-block:: bash + + python setup.py install --flavor=dev + + .. code-block:: bash + + sysargv ['setup.py', 'install'] + thon setup.py install --flavor=dev + Requirement already satisfied: Cython in c:\program files (x86)\python36-32\lib\site-packages + {'name': 'libopenzwave', 'sources': ['src-lib/libopenzwave/libopenzwave.pyx'], 'include_dirs': ['openzwave/cpp/src', 'openzwave + /cpp/src/value_classes', 'openzwave/cpp/src/platform', 'openzwave/cpp/build/windows', 'src-lib/libopenzwave', 'openzwave/cpp/bu + ild/windows/vs2017/Release/'], 'define_macros': [('PY_LIB_VERSION', '0.4.4'), ('PY_SSIZE_T_CLEAN', 1), ('PY_LIB_FLAVOR', 'dev') + , ('PY_LIB_BACKEND', 'cython')], 'libraries': ['setupapi', 'msvcrt', 'ws2_32', 'dnsapi'], 'extra_objects': ['openzwave/cpp/buil + d/windows/vs2017/Release//OpenZWave.lib'], 'extra_compile_args': [], 'extra_link_args': [], 'language': 'c++'} + ['six', 'PyDispatcher>=2.0.5', 'Cython'] + Requirement already satisfied: Cython in c:\program files (x86)\python36-32\lib\site-packages + running install + flavor --flavor=dev c:\program files (x86)\python36-32\lib\site-packages + running build_openzwave + Found MSBuild.exe : c:/Program Files (x86)/Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe + Found arch : Win32 wave + Found Visual Studio project : vs2017 (x86)/Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe + Found build path : openzwave/cpp/build/windows/vs2017/Release/ + ... + ... + byte-compiling C:\Program Files (x86)\Python36-32\Lib\site-packages\python_openzwave\scripts\__init__.py to __init__.cpython-36 + .pyc + running install_egg_info + running egg_info + writing python_openzwave.egg-info\PKG-INFO + writing dependency_links to python_openzwave.egg-info\dependency_links.txt + writing entry points to python_openzwave.egg-info\entry_points.txt + ================================================================ + .\scripts\allusers.bat + this script is executed for all users + delete/rename it if you dont need it + ================================================================ + Page de codes active�: 437 + +And finally, test it : + + .. code-block:: bash + + pyozw_check -l -d COM2 -t 30 + + .. code-block:: bash + + ------------------------------------------------------------------------------- + Define options for device COM2 + Start network + Wait for network awake (30s) + ------------------------------------------------------------------------------- + Network is awaked. Talk to controller. + Get python_openzwave version : 0.4.4 + Get python_openzwave config version : Original Z-Wave 2.78 + Get python_openzwave flavor : dev + Get openzwave version : 1.4.2942 + Get config path : C:\Program Files\Python36\lib\site-packages\python_openzwave\ozw_config + Controller capabilities : {'primaryController', 'staticUpdateController'} + Controller node capabilities : {'listening', 'primaryController', 'beaming', 'staticUpdateController'} + Nodes in network : 4 + ------------------------------------------------------------------------------- + Wait for network ready (30s) + ------------------------------------------------------------------------------- + Network is ready. Get nodes + ------------------------------------------------------------ + 1 - Name : ( Location : ) + 1 - Ready : True / Awake : True / Failed : False + 1 - Manufacturer : Aeotec ( id : 0x0086 ) + 1 - Product : DSA02203 Z-Stick S2 ( id : 0x0001 / type : 0x0002 / Version : 3) + 1 - Command classes : set() + 1 - Capabilities : {'listening', 'primaryController', 'beaming', 'staticUpdateController'} + 1 - Neighbors : {4} / Power level : None + 1 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 2 - Name : ( Location : ) + 2 - Ready : True / Awake : True / Failed : False + 2 - Manufacturer : ( id : 0x0000 ) + 2 - Product : ( id : 0x0000 / type : 0x0000 / Version : 2) + 2 - Command classes : set() + 2 - Capabilities : {'listening', 'routing'} + 2 - Neighbors : {3} / Power level : None + 2 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 3 - Name : ( Location : ) + 3 - Ready : False / Awake : True / Failed : True + 3 - Manufacturer : ( id : 0x0000 ) + 3 - Product : ( id : 0x0000 / type : 0x0000 / Version : 3) + 3 - Command classes : set() + 3 - Capabilities : {'listening', 'routing', 'beaming'} + 3 - Neighbors : set() / Power level : None + 3 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 4 - Name : ( Location : ) + 4 - Ready : True / Awake : True / Failed : False + 4 - Manufacturer : GreenWave ( id : 0x0099 ) + 4 - Product : PowerNode 6 port ( id : 0x0004 / type : 0x0003 / Version : 4) + 4 - Command classes : {'COMMAND_CLASS_MANUFACTURER_SPECIFIC', 'COMMAND_CLASS_ASSOCIATION', 'COMMAND_CLASS_NO_OPERATION', 'COMM + AND_CLASS_VERSION', 'COMMAND_CLASS_SWITCH_BINARY', 'COMMAND_CLASS_MULTI_INSTANCE/CHANNEL', 'COMMAND_CLASS_CRC_16_ENCAP', 'COMMA + ND_CLASS_PROTECTION', 'COMMAND_CLASS_CONFIGURATION', 'COMMAND_CLASS_BASIC', 'COMMAND_CLASS_METER', 'COMMAND_CLASS_SWITCH_ALL'} + 4 - Capabilities : {'listening', 'routing', 'beaming'} + 4 - Neighbors : {1} / Power level : None + 4 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + Driver statistics : {'SOFCnt': 49, 'ACKWaiting': 0, 'readAborts': 0, 'badChecksum': 0, 'readCnt': 49, 'writeCnt': 46, 'CANCnt': + 0, 'NAKCnt': 1, 'ACKCnt': 30, 'OOFCnt': 0, 'dropped': 17, 'retries': 0, 'callbacks': 0, 'badroutes': 0, 'noack': 4, 'netbusy': + 0, 'nondelivery': 0, 'routedbusy': 0, 'broadcastReadCnt': 0, 'broadcastWriteCnt': 9} + ------------------------------------------------------------ + Stop network + Exit diff --git a/Makefile b/Makefile index 51c760dc..9bb1a49b 100644 --- a/Makefile +++ b/Makefile @@ -44,18 +44,18 @@ WHL_PYTHON3 := $(shell ls dist/*.whl 2>/dev/null|grep ${python_openzwave_version ARCHNAME = python-openzwave-${python_openzwave_version} ARCHDIR = ${ARCHBASE}/${ARCHNAME} -.PHONY: help clean all update develop install install-api uninstall clean-docs docs autobuild-tests tests pylint commit developper-deps python-deps autobuild-deps arch-deps common-deps cython-deps check venv-clean venv2 venv3 +.PHONY: help clean all update develop install install-api uninstall clean-docs docs autobuild-tests tests pylint commit developer-deps python-deps autobuild-deps arch-deps common-deps cython-deps check venv-clean venv2 venv3 help: @echo "Please use \`make ' where is one of" @echo " build : build python-openzwave and openzwave" - @echo " develop : install python-openzwave for developpers" + @echo " develop : install python-openzwave for developers" @echo " install : install python-openzwave for users" @echo " install-api : install python-openzwave (API only) for users" @echo " uninstall : uninstall python-openzwave" - @echo " developper-deps : install dependencies for developpers" + @echo " developer-deps : install dependencies for developers" @echo " deps : install dependencies for users" - @echo " docs : make documentation" + @echo " docs : make documentation" @echo " tests : launch tests" @echo " commit : publish python-openzwave updates on GitHub" @echo " clean : clean the development directory" @@ -125,9 +125,9 @@ uninstall: -rm -Rf /usr/local/share/python-openzwave -rm -Rf /usr/local/share/openzwave -developper-deps: common-deps cython-deps tests-deps pip-deps doc-deps +developer-deps: common-deps cython-deps tests-deps pip-deps doc-deps @echo - @echo "Dependencies for developpers of python-openzwave installed (python ${python_version_full})" + @echo "Dependencies for developers of python-openzwave installed (python ${python_version_full})" repo-deps: common-deps cython-deps tests-deps pip-deps @echo @@ -157,7 +157,7 @@ endif ifeq (${python_version_major},3) apt-get install --force-yes -y cython3 endif - + ci-deps: apt-get install --force-yes -y python-pip python-dev python-docutils python-setuptools python-virtualenv -apt-get install --force-yes -y python3-pip python3-docutils python3-dev python3-setuptools @@ -182,7 +182,7 @@ tests-deps: doc-deps: -apt-get install --force-yes -y python-sphinx - ${PIP_EXEC} install sphinxcontrib-blockdiag sphinxcontrib-actdiag sphinxcontrib-nwdiag sphinxcontrib-seqdiag + ${PIP_EXEC} install cython sphinxcontrib-blockdiag sphinxcontrib-actdiag sphinxcontrib-nwdiag sphinxcontrib-seqdiag pip-deps: #${PIP_EXEC} install docutils @@ -197,18 +197,18 @@ clean-docs: -rm -Rf docs/pdf docs: clean-docs - -mkdir -p docs/html/nosetests - -mkdir -p docs/html/coverage - -mkdir -p docs/html/pylint - -mkdir -p docs/joomla/nosetests - -mkdir -p docs/joomla/coverage - -mkdir -p docs/joomla/pylint + #-mkdir -p docs/html/nosetests + #-mkdir -p docs/html/coverage + #-mkdir -p docs/html/pylint + #-mkdir -p docs/joomla/nosetests + #-mkdir -p docs/joomla/coverage + #-mkdir -p docs/joomla/pylint #${NOSE_EXEC} $(NOSEOPTS) $(NOSECOVER) tests/ #${NOSE_EXEC} $(NOSEOPTS) tests/ - -cp docs/html/nosetests/* docs/joomla/nosetests - -cp docs/html/coverage/* docs/joomla/coverage + #-cp docs/html/nosetests/* docs/joomla/nosetests + #-cp docs/html/coverage/* docs/joomla/coverage #-$(PYLINT) --output-format=html $(PYLINTOPTS) src-lib/libopenzwave/ src-api/openzwave/ src-manager/pyozwman/ src-web/pyozwweb/>docs/html/pylint/report.html - -cp docs/html/pylint/* docs/joomla/pylint/ + #-cp docs/html/pylint/* docs/joomla/pylint/ cd docs && $(MAKE) docs cp docs/README.rst README.rst cp docs/INSTALL_REPO.rst . @@ -220,12 +220,12 @@ docs: clean-docs cp docs/_build/text/CHANGELOG.txt . cp docs/_build/text/DEVEL.txt . cp docs/_build/text/EXAMPLES.txt . - cp -Rf docs/_build/html/* docs/html/ - cp -Rf docs/_build/joomla/* docs/joomla/ + #cp -Rf docs/_build/html/* docs/html/ + #cp -Rf docs/_build/joomla/* docs/joomla/ @echo @echo "Documentation finished." -install-lib: build +install-lib: ${PYTHON_EXEC} setup-lib.py install --flavor=git @echo @echo "Installation of lib finished." @@ -252,11 +252,11 @@ develop: src-lib/libopenzwave/libopenzwave.cpp ${PYTHON_EXEC} setup-web.py develop ${PYTHON_EXEC} setup.py develop --flavor=dev @echo - @echo "Installation for developpers of python-openzwave finished." + @echo "Installation for developers of python-openzwave finished." tests: - #export NOSESKIP=False && ${NOSE_EXEC} $(NOSEOPTS) tests/ --with-progressive; unset NOSESKIP - export NOSESKIP=False && ${NOSE_EXEC} $(NOSEOPTS) tests/lib tests/api tests/manager ; unset NOSESKIP + export NOSESKIP=False && ${NOSE_EXEC} $(NOSEOPTS) tests/; unset NOSESKIP +#~ export NOSESKIP=False && ${NOSE_EXEC} $(NOSEOPTS) tests/lib tests/api tests/manager ; unset NOSESKIP @echo @echo "Tests for ZWave network finished." @@ -275,7 +275,7 @@ update: openzwave cd openzwave && git pull build: openzwave/.lib/ - ${PYTHON_EXEC} setup-lib.py build + ${PYTHON_EXEC} setup-lib.py build --flavor=dev src-lib/libopenzwave/libopenzwave.cpp: openzwave/.lib/ ${PYTHON_EXEC} setup-lib.py build --flavor=dev @@ -387,6 +387,8 @@ pypi_package:clean-archive cp -f pyozw_pkgconfig.py $(ARCHBASE)/python_openzwave/ cp -f pyozw_setup.py $(ARCHBASE)/python_openzwave/ cp -f pyozw_version.py $(ARCHBASE)/python_openzwave/ + cp -f pyozw_win.py $(ARCHBASE)/python_openzwave/ + cp -f pyozw_progressbar.py $(ARCHBASE)/python_openzwave/ cp -f python_openzwave.egg-info/PKG-INFO $(ARCHBASE)/python_openzwave/ -find $(ARCHBASE)/python_openzwave/ -name \*.pyc -delete 2>/dev/null || true -find $(ARCHBASE)/python_openzwave/ -name \*.so -delete 2>/dev/null || true @@ -417,7 +419,7 @@ commit: push @echo "Commits for branches master pushed on github." tag: - git tag v${python_openzwave_version} + -git tag v${python_openzwave_version} git push origin v${python_openzwave_version} @echo @echo "Tag pushed on github." @@ -461,9 +463,9 @@ new-version: validate-pr -$(MAKE) docs -git commit -m "Auto-commit for new-version" README.rst INSTALL_REPO.rst INSTALL_MAC.rst INSTALL_WIN.rst INSTALL_ARCH.rst LICENSE.txt COPYRIGHT.txt DEVEL.txt EXAMPLES.txt CHANGELOG.txt docs/ -git checkout $(ARCHIVES)/ - git commit -m "Update pyozw_version to ${python_openzwave_version}" pyozw_version.py + -git commit -m "Update pyozw_version to ${python_openzwave_version}" pyozw_version.py $(MAKE) debch - git commit -m "Update debian version to ${python_openzwave_version}" debian/ + -git commit -m "Update debian version to ${python_openzwave_version}" debian/ -$(MAKE) embed_openzave_master -$(MAKE) pypi_package -git add $(ARCHIVES)/python_openzwave-${python_openzwave_version}.zip && git commit -m "Add new pypi package" $(ARCHIVES)/python_openzwave-${python_openzwave_version}.zip && git push @@ -472,6 +474,7 @@ new-version: validate-pr -twine upload archives/python_openzwave-${python_openzwave_version}.zip -r pypitest -twine upload archives/python_openzwave-${python_openzwave_version}.zip -r pypi -$(MAKE) tag + sleep 60 $(MAKE) venv-pypitest-autobuild-tests $(MAKE) venv-pypilive-autobuild-tests @@ -496,16 +499,16 @@ venv-deps: common-deps apt-get install --force-yes -y python-all python-dev python3-all python3-dev python-virtualenv python-pip #~ apt-get install --force-yes -y python-wheel-common python3-wheel python-wheel python-pip-whl apt-get install --force-yes -y pkg-config wget unzip zip - pip install Cython + pip install Cython==0.28.6 pip install wheel docker-deps: common-deps apt-get install --force-yes -y python-all python-dev python3-all python3-dev python-virtualenv apt-get install --force-yes -y python3-pip python-pip python-wheel python3-wheel python-pip-whl - apt-get install --force-yes -y pkg-config wget unzip zip + apt-get install --force-yes -y wget unzip zip apt-get install --force-yes -y g++ libudev-dev libyaml-dev - pip install cython - pip3 install cython + pip install Cython==0.28.6 + pip3 install Cython==0.28.6 venv2: @echo //////////////////////////////////////////////////////////////////////////////////////////// @@ -515,8 +518,9 @@ venv2: @echo virtualenv --python=python2 venv2 + venv2/bin/python --version venv2/bin/pip install nose - venv2/bin/pip install Cython wheel six + venv2/bin/pip install Cython==0.28.6 wheel six pyserial venv2/bin/pip install 'Louie>=1.1' chmod 755 venv2/bin/activate -rm -f src-lib/libopenzwave/libopenzwave.cpp @@ -536,8 +540,9 @@ venv3: @echo virtualenv --python=python3 venv3 + venv3/bin/python --version venv3/bin/pip install nose - venv3/bin/pip install Cython wheel six + venv3/bin/pip install Cython==0.28.6 wheel six pyserial venv3/bin/pip install 'PyDispatcher>=2.0.5' chmod 755 venv3/bin/activate -rm -f src-lib/libopenzwave/libopenzwave.cpp @@ -550,14 +555,20 @@ venv3: @echo venv2-dev: venv2 src-lib/libopenzwave/libopenzwave.cpp - venv2/bin/python setup-lib.py install --flavor=dev - venv2/bin/python setup-api.py install - venv2/bin/python setup-manager.py install + venv2/bin/python setup-lib.py develop --flavor=dev + venv2/bin/python setup-api.py develop + venv2/bin/python setup-manager.py develop venv3-dev: venv3 src-lib/libopenzwave/libopenzwave.cpp - venv3/bin/python setup-lib.py install --flavor=dev - venv3/bin/python setup-api.py install -#~ venv3/bin/python setup-manager.py install + venv3/bin/python setup-lib.py develop --flavor=dev + venv3/bin/python setup-api.py develop + venv3/bin/python setup-manager.py develop + +venv2-install: venv2 src-lib/libopenzwave/libopenzwave.cpp + venv2/bin/python setup.py install --flavor=dev + +venv3-install: venv3 src-lib/libopenzwave/libopenzwave.cpp + venv3/bin/python setup.py install --flavor=dev venv2-shared: venv2 src-lib/libopenzwave/libopenzwave.cpp venv2/bin/python setup-lib.py install --flavor=shared @@ -575,23 +586,29 @@ venv-clean: -rm -rf venv3 -rm -f src-lib/libopenzwave/libopenzwave.cpp -venv-tests: venv2-dev venv3-dev +venv-tests: venv2-tests venv3-tests + +venv2-tests: venv2-dev @echo ========================================================================================== @echo + @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo - @echo "Launch tests for venv-autobuild-autobuild-tests." + @echo Tests for python2 @echo + @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo + -$(MAKE) PYTHON_EXEC=venv2/bin/python NOSE_EXEC=venv2/bin/nosetests tests + @echo - @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo - @echo Tests for python2 + @echo "Tests for venv2 done." @echo - @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo - -$(MAKE) PYTHON_EXEC=venv2/bin/python NOSE_EXEC=venv2/bin/nosetests tests + @echo ========================================================================================== + @echo +venv3-tests: venv3-dev @echo @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo @@ -599,11 +616,12 @@ venv-tests: venv2-dev venv3-dev @echo @echo //////////////////////////////////////////////////////////////////////////////////////////// @echo + -$(MAKE) PYTHON_EXEC=venv3/bin/python NOSE_EXEC=venv3/bin/nosetests tests @echo @echo - @echo "Tests for venv-autobuild-autobuild-tests done." + @echo "Tests for venv3 done." @echo @echo @echo ========================================================================================== @@ -720,14 +738,14 @@ venv-pypitest-autobuild-tests: venv-clean venv2 venv3 -rm -f libopenzwave*.so venv2/bin/pip install "urwid>=1.1.1" - venv2/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave + venv2/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild venv2/bin/python venv2/bin/pyozw_check -o raw|grep '(embed-' venv2/bin/pip install "Cython" venv2/bin/pip uninstall python_openzwave -y - venv2/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave --install-option="--flavor=git" + venv2/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave --install-option="--flavor=git" venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild - venv2/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave --force --install-option="--flavor=git" + venv2/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave --force --install-option="--flavor=git" venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild venv2/bin/python venv2/bin/pyozw_check venv2/bin/python venv2/bin/pyozw_shell --help @@ -744,14 +762,14 @@ venv-pypitest-autobuild-tests: venv-clean venv2 venv3 -rm -f libopenzwave*.so venv3/bin/pip install "urwid>=1.1.1" - venv3/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave + venv3/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild venv3/bin/python venv3/bin/pyozw_check -o raw|grep '(embed-' venv3/bin/pip install "Cython" venv3/bin/pip uninstall python_openzwave -y - venv3/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave --install-option="--flavor=git" + venv3/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave --install-option="--flavor=git" venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild - venv3/bin/pip install -i https://testpypi.python.org/pypi -vvv python_openzwave --force --install-option="--flavor=git" + venv3/bin/pip install -i https://pypi.python.org/pypi -vvv python_openzwave --force --install-option="--flavor=git" venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild venv3/bin/python venv3/bin/pyozw_check venv3/bin/python venv3/bin/pyozw_shell --help @@ -790,16 +808,22 @@ venv-pypilive-autobuild-tests: venv-clean venv2/bin/pip install "urwid>=1.1.1" venv2/bin/pip install "nose" venv2/bin/pip install -vv python_openzwave + venv2/bin/python venv2/bin/pyozw_check -o raw venv2/bin/python venv2/bin/pyozw_check -o raw|grep '(embed-' venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild -#~ venv2/bin/pip install Cython wheel - venv2/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=git" - venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv2/bin/pip install Cython==0.28.6 +#~ venv2/bin/pip install wheel venv2/bin/pip uninstall python_openzwave -y venv2/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=git" venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv2/bin/python venv2/bin/pyozw_check -o raw venv2/bin/python venv2/bin/pyozw_check -o raw|grep '(git-' venv2/bin/pip uninstall python_openzwave -y + venv2/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=ozwdev" + venv2/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv2/bin/python venv2/bin/pyozw_check -o raw + venv2/bin/python venv2/bin/pyozw_check -o raw|grep '(ozwdev-' + venv2/bin/pip uninstall python_openzwave -y @echo @echo //////////////////////////////////////////////////////////////////////////////////////////// @@ -817,16 +841,22 @@ venv-pypilive-autobuild-tests: venv-clean venv3/bin/pip install "nose" venv3/bin/pip install "urwid>=1.1.1" venv3/bin/pip install -vv python_openzwave + venv3/bin/python venv3/bin/pyozw_check -o raw venv3/bin/python venv3/bin/pyozw_check -o raw|grep '(embed-' venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild -#~ venv3/bin/pip install Cython wheel - venv3/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=git" - venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv3/bin/pip install Cython==0.28.6 +#~ venv3/bin/pip install wheel venv3/bin/pip uninstall python_openzwave -y venv3/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=git" venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv3/bin/python venv3/bin/pyozw_check -o raw venv3/bin/python venv3/bin/pyozw_check -o raw|grep '(git-' venv3/bin/pip uninstall python_openzwave -y + venv3/bin/pip install -vv python_openzwave --upgrade --install-option="--flavor=ozwdev" + venv3/bin/nosetests --verbose tests/lib/autobuild tests/api/autobuild tests/manager/autobuild + venv3/bin/python venv3/bin/pyozw_check -o raw + venv3/bin/python venv3/bin/pyozw_check -o raw|grep '(ozwdev-' + venv3/bin/pip uninstall python_openzwave -y -rm -f libopenzwave*.so @echo @@ -1297,7 +1327,7 @@ uninstallso: rm -Rf /usr/local/include/openzwave rm -Rf /usr/local/etc/openzwave rm -Rf /usr/local/share/doc/openzwave* - find /usr/local/lib/pkgconfig/ -iname libopenzwave.pc -delete + -find /usr/local/lib/pkgconfig/ -iname libopenzwave.pc -delete pyozw_pkgconfig.py: wget https://raw.githubusercontent.com/matze/pkgconfig/master/pkgconfig/pkgconfig.py diff --git a/Makefile.archive b/Makefile.archive index ce559770..59789fa6 100644 --- a/Makefile.archive +++ b/Makefile.archive @@ -109,9 +109,9 @@ uninstall: -rm -Rf /usr/local/share/python-openzwave -rm -Rf /usr/local/share/openzwave -developper-deps: common-deps cython-deps tests-deps pip-deps doc-deps +developer-deps: common-deps cython-deps tests-deps pip-deps doc-deps @echo - @echo "Dependencies for developpers of python-openzwave installed (python ${python_version_full})" + @echo "Dependencies for developers of python-openzwave installed (python ${python_version_full})" autobuild-deps: common-deps cython-deps tests-deps pip-deps apt-get install --force-yes -y git diff --git a/README.rst b/README.rst index ec7ab72c..c4ae7c44 100755 --- a/README.rst +++ b/README.rst @@ -6,18 +6,18 @@ :target: https://circleci.com/gh/OpenZWave/python-openzwave :alt: Circle status -.. image:: https://img.shields.io/pypi/dm/python_openzwave.svg - :target: https://pypi.python.org/pypi/python_openzwave - :alt: Pypi downloads +.. image:: https://ci.appveyor.com/api/projects/status/2ogl8tx7o3pqphc9?svg=true + :target: https://ci.appveyor.com/project/bibi21000/python-openzwave + :alt: Appveyor status .. image:: https://img.shields.io/pypi/format/python_openzwave.svg :target: https://pypi.python.org/pypi/python_openzwave :alt: Pypi format -.. image:: https://img.shields.io/pypi/status/python_openzwave.svg - :target: https://pypi.python.org/pypi/python_openzwave - :alt: Pypi status - +.. image:: https://img.shields.io/badge/Documentation-ok-brightgreen.svg?style=flat + :target: http://openzwave.github.io/python-openzwave/index.html + :alt: Documentation + ================ python-openzwave ================ @@ -30,79 +30,79 @@ python-openzwave is a python wrapper for the openzwave c++ library : https://git * a full-event webapp example : flask + socket.io + jquery * a suite of tests * many examples + * `Full documentation `_ -python-openzwave 0.4.0 is coming !!! -==================================== +python-openzwave 0.4.x is here !!! +================================== - - 0.4.0.x versions are for testers only. Don't use it in a production environement !!! +- New installation process via pip - - New installation process via pip - - - First, you need some build tools and libs. On ubuntu, you should use : +- First, you need some build tools and libs. On ubuntu, you should use : .. code-block:: bash sudo apt-get install --force-yes -y make libudev-dev g++ libyaml-dev - - Make your virtualenv and activate it : +- Make your virtualenv and activate it : .. code-block:: bash virtualenv --python=python3 venv3 source venv3/bin/activate - - Install the default (embed) flavor : +- Install the default flavor : .. code-block:: bash (venvX) pip install python_openzwave - - The previous command install python_openzwave statitically linked to sources downloaded from https://github.com/OpenZWave/python-openzwave/tree/master/archives. - You can change this using flavors. There is a bug in the package dependencies and flavors on some systems. You may need to install dependencies manualy : +- The previous command try to install python_openzwave with the flavor 'shared'. + If it can't find a precompiled library of openzwave, it will use the flavor 'embed' with sources downloaded from https://github.com/OpenZWave/python-openzwave/tree/master/archives. + You can change this using flavor option. + There is a bug in the package dependencies and flavors on some systems. You may need to install dependencies manualy : - - on python 2.7 : + - on python 2.7 : .. code-block:: bash - (venvX) pip install cython wheel six + (venvX) pip install cython wheel six pyserial (venvX) pip install 'Louie>=1.1' - - on python 3 : + - on python 3 : .. code-block:: bash - (venvX) pip install cython wheel six + (venvX) pip install cython wheel six pyserial (venvX) pip install 'PyDispatcher>=2.0.5' - - Choose your flavor : +- Choose your flavor : - embed : the default one. Download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives and build them. Python_openzwave is statically build using a cythonized version of libopenzwave. No need to install cython. - shared : if you have install openzwave as module manually, you can link python_openzwave to it. - git : download sources from openzwave github and link statically to it. - - embed_shared (experimental) : download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives, build and install as module on the system. + - embed_shared : download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives, build and install as module on the system. Python_openzwave use it. Need root access to install openzwave libs. - - git_shared (experimental) : download sources from openzwave github, build and install them as module on the system. + - git_shared : download sources from openzwave github, build and install them as module on the system. Python_openzwave use it. Need root access to install openzwave libs. - ozwdev and ozwdev_shared : use the dev branch of openzwave on github. - - dev : for python_openzwave developpers - + - dev : for python_openzwave developers. Look for openzwave sources in a local folder specified by the LOCAL_OPENZWAVE environment variable (defaults to 'openzwave'). - - Install it : +- Install it : .. code-block:: bash - (venvX) pip install python_openzwave --install-option="--flavor=git" + (venvX) pip install python_openzwave --no-deps --install-option="--flavor=git" - - You can update to the last version of openzwave using the git flavor : - +- You can update to the last version of openzwave using the git flavor : + .. code-block:: bash (venvX) pip uninstall -y python_openzwave - (venvX) pip install python_openzwave --no-cache-dir --install-option="--flavor=git" + (venvX) pip install python_openzwave --no-cache-dir --no-deps --install-option="--flavor=git" - - At last, you can launch pyozw_check: +- At last, you can launch pyozw_check to test your installation : If no usb stick is connected to the machine, launch : @@ -163,11 +163,55 @@ python-openzwave 0.4.0 is coming !!! Try to destroy manager Try to destroy options + You can list the nodes on your network using : + + .. code-block:: bash + + (venvX) pyozw_check -l -d /dev/ttyUSB0 -t 60 + + .. code-block:: bash + + ------------------------------------------------------------------------------- + Define options for device /dev/ttyUSB0 + Start network + Wait for network (30s) + Network is ready + ------------------------------------------------------------------------------- + Controller capabilities : {'primaryController', 'staticUpdateController'} + Controller node capabilities : {'listening', 'primaryController', 'staticUpdateController', 'beaming'} + Nodes in network : 4 + Driver statistics : {'noack': 6, 'routedbusy': 0, 'readCnt': 115, 'ACKWaiting': 0, 'badChecksum': 0, 'broadcastReadCnt': 0, 'NAKCnt': 0, 'broadcastWriteCnt': 9, 'dropped': 0, 'CANCnt': 0, 'callbacks': 0, 'OOFCnt': 0, 'readAborts': 0, 'badroutes': 0, 'SOFCnt': 115, 'netbusy': 0, 'writeCnt': 49, 'nondelivery': 0, 'ACKCnt': 49, 'retries': 0} + ------------------------------------------------------------ + 1 - Name : ( Location : ) + 1 - Ready : True / Awake : True / Failed : False + 1 - Manufacturer : Aeotec ( id : 0x0086 ) + 1 - Product : DSA02203 Z-Stick S2 ( id : 0x0001 / type : 0x0002 ) + 1 - Version : 3 / Secured : False / Zwave+ : False + 1 - Command classes : {'COMMAND_CLASS_NO_OPERATION', 'COMMAND_CLASS_BASIC'} + 1 - Capabilities : {'staticUpdateController', 'listening', 'primaryController', 'beaming'} + 1 - Neigbors : {4} / Power level : None + 1 - Is sleeping : False / Can wake-up : False / Battery level : None + + ... + + ------------------------------------------------------------ + 4 - Name : ( Location : ) + 4 - Ready : True / Awake : True / Failed : False + 4 - Manufacturer : GreenWave ( id : 0x0099 ) + 4 - Product : PowerNode 6 port ( id : 0x0004 / type : 0x0003 ) + 4 - Version : 4 / Secured : False / Zwave+ : False + 4 - Command classes : {'COMMAND_CLASS_BASIC', 'COMMAND_CLASS_CONFIGURATION', 'COMMAND_CLASS_SWITCH_BINARY', 'COMMAND_CLASS_VERSION', 'COMMAND_CLASS_CRC_16_ENCAP', 'COMMAND_CLASS_MANUFACTURER_SPECIFIC', 'COMMAND_CLASS_ASSOCIATION', 'COMMAND_CLASS_MULTI_INSTANCE/CHANNEL', 'COMMAND_CLASS_METER', 'COMMAND_CLASS_PROTECTION', 'COMMAND_CLASS_NO_OPERATION', 'COMMAND_CLASS_SWITCH_ALL'} + 4 - Capabilities : {'listening', 'routing', 'beaming'} + 4 - Neigbors : {1} / Power level : None + 4 - Is sleeping : False / Can wake-up : False / Battery level : None + + ... + - The old manager is now available via the pyozw_shell command. You need to install module "urwid>=1.1.1" with pip before using it. - libopenzwave and openzwave python modules are packaged in the python_openzwave. - So developpers needs to update their install_requires (it works fine with pyozw_manager). + So developers needs to update their install_requires (it works fine with pyozw_manager). They can use the following code to update softly : .. code-block:: python @@ -196,15 +240,6 @@ python-openzwave 0.4.0 is coming !!! - Please report your successful installations here : https://github.com/OpenZWave/python-openzwave/issues/73 -python-openzwave 0.3.0 is out !!! -================================= - -Look at CHANGELOG to see new features and release notes. - -Look at INSTALL_REPO to test it now. - -Look at INSTALL_ARCH to install from archive : no need to install cython anymore. - Support ======= You can ask for support on the google group : http://groups.google.com/d/forum/python-openzwave-discuss. @@ -215,87 +250,3 @@ Pull requests ============= Please read DEVEL documentation before submitting pull request. A lot of project tasks are done automatically or with makefile, so they must be done in a certain place or in a special order. - -Migrating from python-openzwave 0.2.X to 0.3.0 -============================================== -I need to update source tree of python-openzwave and modules's names because of a bug in setuptools -: https://bitbucket.org/pypa/setuptools/issue/230/develop-mode-does-not-respect-src . -Sorry for that. - -Update your sources: - -.. code-block:: bash - - git pull - -Before building python-openzwave 0.3.0, you must uninstall the old version : - -.. code-block:: bash - - sudo make uninstall - -About cython : I've made many tests using cython installed via pip : (0.20, 0.21 and 0.22). -Compilation is ok but a segfault appears when launching the tests. Please remove it. - -.. code-block:: bash - - sudo pip uninstall Cython - -You also need to make some minor updates in you code, look at CHANGELOG - -If you have problems, please submit an issue with : - - - cython -V - - the content of the directory /usr/local/lib/python2.7/dist-packages/ (for python2.7) - - the content of /usr/local/lib/python2.7/dist-packages/easy-install.pth (for python 2.7) - - -Ubuntu 64bits ... and the others -================================ - -If you're using Ubuntu 64 bits (and mayde others) and keep your distribution up to date, -you certainly have the segfault problem. - -Ubuntu 12.04 and 14.04 seems to be affected by this bug. Ubuntu 15.10 and Debian Jessie not. - -It appears with the last update of python : - -.. code-block:: bash - - $ python - Python 2.7.6 (default, Jun 22 2015, 17:58:13) - [GCC 4.8.2] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - - -I've open a discussion on cython-users here : https://groups.google.com/forum/#!topic/cython-users/mRsviGuCFOk - -The only way I found to avoid this is to rebuild and reinstall the old release of python : - -.. code-block:: bash - - wget https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6-8.dsc https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6.orig.tar.gz https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6-8.diff.gz - - dpkg-source -x python2.7_2.7.6-8.dsc - - sudo apt-get build-dep python2.7 - - cd python2.7-2.7.6 - - dpkg-buildpackage - -Wait, wait and await again :) - -.. code-block:: bash - - cd .. - - sudo dpkg -i *.deb - -To prevent future updates of python, you could mark its packages. For example, if you use apt to update your distribution, use the following command : - -.. code-block:: bash - - sudo apt-mark hold idle-python2.7 libpython2.7-minimal python2.7-dbg python2.7-minimal libpython2.7 libpython2.7-stdlib python2.7-dev libpython2.7-dbg libpython2.7-testsuite python2.7-doc libpython2.7-dev python2.7 python2.7-examples - -Some users have reported that building python-openzwave using the archive (INSTALL_ARCH) can also do the trick. Let me know if it works for you. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..0dfab890 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,140 @@ +environment: + PYPI_USER: + secure: yna6KiH2GE3Ka1G5a3TlUQ== + PYPI_PASSWORD: + secure: UpISOsYyHdCzurReV6FcTA== + + global: + # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the + # /E:ON and /V:ON options are not enabled in the batch script intepreter + # See: http://stackoverflow.com/a/13751649/163740 + CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" + + matrix: + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python36" + PYTHON_VERSION: "3.6.x" + PYTHON_ARCH: "32" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python36-x64" + PYTHON_VERSION: "3.6.x" + PYTHON_ARCH: "64" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python27" + PYTHON_VERSION: "2.7.x" + PYTHON_ARCH: "32" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python27-x64" + PYTHON_VERSION: "2.7.x" + PYTHON_ARCH: "64" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python34" + PYTHON_VERSION: "3.4.x" + PYTHON_ARCH: "32" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python34-x64" + PYTHON_VERSION: "3.4.x" + PYTHON_ARCH: "64" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python37" + PYTHON_VERSION: "3.7.x" + PYTHON_ARCH: "32" + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + PYTHON: "C:\\Python37-x64" + PYTHON_VERSION: "3.7.x" + PYTHON_ARCH: "64" + +deploy: + - provider: Environment + name: production + on: + APPVEYOR_REPO_TAG: true + +install: + # If there is a newer build queued for the same PR, cancel this one. + # The AppVeyor 'rollout builds' option is supposed to serve the same + # purpose but it is problematic because it tends to cancel builds pushed + # directly to master instead of just PR builds (or the converse). + # credits: JuliaLang developers. + - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` + https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` + Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` + throw "There are newer queued builds for this pull request, failing early." } + - ECHO "Filesystem root:" + - ps: "ls \"C:/\"" + + #~ - ECHO "Installed SDKs:" + #~ - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" + + - ECHO "Installed prgrams:" + - ps: "ls \"C:/Program Files/\"" + - ps: "ls \"C:/Program Files (x86)/\"" + - ps: "ls \"C:/Program Files (x86)/MSBuild/\"" + - ps: "ls \"C:/Program Files (x86)/Windows Kits/\"" + + # Prepend newly installed Python to the PATH of this build (this cannot be + # done from inside the powershell script as it would require to restart + # the parent CMD process). + - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + + # Check that we have the expected version and architecture for Python + - "python --version" + - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" + + # Upgrade to the latest version of pip to avoid it displaying warnings + # about it being out of date. + - "python -m pip install --disable-pip-version-check --user --upgrade pip" + + # Install the build dependencies of the project. If some dependencies contain + # compiled extensions and are not provided as pre-built wheel packages, + # pip will build them from source using the MSVC compiler matching the + # target Python version and architecture + # - "%CMD_IN_ENV% pip install Cython six" + - "python -m pip install wheel" + - "python -m pip install pyserial" + - "python -m pip install Cython six" + - "python -m pip install nose" + - "python -m pip install twine" + + - ps: Write-Host "PYTHON_VERSION $env:PYTHON_VERSION" + + - cmd: IF "%PYTHON_VERSION%" == "2.7.x" ( python -m pip install Louie ) ELSE ( python -m pip install PyDispatcher ) + + - git clone git://github.com/OpenZWave/open-zwave.git C:\projects\python-openzwave\openzwave + +build_script: + # Build the compiled extension + # "python pyozw_win.py" + - "python setup.py install --flavor=dev" + +test_script: + # Run the project tests + - "pyozw_check" + - "nosetests --verbose tests/lib/autobuild tests/api/autobuild" + +after_test: + # If tests are successful, create binary packages for the project. + - python setup.py bdist_wheel --flavor=dev + #~ - "python setup.py bdist_wininst" + #~ - "%CMD_IN_ENV% python setup.py bdist_msi" + - ps: "ls dist" + +artifacts: + # Archive the generated packages in the ci.appveyor.com build report. + - path: dist/* + name: windowswheels + +deploy_script: + # upload to pypi for Windows + - cmd: IF "%APPVEYOR_REPO_TAG%" == "true" (echo "Uploading wheels") + - cmd: IF "%APPVEYOR_REPO_TAG%" == "true" (set HOME=%USERPROFILE%) + - cmd: IF "%APPVEYOR_REPO_TAG%" == "true" (twine upload dist/*.whl --repository-url https://upload.pypi.org/legacy/ -u %PYPI_USER% -p %PYPI_PASSWORD%) + - cmd: IF "%APPVEYOR_REPO_TAG%" == "true" (echo "Finished Artifact Deployment" ) diff --git a/archives/open-zwave-master-0.4.0.35.zip b/archives/open-zwave-master-0.4.0.35.zip new file mode 100644 index 00000000..f56a9ca4 Binary files /dev/null and b/archives/open-zwave-master-0.4.0.35.zip differ diff --git a/archives/open-zwave-master-0.4.1.zip b/archives/open-zwave-master-0.4.1.zip new file mode 100644 index 00000000..676c2903 Binary files /dev/null and b/archives/open-zwave-master-0.4.1.zip differ diff --git a/archives/open-zwave-master-0.4.10.zip b/archives/open-zwave-master-0.4.10.zip new file mode 100644 index 00000000..9b9898ad Binary files /dev/null and b/archives/open-zwave-master-0.4.10.zip differ diff --git a/archives/open-zwave-master-0.4.11.zip b/archives/open-zwave-master-0.4.11.zip new file mode 100644 index 00000000..2247bde9 Binary files /dev/null and b/archives/open-zwave-master-0.4.11.zip differ diff --git a/archives/open-zwave-master-0.4.14.zip b/archives/open-zwave-master-0.4.14.zip new file mode 100644 index 00000000..b84d0d8b Binary files /dev/null and b/archives/open-zwave-master-0.4.14.zip differ diff --git a/archives/open-zwave-master-0.4.15.zip b/archives/open-zwave-master-0.4.15.zip new file mode 100644 index 00000000..12e55244 Binary files /dev/null and b/archives/open-zwave-master-0.4.15.zip differ diff --git a/archives/open-zwave-master-0.4.16.zip b/archives/open-zwave-master-0.4.16.zip new file mode 100644 index 00000000..670b7f68 Binary files /dev/null and b/archives/open-zwave-master-0.4.16.zip differ diff --git a/archives/open-zwave-master-0.4.17.zip b/archives/open-zwave-master-0.4.17.zip new file mode 100644 index 00000000..ffa36699 Binary files /dev/null and b/archives/open-zwave-master-0.4.17.zip differ diff --git a/archives/open-zwave-master-0.4.18.zip b/archives/open-zwave-master-0.4.18.zip new file mode 100644 index 00000000..9897a92f Binary files /dev/null and b/archives/open-zwave-master-0.4.18.zip differ diff --git a/archives/open-zwave-master-0.4.19.zip b/archives/open-zwave-master-0.4.19.zip new file mode 100644 index 00000000..62b61c1d Binary files /dev/null and b/archives/open-zwave-master-0.4.19.zip differ diff --git a/archives/open-zwave-master-0.4.2.zip b/archives/open-zwave-master-0.4.2.zip new file mode 100644 index 00000000..14c251aa Binary files /dev/null and b/archives/open-zwave-master-0.4.2.zip differ diff --git a/archives/open-zwave-master-0.4.3.zip b/archives/open-zwave-master-0.4.3.zip new file mode 100644 index 00000000..9e3568d8 Binary files /dev/null and b/archives/open-zwave-master-0.4.3.zip differ diff --git a/archives/open-zwave-master-0.4.4.zip b/archives/open-zwave-master-0.4.4.zip new file mode 100644 index 00000000..826ac8e3 Binary files /dev/null and b/archives/open-zwave-master-0.4.4.zip differ diff --git a/archives/open-zwave-master-0.4.5.zip b/archives/open-zwave-master-0.4.5.zip new file mode 100644 index 00000000..c9a94777 Binary files /dev/null and b/archives/open-zwave-master-0.4.5.zip differ diff --git a/archives/open-zwave-master-0.4.6.zip b/archives/open-zwave-master-0.4.6.zip new file mode 100644 index 00000000..c26caf17 Binary files /dev/null and b/archives/open-zwave-master-0.4.6.zip differ diff --git a/archives/open-zwave-master-0.4.7.zip b/archives/open-zwave-master-0.4.7.zip new file mode 100644 index 00000000..10e0a163 Binary files /dev/null and b/archives/open-zwave-master-0.4.7.zip differ diff --git a/archives/open-zwave-master-0.4.8.zip b/archives/open-zwave-master-0.4.8.zip new file mode 100644 index 00000000..f5d3cb1e Binary files /dev/null and b/archives/open-zwave-master-0.4.8.zip differ diff --git a/archives/open-zwave-master-0.4.9.zip b/archives/open-zwave-master-0.4.9.zip new file mode 100644 index 00000000..f8899041 Binary files /dev/null and b/archives/open-zwave-master-0.4.9.zip differ diff --git a/archives/python_openzwave-0.4.0.35.zip b/archives/python_openzwave-0.4.0.35.zip new file mode 100644 index 00000000..1d1cb64b Binary files /dev/null and b/archives/python_openzwave-0.4.0.35.zip differ diff --git a/archives/python_openzwave-0.4.1.zip b/archives/python_openzwave-0.4.1.zip new file mode 100644 index 00000000..a2925d22 Binary files /dev/null and b/archives/python_openzwave-0.4.1.zip differ diff --git a/archives/python_openzwave-0.4.10.zip b/archives/python_openzwave-0.4.10.zip new file mode 100644 index 00000000..7762b7ff Binary files /dev/null and b/archives/python_openzwave-0.4.10.zip differ diff --git a/archives/python_openzwave-0.4.11.zip b/archives/python_openzwave-0.4.11.zip new file mode 100644 index 00000000..9ab4b224 Binary files /dev/null and b/archives/python_openzwave-0.4.11.zip differ diff --git a/archives/python_openzwave-0.4.14.zip b/archives/python_openzwave-0.4.14.zip new file mode 100644 index 00000000..31798f3d Binary files /dev/null and b/archives/python_openzwave-0.4.14.zip differ diff --git a/archives/python_openzwave-0.4.15.zip b/archives/python_openzwave-0.4.15.zip new file mode 100644 index 00000000..d341a2e2 Binary files /dev/null and b/archives/python_openzwave-0.4.15.zip differ diff --git a/archives/python_openzwave-0.4.16.zip b/archives/python_openzwave-0.4.16.zip new file mode 100644 index 00000000..c08369f2 Binary files /dev/null and b/archives/python_openzwave-0.4.16.zip differ diff --git a/archives/python_openzwave-0.4.17.zip b/archives/python_openzwave-0.4.17.zip new file mode 100644 index 00000000..f1008c65 Binary files /dev/null and b/archives/python_openzwave-0.4.17.zip differ diff --git a/archives/python_openzwave-0.4.18.zip b/archives/python_openzwave-0.4.18.zip new file mode 100644 index 00000000..4dafdcfd Binary files /dev/null and b/archives/python_openzwave-0.4.18.zip differ diff --git a/archives/python_openzwave-0.4.19.zip b/archives/python_openzwave-0.4.19.zip new file mode 100644 index 00000000..0c9cafef Binary files /dev/null and b/archives/python_openzwave-0.4.19.zip differ diff --git a/archives/python_openzwave-0.4.2.zip b/archives/python_openzwave-0.4.2.zip new file mode 100644 index 00000000..f79ae946 Binary files /dev/null and b/archives/python_openzwave-0.4.2.zip differ diff --git a/archives/python_openzwave-0.4.3.zip b/archives/python_openzwave-0.4.3.zip new file mode 100644 index 00000000..dc37d2e6 Binary files /dev/null and b/archives/python_openzwave-0.4.3.zip differ diff --git a/archives/python_openzwave-0.4.4.zip b/archives/python_openzwave-0.4.4.zip new file mode 100644 index 00000000..ec98edc5 Binary files /dev/null and b/archives/python_openzwave-0.4.4.zip differ diff --git a/archives/python_openzwave-0.4.5.zip b/archives/python_openzwave-0.4.5.zip new file mode 100644 index 00000000..db6317d6 Binary files /dev/null and b/archives/python_openzwave-0.4.5.zip differ diff --git a/archives/python_openzwave-0.4.6.zip b/archives/python_openzwave-0.4.6.zip new file mode 100644 index 00000000..9c6fa0f8 Binary files /dev/null and b/archives/python_openzwave-0.4.6.zip differ diff --git a/archives/python_openzwave-0.4.7.zip b/archives/python_openzwave-0.4.7.zip new file mode 100644 index 00000000..e0c43de7 Binary files /dev/null and b/archives/python_openzwave-0.4.7.zip differ diff --git a/archives/python_openzwave-0.4.8.zip b/archives/python_openzwave-0.4.8.zip new file mode 100644 index 00000000..26d47a4c Binary files /dev/null and b/archives/python_openzwave-0.4.8.zip differ diff --git a/archives/python_openzwave-0.4.9.zip b/archives/python_openzwave-0.4.9.zip new file mode 100644 index 00000000..51918e6a Binary files /dev/null and b/archives/python_openzwave-0.4.9.zip differ diff --git a/debian/changelog b/debian/changelog index e5599fa5..8744ed4c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -python-openzwave (0.4.0.34) UNRELEASED; urgency=medium +python-openzwave (0.4.19) UNRELEASED; urgency=medium * Try to fix * Automatic release from upstream. Look at CHANGELOG.txt @@ -8,8 +8,28 @@ python-openzwave (0.4.0.34) UNRELEASED; urgency=medium * Automatic release from upstream. Look at CHANGELOG.txt * Automatic release from upstream. Look at CHANGELOG.txt * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt + * Automatic release from upstream. Look at CHANGELOG.txt - -- bibi21000 Mon, 08 May 2017 22:14:07 +0200 + -- bibi21000 Wed, 20 Mar 2019 10:57:44 +0100 python-openzwave (0.3.0b8) UNRELEASED; urgency=medium diff --git a/docs/CHANGELOG.rst b/docs/CHANGELOG.rst index 5077dae9..ec9d1b02 100755 --- a/docs/CHANGELOG.rst +++ b/docs/CHANGELOG.rst @@ -4,6 +4,75 @@ Changelog ========= +python_openzwave 0.4.18.x: + * Fix python 2.7/appveyor + * Add serial port auto-detection + + +python_openzwave 0.4.17.x: + * Add wheels for Windows + + +python_openzwave 0.4.16.x: + * Fix appveyor build for windows + + +python_openzwave 0.4.15.x: + * Update embeded package + + +python_openzwave 0.4.14.x: + * Use Cython 0.28.6 + * Update embeded package + + +python_openzwave 0.4.12.x: + * Improve support Windows + * COMMAND_CLASS_ZWAVE_PLUS_INFO renamed to COMMAND_CLASS_ZWAVEPLUS_INFO + * Update thermostat + * Update embeded package + + +python_openzwave 0.4.11.x: + * Update embeded package + + +python_openzwave 0.4.10.x: + * Improve support Windows in pip + * Improve tests Windows + * Update contructors for scenes and groups + + +python_openzwave 0.4.9.x: + * Improve support Windows in pip + * Update tests + + +python_openzwave 0.4.6.x: + * First try to support Windows in pip + + +python_openzwave 0.4.5.x: + * Fix bug in node statistics and add test. + * Update Makefile to build flavor dev + * Update pyozw_check. + * Update default flavor : check cython is here before choosing shared + * Fix controller.update_ozw_config when directory isn't writable + + +python_openzwave 0.4.4.x: + * Add new options to pyozw_check to list nodes on network. + + +python_openzwave 0.4.3.x: + * Fix bug in default flavor. + + +python_openzwave 0.4.1.x: + * Update the default flavor : try to use a precompiled library. If can't find one, use the embeded package. + * Add method to controller to get new config from github. + + python_openzwave 0.4.0.x: * New installation process via pip @@ -21,7 +90,11 @@ python_openzwave 0.4.0.x: * Add ozwdev and ozwdev_shared flavors : use openzwave dev branch instead of master * Rename to COMMAND_CLASS_MULTI_CHANNEL_V2 to COMMAND_CLASS_MULTI_INSTANCE/CHANNEL * Add tests for c++ library sync - + * Add door locks helpers + * Add helpers for config parameters + * Add data_items to value's dict + + python-openzwave 0.3.3: * Openzwave update diff --git a/docs/DEVEL.rst b/docs/DEVEL.rst index c2c7b753..1e6a79f6 100644 --- a/docs/DEVEL.rst +++ b/docs/DEVEL.rst @@ -4,89 +4,54 @@ Developers information ====================== + How to develop for python-openzwave =================================== -Get the sources - -.. code-block:: bash - - git clone https://github.com/OpenZWave/python-openzwave +Fork the project on Github. -You can install all the dependances to develop for python-openzwave using the command : +Get the sources : .. code-block:: bash - sudo make developper-deps + git clone https://github.com/yourname/python-openzwave -You must now install python-openzwave in develop mode +You can install all the dependances to develop for python-openzwave using the command : .. code-block:: bash - make develop - -Your password will be asked (by sudo) for installing eggs in your local directory. - -Develop, test, debug, test, ... :) - -Update the documentation if needed. You surely found the documentation useful, so please keep it up to date. - -You can create an account on travis or docker to run the tests. + sudo make developer-deps -At last but not least, submit your request. - -How to develop for libopenzwave (was python-openzwave-lib) -========================================================== -After updating the pyx, you need to reinstall it. Otherwise, your changes will not be applied : +You must now install python-openzwave in develop mode. Depending on which python version you prefer, use : .. code-block:: bash - make develop - -Tests -===== - -First, install the dependances : + make venv2-dev +or + .. code-block:: bash - sudo make tests-deps + make venv2-dev -To launch all the tests suite (about 140 tests), use the followind command : +Keep in mind that your updates must be python 2 / python 3 compatible. -.. code-block:: bash - - make tests - -To launch on ly some tests : +Develop, test, debug, test, ... :) -.. code-block:: bash +Update the documentation if needed. You surely found the documentation useful, so please keep it up to date. - nosetests --verbosity=2 tests/api/test_controller_command.py +It a good idea to add automatic tests. -Some tests need manual operations (ie to add a node, to remove one, ...). For example, to test the remove node, use : +Launch the full test suite (for python 2 and python 3) : .. code-block:: bash - export MANUALSKIP='False' && nosetests --verbosity=2 tests/api/test_controller_command.py -m test_150 && unset MANUALSKIP - test_150_command_remove_node_and_wait_for_user (tests.api.test_controller_command.TestControllerCommand) ... ok - - ---------------------------------------------------------------------- - Ran 1 test in 16.031s - - OK + make venv-tests -You should push the inclusion button of the node before the end of the test. +At last but not least, submit your request with the result of tests in the comment. -Some tests don't need a ZWave Stick to be launched, so they can be run on the autobuilders (travis, docker, ...). Place them in the autobuild directory. +If you don't follow the previous steps, your PR will be refused or letting in pending state until I've got time to test it. -Travis-ci, Docker Hub, nosetests and pylint are used to test quality of code. There reports are here : - - - Docker : https://registry.hub.docker.com/u/bibi21000/python-openzwave/ - - Travis : https://travis-ci.org/bibi21000/python-openzwave - - `Nosetests report `_ - - `Coverage report `_ - - `Pylint report `_ Documentation ============= @@ -98,90 +63,6 @@ First, install the dependances : sudo make doc-deps Documentation is managed with sphinx. -Don't utpdate txt files (README, INSTALL, ...), update the RST sources in docs. -Use the following commands to generate all docs files (txt, html and joomla) - -You need to have installed python-openzwave (in either develop or install mode) before generating the documentation. - -.. code-block:: bash - - make docs - -Static vs dynamic (or shared) -============================= -The openzwave (c++) lib needs to run as a singleton : it means that it MUST have only one instance of the manager running on your computer. - -There is 2 ways of linking libraries with a program : - - * static : includes a copy of the library in your binary program. - This means that your program has its own instance of the library. - This the way the install.sh runs. - So you CAN'T have another program (like the control-panel) running when using the python-openzwave library - - * dynamic or shared : includes a link to the library in your binary program. - This means that your program share the library with other programs. - In this case, the instance is owned directly by the library. - This the way the debian package works. So you CAN have another program running when using the python-openzwave library. - Of course, this program MUST use the shared library too. - -About sudo -========== -If you are like me and don't like root (and sudo), you can use the following tip to install packages via pip : - -Look at your python local library, it should looks like : - -.. code-block:: bash - - ls -lisa /usr/local/lib/python2.7/dist-packages/ - total 2428 - 1445174 12 drwxrwsr-x 115 root staff 12288 avril 9 21:35 . - 1445172 4 drwxrwsr-x 4 root staff 4096 mai 2 2014 .. - 1457164 4 drwxr-sr-x 5 root staff 4096 nov. 26 2013 actdiag - 1715480 4 drwxr-sr-x 2 root staff 4096 nov. 26 2013 actdiag-0.5.1.egg-info - 1457163 4 -rw-r--r-- 1 root staff 1004 nov. 26 2013 actdiag_sphinxhelper.py - 1457172 4 -rw-r--r-- 1 root staff 620 nov. 26 2013 actdiag_sphinxhelper.pyc - .... - -So, add your common user to the staff group : - -.. code-block:: bash - - sudo usermod -a -G staff userName - -Add the write right to the group staff - -.. code-block:: bash - - sudo chmod -Rf g+w /usr/local/lib/python2.7/dist-packages/ - -And now, it's time log off and log on. Groups are checked when you open the session. - -You can now install your packages without sudo. - -Python3 and virtualenv -====================== -Python 3 is actually not supported. - -A branch (python3) has been created with a special Dockerfile. It build python-openzwave and launch some tests. -This branch is automatically merged from master at "make commit". - -So please, do not directly push under python3 branch. Make your developments under master or another branch. - -It's important for me have python2/python3 compatibilty in the master branch. -cython can help for this : http://docs.cython.org/src/tutorial/strings.html - -The Makefile sill try to automatically configure your version of python (running python --version). - -If you want to install python-openzwave in a python virtual environnement, you should use something like : - -.. code-block:: bash - - make VIRTUAL_ENV=/path/to/my/venv ... - -If you use python 3 and your python executable is called python3 : - -.. code-block:: bash - make PYTHON_EXEC=python3 ... +Don't update txt and rst files (README, INSTALL, ...) in the root directory, update the RST sources in docs. -You can also put these variables in a CONFIG.make file instead of passing them to the command line diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst new file mode 100755 index 00000000..890e529c --- /dev/null +++ b/docs/INSTALL.rst @@ -0,0 +1,41 @@ +:orphan: + +==================================== +Installing python-openzwave from pip +==================================== + + +Flavors +======= + +Flavor embed +------------ + + +Flavor shared +------------- + + +Flavor git +---------- + + +Flavor ozwdev +------------- + + +Flavor ozwdev +------------- + + +Flavor dev +---------- + + +OS +== + +Windows +------- + + diff --git a/docs/INSTALL_WIN.rst b/docs/INSTALL_WIN.rst index 8c102ef1..6ced83fc 100755 --- a/docs/INSTALL_WIN.rst +++ b/docs/INSTALL_WIN.rst @@ -5,51 +5,183 @@ Installing python-openzwave on Windows ====================================== -This HOW-TO is for 0.4.X. +Install Microsoft tools +======================= -It should be possible to make it pip friendly. Need a command line to build openzwave c++ lib. +This package use MSBuild.exe to build openzwave code. -How To Build python-openzwave on Windows with VS2015 -==================================================== +You can find it in Visual Studio 2017 or Visual Studio 2015. -Assuming Python 3.5 is set in PATH -Assuming your python environment has pip, cython, setuptools +It's also possible to get it as a separate package. +Only release 14.0 and 15.0 of Microsft Build Tools are tested. -Get sources ------------ +You nust use the C++ compiler used to build your version of python : https://wiki.python.org/moin/WindowsCompilers -.. code-block:: bash - git clone https://github.com/openzwave/python-openzwave.git +Install other tools +=================== - cd python-openzwave - git clone git://github.com/OpenZWave/open-zwave.git openzwave +You need git to clone the repository and python (32 bits or 64 bits). Add it to your PATH. + +Install dependencies : + + - for python 2.7 : - cd openzwave - git checkout Dev - cd .. - git checkout + .. code-block:: bash + (venvX) pip install Cython six Louie -Build open-zwave ----------------- + - for python 3 : -Open openzwave/cpp/build/windows/vs2010/OpenZWave.sln in Visual Studio + .. code-block:: bash -When asked, accept the project upgrade to VS2015 + (venvX) pip install Cython six PyDispatcher -Build Win32|Release +clone repositories +================== +Clone python-openzwave: + + +.. code-block:: bash -Build python_openzwave ----------------------- + git clone https://github.com/OpenZWave/python-openzwave.git -From a Command Prompt, install it : +And clone open-zwave inside python-openzwave : .. code-block:: bash - python setup install --dev + cd python-openzwave + git clone https://github.com/OpenZWave/open-zwave.git openzwave + +It's mandatory to clone the previous repository in a directory called openzwave (not open-zwave) + +Visual studio +============= + +Copy vs2010 in a new directory vs2017 (or vs2015 depending of which Visual Studio you use) : + +.. code-block:: bash -Reference for 0.3.X : https://github.com/OpenZWave/python-openzwave/issues/53 + xcopy openzwave\cpp\build\windows\vs2010 openzwave\cpp\build\windows\vs2017 /s /e /h + +Open the project (openzwave\cpp\build\windows\vs2017\OpenZWave.sln) in your Visual Studio. +If you want to build for 64bits, add a new target for it. And finally close it. + +Python-openzwave +================ + +Build and install python-openzwave : + + .. code-block:: bash + + python setup.py install --flavor=dev + + .. code-block:: bash + + sysargv ['setup.py', 'install'] + thon setup.py install --flavor=dev + Requirement already satisfied: Cython in c:\program files (x86)\python36-32\lib\site-packages + {'name': 'libopenzwave', 'sources': ['src-lib/libopenzwave/libopenzwave.pyx'], 'include_dirs': ['openzwave/cpp/src', 'openzwave + /cpp/src/value_classes', 'openzwave/cpp/src/platform', 'openzwave/cpp/build/windows', 'src-lib/libopenzwave', 'openzwave/cpp/bu + ild/windows/vs2017/Release/'], 'define_macros': [('PY_LIB_VERSION', '0.4.4'), ('PY_SSIZE_T_CLEAN', 1), ('PY_LIB_FLAVOR', 'dev') + , ('PY_LIB_BACKEND', 'cython')], 'libraries': ['setupapi', 'msvcrt', 'ws2_32', 'dnsapi'], 'extra_objects': ['openzwave/cpp/buil + d/windows/vs2017/Release//OpenZWave.lib'], 'extra_compile_args': [], 'extra_link_args': [], 'language': 'c++'} + ['six', 'PyDispatcher>=2.0.5', 'Cython'] + Requirement already satisfied: Cython in c:\program files (x86)\python36-32\lib\site-packages + running install + flavor --flavor=dev c:\program files (x86)\python36-32\lib\site-packages + running build_openzwave + Found MSBuild.exe : c:/Program Files (x86)/Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe + Found arch : Win32 wave + Found Visual Studio project : vs2017 (x86)/Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe + Found build path : openzwave/cpp/build/windows/vs2017/Release/ + ... + ... + byte-compiling C:\Program Files (x86)\Python36-32\Lib\site-packages\python_openzwave\scripts\__init__.py to __init__.cpython-36 + .pyc + running install_egg_info + running egg_info + writing python_openzwave.egg-info\PKG-INFO + writing dependency_links to python_openzwave.egg-info\dependency_links.txt + writing entry points to python_openzwave.egg-info\entry_points.txt + ================================================================ + .\scripts\allusers.bat + this script is executed for all users + delete/rename it if you dont need it + ================================================================ + Page de codes active�: 437 + +And finally, test it : + + .. code-block:: bash + + pyozw_check -l -d COM2 -t 30 + + .. code-block:: bash + + ------------------------------------------------------------------------------- + Define options for device COM2 + Start network + Wait for network awake (30s) + ------------------------------------------------------------------------------- + Network is awaked. Talk to controller. + Get python_openzwave version : 0.4.4 + Get python_openzwave config version : Original Z-Wave 2.78 + Get python_openzwave flavor : dev + Get openzwave version : 1.4.2942 + Get config path : C:\Program Files\Python36\lib\site-packages\python_openzwave\ozw_config + Controller capabilities : {'primaryController', 'staticUpdateController'} + Controller node capabilities : {'listening', 'primaryController', 'beaming', 'staticUpdateController'} + Nodes in network : 4 + ------------------------------------------------------------------------------- + Wait for network ready (30s) + ------------------------------------------------------------------------------- + Network is ready. Get nodes + ------------------------------------------------------------ + 1 - Name : ( Location : ) + 1 - Ready : True / Awake : True / Failed : False + 1 - Manufacturer : Aeotec ( id : 0x0086 ) + 1 - Product : DSA02203 Z-Stick S2 ( id : 0x0001 / type : 0x0002 / Version : 3) + 1 - Command classes : set() + 1 - Capabilities : {'listening', 'primaryController', 'beaming', 'staticUpdateController'} + 1 - Neighbors : {4} / Power level : None + 1 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 2 - Name : ( Location : ) + 2 - Ready : True / Awake : True / Failed : False + 2 - Manufacturer : ( id : 0x0000 ) + 2 - Product : ( id : 0x0000 / type : 0x0000 / Version : 2) + 2 - Command classes : set() + 2 - Capabilities : {'listening', 'routing'} + 2 - Neighbors : {3} / Power level : None + 2 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 3 - Name : ( Location : ) + 3 - Ready : False / Awake : True / Failed : True + 3 - Manufacturer : ( id : 0x0000 ) + 3 - Product : ( id : 0x0000 / type : 0x0000 / Version : 3) + 3 - Command classes : set() + 3 - Capabilities : {'listening', 'routing', 'beaming'} + 3 - Neighbors : set() / Power level : None + 3 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + 4 - Name : ( Location : ) + 4 - Ready : True / Awake : True / Failed : False + 4 - Manufacturer : GreenWave ( id : 0x0099 ) + 4 - Product : PowerNode 6 port ( id : 0x0004 / type : 0x0003 / Version : 4) + 4 - Command classes : {'COMMAND_CLASS_MANUFACTURER_SPECIFIC', 'COMMAND_CLASS_ASSOCIATION', 'COMMAND_CLASS_NO_OPERATION', 'COMM + AND_CLASS_VERSION', 'COMMAND_CLASS_SWITCH_BINARY', 'COMMAND_CLASS_MULTI_INSTANCE/CHANNEL', 'COMMAND_CLASS_CRC_16_ENCAP', 'COMMA + ND_CLASS_PROTECTION', 'COMMAND_CLASS_CONFIGURATION', 'COMMAND_CLASS_BASIC', 'COMMAND_CLASS_METER', 'COMMAND_CLASS_SWITCH_ALL'} + 4 - Capabilities : {'listening', 'routing', 'beaming'} + 4 - Neighbors : {1} / Power level : None + 4 - Is sleeping : False / Can wake-up : False / Battery level : None + ------------------------------------------------------------ + Driver statistics : {'SOFCnt': 49, 'ACKWaiting': 0, 'readAborts': 0, 'badChecksum': 0, 'readCnt': 49, 'writeCnt': 46, 'CANCnt': + 0, 'NAKCnt': 1, 'ACKCnt': 30, 'OOFCnt': 0, 'dropped': 17, 'retries': 0, 'callbacks': 0, 'badroutes': 0, 'noack': 4, 'netbusy': + 0, 'nondelivery': 0, 'routedbusy': 0, 'broadcastReadCnt': 0, 'broadcastWriteCnt': 9} + ------------------------------------------------------------ + Stop network + Exit diff --git a/docs/Makefile b/docs/Makefile index 6a2207bb..8b00b67f 100755 --- a/docs/Makefile +++ b/docs/Makefile @@ -43,7 +43,7 @@ clean: -rm -rf $(BUILDDIR)/* html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -E -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." diff --git a/docs/README.rst b/docs/README.rst index ec7ab72c..c4ae7c44 100755 --- a/docs/README.rst +++ b/docs/README.rst @@ -6,18 +6,18 @@ :target: https://circleci.com/gh/OpenZWave/python-openzwave :alt: Circle status -.. image:: https://img.shields.io/pypi/dm/python_openzwave.svg - :target: https://pypi.python.org/pypi/python_openzwave - :alt: Pypi downloads +.. image:: https://ci.appveyor.com/api/projects/status/2ogl8tx7o3pqphc9?svg=true + :target: https://ci.appveyor.com/project/bibi21000/python-openzwave + :alt: Appveyor status .. image:: https://img.shields.io/pypi/format/python_openzwave.svg :target: https://pypi.python.org/pypi/python_openzwave :alt: Pypi format -.. image:: https://img.shields.io/pypi/status/python_openzwave.svg - :target: https://pypi.python.org/pypi/python_openzwave - :alt: Pypi status - +.. image:: https://img.shields.io/badge/Documentation-ok-brightgreen.svg?style=flat + :target: http://openzwave.github.io/python-openzwave/index.html + :alt: Documentation + ================ python-openzwave ================ @@ -30,79 +30,79 @@ python-openzwave is a python wrapper for the openzwave c++ library : https://git * a full-event webapp example : flask + socket.io + jquery * a suite of tests * many examples + * `Full documentation `_ -python-openzwave 0.4.0 is coming !!! -==================================== +python-openzwave 0.4.x is here !!! +================================== - - 0.4.0.x versions are for testers only. Don't use it in a production environement !!! +- New installation process via pip - - New installation process via pip - - - First, you need some build tools and libs. On ubuntu, you should use : +- First, you need some build tools and libs. On ubuntu, you should use : .. code-block:: bash sudo apt-get install --force-yes -y make libudev-dev g++ libyaml-dev - - Make your virtualenv and activate it : +- Make your virtualenv and activate it : .. code-block:: bash virtualenv --python=python3 venv3 source venv3/bin/activate - - Install the default (embed) flavor : +- Install the default flavor : .. code-block:: bash (venvX) pip install python_openzwave - - The previous command install python_openzwave statitically linked to sources downloaded from https://github.com/OpenZWave/python-openzwave/tree/master/archives. - You can change this using flavors. There is a bug in the package dependencies and flavors on some systems. You may need to install dependencies manualy : +- The previous command try to install python_openzwave with the flavor 'shared'. + If it can't find a precompiled library of openzwave, it will use the flavor 'embed' with sources downloaded from https://github.com/OpenZWave/python-openzwave/tree/master/archives. + You can change this using flavor option. + There is a bug in the package dependencies and flavors on some systems. You may need to install dependencies manualy : - - on python 2.7 : + - on python 2.7 : .. code-block:: bash - (venvX) pip install cython wheel six + (venvX) pip install cython wheel six pyserial (venvX) pip install 'Louie>=1.1' - - on python 3 : + - on python 3 : .. code-block:: bash - (venvX) pip install cython wheel six + (venvX) pip install cython wheel six pyserial (venvX) pip install 'PyDispatcher>=2.0.5' - - Choose your flavor : +- Choose your flavor : - embed : the default one. Download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives and build them. Python_openzwave is statically build using a cythonized version of libopenzwave. No need to install cython. - shared : if you have install openzwave as module manually, you can link python_openzwave to it. - git : download sources from openzwave github and link statically to it. - - embed_shared (experimental) : download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives, build and install as module on the system. + - embed_shared : download sources from https://github.com/OpenZWave/python-openzwave/tree/master/archives, build and install as module on the system. Python_openzwave use it. Need root access to install openzwave libs. - - git_shared (experimental) : download sources from openzwave github, build and install them as module on the system. + - git_shared : download sources from openzwave github, build and install them as module on the system. Python_openzwave use it. Need root access to install openzwave libs. - ozwdev and ozwdev_shared : use the dev branch of openzwave on github. - - dev : for python_openzwave developpers - + - dev : for python_openzwave developers. Look for openzwave sources in a local folder specified by the LOCAL_OPENZWAVE environment variable (defaults to 'openzwave'). - - Install it : +- Install it : .. code-block:: bash - (venvX) pip install python_openzwave --install-option="--flavor=git" + (venvX) pip install python_openzwave --no-deps --install-option="--flavor=git" - - You can update to the last version of openzwave using the git flavor : - +- You can update to the last version of openzwave using the git flavor : + .. code-block:: bash (venvX) pip uninstall -y python_openzwave - (venvX) pip install python_openzwave --no-cache-dir --install-option="--flavor=git" + (venvX) pip install python_openzwave --no-cache-dir --no-deps --install-option="--flavor=git" - - At last, you can launch pyozw_check: +- At last, you can launch pyozw_check to test your installation : If no usb stick is connected to the machine, launch : @@ -163,11 +163,55 @@ python-openzwave 0.4.0 is coming !!! Try to destroy manager Try to destroy options + You can list the nodes on your network using : + + .. code-block:: bash + + (venvX) pyozw_check -l -d /dev/ttyUSB0 -t 60 + + .. code-block:: bash + + ------------------------------------------------------------------------------- + Define options for device /dev/ttyUSB0 + Start network + Wait for network (30s) + Network is ready + ------------------------------------------------------------------------------- + Controller capabilities : {'primaryController', 'staticUpdateController'} + Controller node capabilities : {'listening', 'primaryController', 'staticUpdateController', 'beaming'} + Nodes in network : 4 + Driver statistics : {'noack': 6, 'routedbusy': 0, 'readCnt': 115, 'ACKWaiting': 0, 'badChecksum': 0, 'broadcastReadCnt': 0, 'NAKCnt': 0, 'broadcastWriteCnt': 9, 'dropped': 0, 'CANCnt': 0, 'callbacks': 0, 'OOFCnt': 0, 'readAborts': 0, 'badroutes': 0, 'SOFCnt': 115, 'netbusy': 0, 'writeCnt': 49, 'nondelivery': 0, 'ACKCnt': 49, 'retries': 0} + ------------------------------------------------------------ + 1 - Name : ( Location : ) + 1 - Ready : True / Awake : True / Failed : False + 1 - Manufacturer : Aeotec ( id : 0x0086 ) + 1 - Product : DSA02203 Z-Stick S2 ( id : 0x0001 / type : 0x0002 ) + 1 - Version : 3 / Secured : False / Zwave+ : False + 1 - Command classes : {'COMMAND_CLASS_NO_OPERATION', 'COMMAND_CLASS_BASIC'} + 1 - Capabilities : {'staticUpdateController', 'listening', 'primaryController', 'beaming'} + 1 - Neigbors : {4} / Power level : None + 1 - Is sleeping : False / Can wake-up : False / Battery level : None + + ... + + ------------------------------------------------------------ + 4 - Name : ( Location : ) + 4 - Ready : True / Awake : True / Failed : False + 4 - Manufacturer : GreenWave ( id : 0x0099 ) + 4 - Product : PowerNode 6 port ( id : 0x0004 / type : 0x0003 ) + 4 - Version : 4 / Secured : False / Zwave+ : False + 4 - Command classes : {'COMMAND_CLASS_BASIC', 'COMMAND_CLASS_CONFIGURATION', 'COMMAND_CLASS_SWITCH_BINARY', 'COMMAND_CLASS_VERSION', 'COMMAND_CLASS_CRC_16_ENCAP', 'COMMAND_CLASS_MANUFACTURER_SPECIFIC', 'COMMAND_CLASS_ASSOCIATION', 'COMMAND_CLASS_MULTI_INSTANCE/CHANNEL', 'COMMAND_CLASS_METER', 'COMMAND_CLASS_PROTECTION', 'COMMAND_CLASS_NO_OPERATION', 'COMMAND_CLASS_SWITCH_ALL'} + 4 - Capabilities : {'listening', 'routing', 'beaming'} + 4 - Neigbors : {1} / Power level : None + 4 - Is sleeping : False / Can wake-up : False / Battery level : None + + ... + - The old manager is now available via the pyozw_shell command. You need to install module "urwid>=1.1.1" with pip before using it. - libopenzwave and openzwave python modules are packaged in the python_openzwave. - So developpers needs to update their install_requires (it works fine with pyozw_manager). + So developers needs to update their install_requires (it works fine with pyozw_manager). They can use the following code to update softly : .. code-block:: python @@ -196,15 +240,6 @@ python-openzwave 0.4.0 is coming !!! - Please report your successful installations here : https://github.com/OpenZWave/python-openzwave/issues/73 -python-openzwave 0.3.0 is out !!! -================================= - -Look at CHANGELOG to see new features and release notes. - -Look at INSTALL_REPO to test it now. - -Look at INSTALL_ARCH to install from archive : no need to install cython anymore. - Support ======= You can ask for support on the google group : http://groups.google.com/d/forum/python-openzwave-discuss. @@ -215,87 +250,3 @@ Pull requests ============= Please read DEVEL documentation before submitting pull request. A lot of project tasks are done automatically or with makefile, so they must be done in a certain place or in a special order. - -Migrating from python-openzwave 0.2.X to 0.3.0 -============================================== -I need to update source tree of python-openzwave and modules's names because of a bug in setuptools -: https://bitbucket.org/pypa/setuptools/issue/230/develop-mode-does-not-respect-src . -Sorry for that. - -Update your sources: - -.. code-block:: bash - - git pull - -Before building python-openzwave 0.3.0, you must uninstall the old version : - -.. code-block:: bash - - sudo make uninstall - -About cython : I've made many tests using cython installed via pip : (0.20, 0.21 and 0.22). -Compilation is ok but a segfault appears when launching the tests. Please remove it. - -.. code-block:: bash - - sudo pip uninstall Cython - -You also need to make some minor updates in you code, look at CHANGELOG - -If you have problems, please submit an issue with : - - - cython -V - - the content of the directory /usr/local/lib/python2.7/dist-packages/ (for python2.7) - - the content of /usr/local/lib/python2.7/dist-packages/easy-install.pth (for python 2.7) - - -Ubuntu 64bits ... and the others -================================ - -If you're using Ubuntu 64 bits (and mayde others) and keep your distribution up to date, -you certainly have the segfault problem. - -Ubuntu 12.04 and 14.04 seems to be affected by this bug. Ubuntu 15.10 and Debian Jessie not. - -It appears with the last update of python : - -.. code-block:: bash - - $ python - Python 2.7.6 (default, Jun 22 2015, 17:58:13) - [GCC 4.8.2] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - - -I've open a discussion on cython-users here : https://groups.google.com/forum/#!topic/cython-users/mRsviGuCFOk - -The only way I found to avoid this is to rebuild and reinstall the old release of python : - -.. code-block:: bash - - wget https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6-8.dsc https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6.orig.tar.gz https://launchpad.net/ubuntu/+archive/primary/+files/python2.7_2.7.6-8.diff.gz - - dpkg-source -x python2.7_2.7.6-8.dsc - - sudo apt-get build-dep python2.7 - - cd python2.7-2.7.6 - - dpkg-buildpackage - -Wait, wait and await again :) - -.. code-block:: bash - - cd .. - - sudo dpkg -i *.deb - -To prevent future updates of python, you could mark its packages. For example, if you use apt to update your distribution, use the following command : - -.. code-block:: bash - - sudo apt-mark hold idle-python2.7 libpython2.7-minimal python2.7-dbg python2.7-minimal libpython2.7 libpython2.7-stdlib python2.7-dev libpython2.7-dbg libpython2.7-testsuite python2.7-doc libpython2.7-dev python2.7 python2.7-examples - -Some users have reported that building python-openzwave using the archive (INSTALL_ARCH) can also do the trick. Let me know if it works for you. diff --git a/docs/_index_txt.rst b/docs/_index_txt.rst index 4ebd7801..c0e88762 100755 --- a/docs/_index_txt.rst +++ b/docs/_index_txt.rst @@ -5,7 +5,6 @@ * :doc:`Install from archive ` * :doc:`Install for MacOs ` * :doc:`Install for Windows ` -* :doc:`Manual installation ` * :doc:`Change log ` * :doc:`Examples ` * :doc:`Developpers notes ` diff --git a/docs/command.rst b/docs/command.rst index 0a0d4e9c..ecef5297 100755 --- a/docs/command.rst +++ b/docs/command.rst @@ -7,5 +7,5 @@ The commands to use with nodes. :maxdepth: 2 .. automodule:: openzwave.command - :members: ZWaveNodeBasic, ZWaveNodeSwitch, ZWaveNodeSensor + :members: ZWaveNodeBasic, ZWaveNodeSwitch, ZWaveNodeSensor, ZWaveNodeDoorLock diff --git a/docs/conf.py b/docs/conf.py index d1358e3e..5748fb51 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -257,3 +257,5 @@ # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' + +suppress_warnings = ['image.nonlocal_uri'] diff --git a/docs/data.rst b/docs/data.rst index 3787f3a9..fcf7357e 100755 --- a/docs/data.rst +++ b/docs/data.rst @@ -12,4 +12,8 @@ The common data structures and defitions. .. autodata:: PyValueTypes .. autodata:: PyLogLevels .. autodata:: PyControllerCommand +.. autodata:: PyControllerError .. autodata:: PyControllerState +.. autodata:: PyOptionList +.. autodata:: PyStatDriver +.. autodata:: PyStatNode diff --git a/docs/diagrams.rst b/docs/diagrams.rst index d3809f65..e470c482 100755 --- a/docs/diagrams.rst +++ b/docs/diagrams.rst @@ -8,7 +8,7 @@ Full startup process ==================== .. blockdiag:: - :maxwidth: 600 + :width: 600 blockdiag StartupProcess { orientation = portrait; diff --git a/docs/index.rst b/docs/index.rst index 6d61c312..6cc2f303 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,12 @@ Contents: .. toctree:: :maxdepth: 3 - The new "pyx". It provides a low level to the ZWave network. - And its data's definitions - The new API. Map a ZWave Network in objects. + The Readme. + Installation notes. + The low level library ("pyx") to the ZWave network. + The API. Map a ZWave Network in python objects. + How to submit a PR. + Changelog. Indices and tables diff --git a/docs/libopenzwave.rst b/docs/libopenzwave.rst index 7da30fbe..0dc35df6 100755 --- a/docs/libopenzwave.rst +++ b/docs/libopenzwave.rst @@ -5,3 +5,15 @@ libopenzwave module :members: :undoc-members: :show-inheritance: + +.. automodule:: libopenzwave +.. autodata:: PyNotifications +.. autodata:: PyGenres +.. autodata:: PyValueTypes +.. autodata:: PyLogLevels +.. autodata:: PyControllerCommand +.. autodata:: PyControllerError +.. autodata:: PyControllerState +.. autodata:: PyOptionList +.. autodata:: PyStatDriver +.. autodata:: PyStatNode diff --git a/docs/object.rst b/docs/object.rst index 93e1e972..541d6ec9 100755 --- a/docs/object.rst +++ b/docs/object.rst @@ -8,4 +8,4 @@ The low level object. Implements cache mechanism. .. automodule:: openzwave.object :members: ZWaveObject, ZWaveNodeInterface, ZWaveException, ZWaveTypeException, - ZWaveCacheException, ZWaveCommandClassException, NullLoggingHandler + ZWaveCacheException, ZWaveCommandClassException diff --git a/docs/pyozwman.rst b/docs/pyozwman.rst index 46b05035..bcb044cb 100644 --- a/docs/pyozwman.rst +++ b/docs/pyozwman.rst @@ -35,6 +35,6 @@ command cd. All available commands are displayed on every screens. You can use the tab keys to switch between the view panel and the edit panel and the up and down ones to view all informations. -For the developpers : this a good example on how to use the api. +For the developers : this provides a good example on how to use the api. Update are sent to uwird widget using louie notifications. ZWave data updates are done in the set, add, delete, remove, ... methods. diff --git a/examples/api_demo.py b/examples/api_demo.py index 18dbc557..8365589a 100755 --- a/examples/api_demo.py +++ b/examples/api_demo.py @@ -208,9 +208,9 @@ print(" label/help : {}/{}".format (network.nodes[node].values[val].label,network.nodes[node].values[val].help)) print(" id on the network : {}".format (network.nodes[node].values[val].id_on_network)) print(" level: {}".format (network.nodes[node].get_dimmer_level(val))) -print "------------------------------------------------------------" -print "Retrieve RGB Bulbs on the network" -print "------------------------------------------------------------" +print("------------------------------------------------------------") +print("Retrieve RGB Bulbs on the network") +print("------------------------------------------------------------") values = {} for node in network.nodes: for val in network.nodes[node].get_rgbbulbs() : @@ -218,9 +218,9 @@ print(" label/help : {}/{}".format(network.nodes[node].values[val].label,network.nodes[node].values[val].help)) print(" id on the network : {}".format(network.nodes[node].values[val].id_on_network)) print(" level: {}".format(network.nodes[node].get_dimmer_level(val))) -print "------------------------------------------------------------" -print "Retrieve sensors on the network" -print "------------------------------------------------------------" +print("------------------------------------------------------------") +print("Retrieve sensors on the network") +print("------------------------------------------------------------") values = {} for node in network.nodes: for val in network.nodes[node].get_sensors() : @@ -228,9 +228,9 @@ print(" label/help : {}/{}".format(network.nodes[node].values[val].label,network.nodes[node].values[val].help)) print(" id on the network : {}".format(network.nodes[node].values[val].id_on_network)) print(" value: {} {}".format(network.nodes[node].get_sensor_value(val), network.nodes[node].values[val].units)) -print "------------------------------------------------------------" -print "Retrieve thermostats on the network" -print "------------------------------------------------------------" +print("------------------------------------------------------------") +print("Retrieve thermostats on the network") +print("------------------------------------------------------------") values = {} for node in network.nodes: for val in network.nodes[node].get_thermostats() : diff --git a/examples/api_sniff.py b/examples/api_sniff.py index d8bb22af..53ce3e4f 100755 --- a/examples/api_sniff.py +++ b/examples/api_sniff.py @@ -41,7 +41,11 @@ from openzwave.network import ZWaveNetwork from openzwave.option import ZWaveOption import time -from louie import dispatcher, All +import six +if six.PY3: + from pydispatch import dispatcher +else: + from louie import dispatcher device="/dev/ttyUSB0" log="Debug" diff --git a/examples/hello_world.py b/examples/hello_world.py index 9886a67b..ef0a8402 100755 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -41,7 +41,11 @@ from openzwave.network import ZWaveNetwork from openzwave.option import ZWaveOption import time -from louie import dispatcher, All +import six +if six.PY3: + from pydispatch import dispatcher +else: + from louie import dispatcher device="/dev/ttyUSB0" log="None" diff --git a/examples/test_lib.py b/examples/test_lib.py index 20f05d48..2ce9b68b 100755 --- a/examples/test_lib.py +++ b/examples/test_lib.py @@ -65,12 +65,12 @@ def callback(args): if 'valueId' in args: v = args['valueId'] print('valueID: {}'.format(v['id'])) - if v.has_key('groupIndex') and v['groupIndex'] != 0xff: print('GroupIndex: {}'.format(v['groupIndex'])) - if v.has_key('event') and v['event'] != 0xff: print('Event: {}'.format(v['event'])) - if v.has_key('value'): print('Value: {}'.format(str(v['value']))) - if v.has_key('label'): print('Label: {}'.format(v['label'])) - if v.has_key('units'): print('Units: {}'.format(v['units'])) - if v.has_key('readOnly'): print('ReadOnly: {}'.format(v['readOnly'])) + if 'groupIndex' in v and v['groupIndex'] != 0xff: print('GroupIndex: {}'.format(v['groupIndex'])) + if 'event' in v and v['event'] != 0xff: print('Event: {}'.format(v['event'])) + if 'value' in v: print('Value: {}'.format(str(v['value']))) + if 'label' in v: print('Label: {}'.format(v['label'])) + if 'units' in v: print('Units: {}'.format(v['units'])) + if 'readOnly' in v: print('ReadOnly: {}'.format(v['readOnly'])) print('-------------------------------------------------\n') print("Add watcher") diff --git a/github_deploy_key.enc b/github_deploy_key.enc new file mode 100644 index 00000000..f3dad52f --- /dev/null +++ b/github_deploy_key.enc @@ -0,0 +1 @@ +gAAAAABZQtLzloi-Lo8ejSQiUuAlw605x7C5pGJ270Ak-6uMgS4m02uf3nmTLRRgZiKfEevzZaV_r5pBp4CLvxUKjX0ne0iMngvTUyRg8C_7-vVhSkWlTXxzhvorO7Bh24Txy1nLEVfu5suTqQeI0DmAX2i-QylT1GAeo_81Mz-AFe64Wul51Q4iG2g8HFVeqEI7O_mjwvMC5je3Ip0oDMtNSw1zdTqa1SzfzEPQOJOJkY88ssuiRlGhWK1rHtGqKuzHJltjFYkFbeIQnGRvlh3hDumgXhW_6YGlJfGbVLw5dGfx8QO4myLCd72veNc0oeGbbxGDdfz7hpTSITjcolXvDpg2-30kBvV4xCiaFECBn2F8-V6Tm4vJDqchUsw-JT27pIvukNuOu6Zrt2z_Bx_NSDrsE27AgIysqVedFeFJjG7Uv1IzQ6t8qxbikPx1AlS9BodD3cKdB9vvDYZirspL7tus0TCUfews-UYxXB5DTsSSkJyFCy4fw52ATmWN8x-KHVFqVo9ONAF-WyUKZ0KHBg_eYU02oSnO7ceSoR80dgnbSbH6RiZ-8cNdQleFBKK313PJvhpXA3SylDrzPjO63EnJPK7gMbT83QcollBm8oRV-4l4Qxjk-IrnEhSRwJdaNcMPppTp5pA-KC17yX6E-pXYDFcyxNOSUyul8Sh8C5_JXpGq-au8PB1XRitD-Rg1y0bcoy6ZaZpEfxIICJy0K4fLF-ly9u1vFV-p484Ea7QUstnKlnicdS--YqvZJ_sofbYDtx4tjS2oMz58NVUZtAwNmUhGhBk-aAtXau6FZbJvXiPUx4f07_JJTpIDbZWaQv9Bt4oVXpjm-HHKdaW7d1ju6X93xnQqPZORYhBVTgwd-CNgMC3zYoMHHBgU4fLzr-qtnZ_Ie0TpFagnDcusJw7Syk3BQ9ikuPee85-t6lzyd4XbM1L7ryXzYe-DYBt4slHfEVPukJ8-aX8_DJI56yoN56FF19tOJn8nU5XKdg7oovmMSn8mHZtDdOF-jIlIBobG0C8-3S-pcTL_YjmKEY2GpQaKfYn7y16w2eW93tq6Dpuj9xhuG10Q8u0gZjaKhMIyu1inIUzB-26aRp_DJ2qOCyXrcd0IWmRQBEh4V_UJxzrApvgmL2mcNv-ueR5kK3xpzkhxvf5nwlHqC_0F0OZJwCVkklG4Hzdivq4U57oKHyBWYMeXJ64mBUHJbzfqHDE5hJnnxRy2UaK9_aGgCbPSzqBpNjwp8E16uva2nuIgxUNL4qpsxOLMfZAJKnEh_RIEk76kihbZmdBGjHSbjnFE1tuLKQLpN3EH69O5YgUyUene5DLh6v7984uB8I3YZLUweBbAXBBXw1fa8ddgiU3m2KZMCyMRE2GA5xl7DgpwReEkz6jamWVXuV2767InJ-eIcPaSr4YHSdXW6cO8D_uEl0KM5JTFVA1lkx7z7tez9EQuSVEGLYBNqfjvE6SUbY255U67P5dbijhSIPpnnuEQWzX-klx_sAEuHAicmioTxXC_vpKoLQNhNNbHUVNkyxSG0nCGxANfJyzdwsiS6cZgI94MmRqxa7RhmOvXRyDl1tHvyA1uBBX7-g6tVaosLwuAaq-z_CPWxEvE1k7eXsnN7bXAyyj_M1vTv0jAN1fu7Pho-ArgaOvpiw47346oPbYQn_tedkCpWguIbiDTD2iiamDiPWpLOExNQhk9xNo7ESDn85mZuNJMdfSjxMXlStRudn0JbYH6QcmmztzfapRrhvvHF4eI9Ox2TaSKZoPDB34eIAydOPbHTIlvHmM1mF_h9WH0hUHmjbWiH2_qYwPnq4phqF8Dot1l3QxloW-lSY08vpkMMYYgy4sxDR4BxUPtB0UtnuDNuAuXPtPOmG5aLaPNz47tOo7lDZwp24jnLLa0bzrhmNYrNiv0oQZRBurWWzSDk5uOijpYTLjCcu1qO_KnIj0rSfr5hi22nhNVSOarLDpR5Fhy6aaKD_p3xRQ2tl3KL8dgOjHI-0L338kHxGVM1wyWPFTxTUXAOoJGPToBR0o7RkHp_FcfdBDN6JNj35XRo-C_92yM3HZR1grW7P8zFRsnMUBGqpthmCYeXC60RXB00xCGxMOTtQm_q7wEFZ7bdBV2VVVnRaLJcLOCXZ4l9qz2MdJVSprlQlkYd9No5W5NCyBukkqfCzpR94u0CU1VjC_8JhI5uS747_uRUNFNxr1T_qvAMcEGv7UHFmSaqledMDi_dScf1xKpt3vegss8PXem2H1BQ0txWAGC0g247X7DQ7JmcXOXnxELgOl17T53YjVXguVdbMxMSIZcb40QrBL401ieJWZ_BlIQAn3PqmUViSX-EfL5cxMkW2QjWCezfAX1M-Qcb8p4e6E_mnowoxLKiQNNsDqrMTHwal7cXuvop5sx28zo5-Gxn-OQF-Dmmvr1ABGlwJknNJyZkj2bKTJ7RUx7jJuhma1olnl0Jf9Axx4ZZQoFFKhfM18mslDxGgT_KUlH65x-miRoo4dhwIfHXxo4mjgTukz1YChVByyx2jHIo-FIeu5JSM10Kb15heoaH50tHSSM7ueZjZ_8RORFellZBqnW08Q5ZdijhTxLEX5HOVxV3KJvdMelxd_gAI1Txq7UPIiapNPB7QNA6gXMD7fgkGa4j33965FhW5yXw0QurdSVBUtwtwt7vi2hmcBdh8qiL0Sr0ydK4I5qQKtEuojKZG1JmwvbkIL5HKdRXiuby-KYLoHsxjzadhwpkRE3inktqjaQlShE4TEgkEEeKFBgm7Wro0rqeLd2HYbu2O3dkL_i6OyCpTCD4QemtuKUbdRnFK5GzDDys8a2iW2X6iRKpPOaCiT37iokWXrff2RG7gEE1AIScjXoCIHraxaFhGrR1Z7Nfe-b80pSP902aeER5RDKxR6scvh0UnV58mIL5H-aZPbWIHFyIT6CkjaUOc7OBKjeK-KNI7eVOnUZY9fHce472ie9j_zJwbndNMkdlqsBATO3gkvR9fbOxIiFz_MsB15ut8YzfjGy5XWJLUofAldNEwd-4wrodkB0ZDh88nBgUH60zem1gJVdvE5j5KWCfpHRd0orwEoL3ouyGKfEXhQk-2F6hcwRFoFLNhKzEFJITIW5YsAfrZmhNFI9hHjzyccvYLHbTzKAj4CDyKZOnndIssz2DpghenFQtsnbunVygGhLQv6cOwDVBs00MKjaIE7EcswlZ_WzZu3nd2G8dsw22AJMZGsvOt_cFOzkoWTudWDfr3F7q9-K7A1ei3YPzfoxXZJAlSTi8SJnVjCD60SeG6B_EKW-EZP5nGA2zYHFdNiJT9NwpwV-oj6W2lUos9_I899HAnUKK2Gxs7RQRxv7evEK1eQWwlQ_uJ2KaditwLO0H-TlNgEZZvsqrKcvz72gXQqhIeqS0F4HFM0Q1ogO1UZWG41LtWEahZRjLxoazgkRTcGPB5B5x545dFDXDJ9SYI8gFjK8CLzIS9iYMqJpXN7fMQlOuWzN_eikU-j3ppTMMtY5Txxdkmo7Y6CArZTKxW1A1I-CRGyo27iL3eVqSpRUj8oMfVkXGw72i5meZGOH_lWsIK3bs077ovhndEtJsQ1dXa7UKXpLm_7vX_BgEi9URSFAQG40ypCtxTAsyDrmdfktwod0Sbd_WN1IXmnpqVAZWT0awGXV3h5X7_0-3wDSHZAbCUSOZWPKBZPOddGPS0wZk0lOUBPXr_ptkea2cqBVem9YmLN64Ueu59YOlYpLs1670Lb8dvIe07exNAi6oFl_XE9vAG0ziUmRhWgKtovNByqMFEvpCJSctT6lVlEdkxCKG35sXYvVCQkAMN3BZnG9fsJq8t-INeu2W7mRvSPN_intV7hscAajcrlFm688_-ScBIz53j9DaYDhvl9yqapDVu4N7ORiZVpdxJyP56XNFs3k4lPI7UKykzT8yMxUSZzQmahl861bWXiIoVuUng4UgkGuY0X3tIQl4zOM33wluik4Xzt1qxkp3DuhFZVuiUhTmHvaG18-72L6VZ0h7jfUUZ1phtcEtLjBHbEkUN8kItJoYrs7iVCTpX0POjQib80E5tCCdBi-8rWIuUyrs81-0hfpENiz6vujiuVtmVWvnnzExhbrE-bgFmOqj8wT4Ks5g9NVhb9Q0KAzeG01cMHxNl-zyTC-uVeqD0A_IbszpJHlV0pjKNVS1bqCJr_BsvLqy1NNo-7qYH8Yl4QI81pIyeStYFn_XjpB-XnG6jS4ET0lmzA2kAuUxs39BAJof8-y9aMhMlXH379wQwuTHrAJyorPQXswSNA9XAFgIWqt9dlBZKf4kJs-JKvkI8yWoDTiQV_bu_bP3tSEBxukpcO2hl09GHHnEIQqMYQV_ID_qmpYrf5qRZnhBt8QcEcujBIBzfP2Xfauq0tg4bYYgofrF3Y= \ No newline at end of file diff --git a/github_deploy_key_openzwave_python_openzwave.enc b/github_deploy_key_openzwave_python_openzwave.enc new file mode 100644 index 00000000..7084b6cb --- /dev/null +++ b/github_deploy_key_openzwave_python_openzwave.enc @@ -0,0 +1 @@ +gAAAAABaaPgox9_NS0MxF8CneeTVNKqVTLD4L9qfTWWYyzBzMjv5RMLlK6yaarYcvLo4tCPFM9o1i9QBatG5nWNzeyosiBCvft8wmYmua1rWLuAP2bGic3QgviCw75wvA677DDHfZ5w--spPJNfdUcmWlh0bONeBKi4kHFdTXKZ0snjciqAehF1vyc3YcnBIQEhZ0GZSxavbFeXhfgtf5ysw79-KIY295KbBmF1UpieDCE-LJiLxjIc027Qymw2gL-JSoRfCtFZRl9PD6E2MmEk2YWYuZhkxYMpTMmTouK8E70QKQXpfUX7M8yyidR_DXjyrNsReOC4gJtZhFkIMZZ7ic2WJ93SjSI7kCetHF-gE1sB-c89WVOH19htCldHj2_MeeXR0aF4dyC5-P2eHapMY0AHZo-A-z2AIeO9zmmiqFhu-PNQfkoq8bpfvGQgRRT20mDHbRxuwAQMYuoSyBaF35w7pEzPjJv3rmJO_3x4SLZoCZ6UBq-03TyMrpAF5hhycct79EjJGBhGXGAQiQNW2yeW1mpx9J4AsyJJ6INjfMvqYMdY8tQxsEO117HdwLh-R3qMlwl1B10_tmMDs5dwIphMkRgdEwHGFlE6hkBN5nDx3eH-AH5VaYxBaro8Z_wu6FzFFhMbSfJDq1x8b7uJRhk1K0DI1lqRKrcfAVrdW3r7WGodmUdi8TNk2_pYcPRAi-adYiN6QHUQTguJ0FWl3kvm3WOfR1-WPqfGSu6DCHGADTxMQFrl94vnCqEGtc7GLg27cuq72JMvcZqcu9bK39cu64d1UExzLd1slfjKya5dCCGt1t0PPxx4KtqRqzndgDSrF0csCViBZA4CUytDtUdQF79wi3pJckJoaNRCKzykg_Hmvg52POPtclRum3e70-yToxRsZRAEjMyVXs3jrYVGJvl7PtYydhvwVUq9BK5lQcXyyHnztgABLnIb7eYt5APIRAUC554Kx1hnsyUkSH1VgvFs7-I1ZiOSVq7-Vh1OksyfEkPnwKv86Z4rTAXQkw9JlKDh2VC0piVia_iwRwOBLat6KkVDRvcrEuSHtLaBnYj14hIY9rEZQks5cavDS3XoEVZhvcQag7FQDbCGMBVs1y0rw-IY8a3gyR1fegtHH6CuucS8FoWy1VPdTrniIfmYSpRJQFPMqt-wfrTXeYXa6jBxuspV8rh9w_a-hMMbr87KENqSsa18pPey9GmBHCUaIwmWcHKqtbzULtgeOQBo1aKcii6BLG91qE9ysexrXUcDUpl55PF_UfY_Nweyu_jwozjYV8_XO-RIjruDonni1OjO8-HdnlTdj-VBN13OqWPs7BWeNWJ11lxAlLn8L-ZaqAqO1fY-f_xJ0SCLLyK2_2Osvn51ZckngpZ_nyrQU5t0k39xhXiN5_lKXeU8KNsvZ5JO6t7iG6JctVwu-v7AZgKFw5UFfTj3QLj509fjzBUBHl0PVh8HgBtMScWCBAB7V_KDwFgY4JRFvQ1PTrk8Rm5QnlYKVKhrZAbrKwrB58stKk3azZgkWxbquYkv2ffZtCoVmmQUaXbIFgQ7JKSlF2DINoIztAu5M2e99YTQC-6j2eOkiEDqdk4lI5CTESnjSYtmVracoRhjnnLfskgSt04ec8Q4hymqKGFC1QYCgXYcU1H1umrYuchz9HwoHDIe51YVAf86rI1-grm8Z2baQUIoVA1n_1Jj6ENYEMpHPk6OjFu10tgSpSpTAgTUXpmsFspyPJzlD_ThqyebLOKr_iv3jJ8vkSOto1-fxAH9lNd9VM-HpQutxXcxilA6Kf5i3bMHktD_9h-dbg6akazaSe3uwIL5c7_OnKDsKOIbWRYpQ5hNKwquS02gOQCYiPuYokHL-XJMZHAkYUMDjAvgYy4awieSVQmaNo7HfZLJWfwWuE7cdz1lqkpDNnjkQ72cUbRq34bekvgrjEvDslqxmqjBAL2IBfacbpMxVm4pGTmjP3ZGvhIAizY-I_F_J5TlEJolpdmApRV-wfjCk7eZpOqFfUrOT9BRR22FYiXY1rMrFKxlvwCmBYbKtVNPaLaOjQJoRTtyc5iJc3kv0XcI_5fiAGciG87nFXd3IA9hO04N5jV5XKaMlVSCJ1jJdlre4wQuESiDtzaIY7-bAgrRocllIshZezf0aw9qQa-iXVsK7Ili8d-ewr9TL6CK2g5qjwMv5BvCvhYaV-kON7Jvk1buYg8GHuNSRJuzbHvEETihYASB2dPOGvSwtKw1imDnfbUYxYyC8fBNlbg4ttlDRYnlSNVYqn8LNqKaeuvrpP7xpEuTMB4KcloDJ8UuaUYM9ty_6evZBrL9FwSb5qj0p0mZ12O_NHgHvDqNX35DMC4GNqvV5iOhlOChCq92QRd2QhkwrgGpctPADOU1Wo8c8T44PkKxymeyjhJEXrbmlL5SdS2wV3HOu_TyjPXIEEdAv6Czex6VHbDR6fPOJAyiCdCwrraeElWqKMOYOLW-xlI9zS1TJUJXKez7QsEkoCJMk0htzpu_dF_pFk5u4RmTeXHH-KlVTDvxuQlnnT-lbRLz0XtukKtjGPyZHJbdCfbVgULRI-Z204NN91LRZ4E4MGjofTbLWIKU4CrxoQAcQeUh1xIGt2ZH4CoF3xsm46GuS65Wf5NPoqWGFZ8y_8vEMxuSJG6iaskiuQRnW_ikkHAws0RLcJh_gpdF0uShaSoO7zJXcdkYF75IDVaHJeIGIh7SDhVAE6rDnEpVLETd-5wm_zaLO-nJ1b6-qe0k_V4tQG24VdErF6IumXqUuDqwjT3Jy4-pR0Bd9_hd2wyOGZN6oo5tF3xz1IvY5i6GM1PH2P0qMnephzri7b9yJYFM5Y6PzjSY9sZC44rt6GlAHQ4nfzqLhCXR8dr6UYPPF1KKhpDL-WdUu6VxjEMUWVxxsNvcjJRC0ggTpu9uRtBqdRt_PRV0sKoSj3NLICg7ludePdpdw5w-Sx-rSm0c0xjROSlA-0mLHN2i4ZbOolyU1JpUqH2Zz22I10aofeBapxAiXfzLzle_M1ZmeWt8tqm4pEx0DjGVjtMNKhgLRaEgDcAgm6FNUA-W4KCysnLcC-J3l8xyhrZvDXW0KT7oUtwcJi1ZHXOJE6ZAVjMRjkFJJlkhCflTDjU0V1-Uue6yw-Moo9KHbq5uDGMKtzrj_zkpLIBIilZ_kTPSfZrfB5m2jR9Q1Pn07KRoXWKnSkqr9u8hHZ-kfpc_yi6Y7YI4ghENv15zDXRHO2WYKIpOe_biEbJ4djHariIBokXAEF8_lbFiMM_d0kTqYdXxGrJktwakh0hs2uO8PcXCMgNu0Oi23xPSqUPQjpLkNL_1VRkaMbQGVLW9EyBJfMLs7TFfmxcrJXqo5rEJ5gsx4O5B4syi9pM3HFxwPz2p5tsSrK6Cy5n-OYD-E4fpbE1a1xP5UZXRtpOFrL7OT48xQ9xTrsUq2sCR-e_JsGePWGJJrkTzDrpINSvYw8U94dGf23YvAJn03y2EmGU5NXNvsc9ize3a6uoKyA3swNP2FHvPuG16XjlHmySixLQPWQwtUn75q9sfN9XBgPzqwDY-KJrZXABp9iPuHHHxhttaNHXf15GY9rGbAMaTQ7SGDjSykXO-sUrFDmLsO1AsuvEHN1plV0kYYNY3DVP0uZ5vc3_P35RvdkRWfYV_oG6TnAHKgTVu18gdtD6Db7QhBP2LqxbYR9PQQ1U5vWFAbBLf1sst5O_Y5gIkmw4jd6lR_QXcBPvEWzdEc2Z3uLIVrgQxwAXfwOMWVTlkwV3bvP9pH_mGSdmWhDZQeXx06HaJaHMHYKM9oT_peXbSP1xPBxSu_qL7CBZYEOr72bAaU5xFmylENOKlfCxD7cx35zArbFJrHcG4AabBh3HSQE8xjpgzNVTAskWSiesknI5jYtzsvjTu0wEfSGikYHe_R_aKuSTiJotN6MExOhuOJt1CvCUWmVIKtfvyDFmW0MCRslIxdEtrSJfvQBMD0bsk1f6M9GiAdF3xoX2jeDCwp2Rn9gefUWwG-01nc6QbEUYC-frNp2w4x-2NFmiBirVLr9_Dbcg4TxWmArnjg85YfkIk_Iy8HtO-Lv0QJm4hcdyait6_AikTZlOIVkwwkedA42q7s5CisbY_53p9pmc2yeas6RwgPAgYX_8b1ipy8zbnjf28BCytEazeeGPqcFJR37dAkjQrbA-YK_PZV62xY6UlpVii9T4Bpd70jcnnJ4_TieSqPJNzypopJBKS2OlaN-vHLZ2i8iZ7OpA0ZjBJtRT8jyplsLi7GRIA9CJgBWnP_54udPGg4RFkwCNk5GodBVVKmaGqpHKp7_Q-0pIMVCASkktGx6g0NWP59SFJNUHejM9QgwhLlaB3CC8y1p2_57wAFhl07lTQdfhbFKz3053_obzBu8wJiCoQBI3sZXcs= \ No newline at end of file diff --git a/pyozw_progressbar.py b/pyozw_progressbar.py new file mode 100644 index 00000000..7ea4d0ce --- /dev/null +++ b/pyozw_progressbar.py @@ -0,0 +1,159 @@ +import sys +import os +import time +import datetime +import io +import threading + +try: + PY3 = not unicode +except NameError: + PY3 = True + +TEMPLATE = ( + '\r' + '{prefix} ' + '{percent}% ' + '{count} ' + 'Elapsed: 0{elapsed} ' + 'Remaining: {remaining} ' + '{file_name}' +) + + +def remap(value, old_min=0, old_max=0, new_min=0, new_max=0): + old_range = old_max - old_min + new_range = new_max - new_min + + return ( + int((((value - old_min) * new_range) / old_range)) + new_min + ) + + +print_lock = threading.Lock() + + +class ProgressBar(object): + + def __init__(self): + self.stdout = sys.stdout + sys.stdout = self + self.files = [] + self.count = 0 + self.start = None + self.prefix = '' + self.last_line_len = 0 + self.file_position = 0 + + def flush(self): + pass + + def isatty(self): + return True + + def close(self): + if self.start is not None: + print_lock.acquire() + if self.files: + self.update(50, 100, file_name=self.files[-1]) + else: + self.update(50, 100, file_name='') + + self.stdout.write('\n\n') + self.stdout.flush() + print_lock.release() + + sys.stdout = self.stdout + + def write(self, line): + if PY3: + try: + line = line.decode("utf-8") + except AttributeError: + pass + + if str('Build openzwave') in line: + print_lock.acquire() + self.stdout.write('\n') + self.stdout.flush() + + # try: + # self.file_position = self.stdout.tell() + # except (io.UnsupportedOperation, WindowsError): + # pass + + self.prefix = 'Build OpenZWave' + self.start = time.time() + self.update(0, 0, file_name='') + print_lock.release() + + elif self.start is not None: + if str('/errorReport:queue') in line: + print_lock.acquire() + files = line.split('/errorReport:queue ')[1] + self.files = [ + os.path.split(f)[1] for f in files.split(' ') + ] + self.count = len(self.files) + print_lock.release() + + elif line.strip() in self.files: + print_lock.acquire() + self.files.remove(line.strip()) + count = remap( + self.count - len(self.files), + old_max=self.count, + new_max=50 + ) + percent = remap( + self.count - len(self.files), + old_max=self.count, + new_max=100 + ) + + self.update(count, percent, line.strip()) + if not self.files: + self.update(50, 100, file_name='') + print_lock.release() + + def update(self, count, percent, file_name): + current = time.time() + elapsed = current - self.start + + percent = str(percent) + percent = ' ' * (3 - len(percent)) + percent + + if count: + time_per_file = elapsed / (self.count - len(self.files)) + remaining = time_per_file * len(self.files) + remaining = '0' + str(datetime.timedelta(seconds=int(remaining))) + else: + remaining = '99:99:99' + + line = TEMPLATE.format( + prefix=self.prefix, + percent=percent, + count='#' * count + ' ' * (50 - count), + elapsed=str(datetime.timedelta(seconds=int(elapsed))), + remaining=remaining, + file_name=file_name + ) + + # try: + # self.stdout.seek(self.file_position) + # self.stdout.truncate() + # except (io.UnsupportedOperation, WindowsError): + # pass + + if self.last_line_len: + self.stdout.write('\r' + ' ' * self.last_line_len) + + self.stdout.write(line) + self.stdout.flush() + self.last_line_len = len(line) + + def __getattr__(self, item): + if item in self.__dict__: + return self.__dict__[item] + + return getattr(self.stdout, item) diff --git a/pyozw_setup.py b/pyozw_setup.py old mode 100755 new mode 100644 index 704f5a4b..b201840f --- a/pyozw_setup.py +++ b/pyozw_setup.py @@ -21,8 +21,8 @@ along with python-openzwave. If not, see http://www.gnu.org/licenses. Build process : -- ask user what to do (zmq way in pip) -- or parametrizes it +- ask user what to do (zmq way in pip) +- or parametrizes it --dev : use local sources and cythonize way (for python-openzwave devs, ...) --embed : use local sources and cpp file (for third parties packagers, ...) --git : download openzwave from git (for geeks) @@ -48,175 +48,175 @@ try: from wheel.bdist_wheel import bdist_wheel as _bdist_wheel except ImportError: - log.warn("ImportError in : from wheel.bdist_wheel import bdist_wheel as _bdist_wheel") + log.warn("ImportError in : from wheel.bdist_wheel import bdist_wheel as _bdist_wheel") from platform import system as platform_system import glob from pyozw_version import pyozw_version -LOCAL_OPENZWAVE = 'openzwave' +try: + PY3 = not unicode +except NameError: + PY3 = True + +LOCAL_OPENZWAVE = os.getenv('LOCAL_OPENZWAVE', 'openzwave') SETUP_DIR = os.path.dirname(os.path.abspath(__file__)) -def get_default_exts (): - exts = { "name": "libopenzwave", - "sources": [ ], - "include_dirs": [ ], - "define_macros": [ ( 'PY_LIB_VERSION', pyozw_version ) ], - "libraries": [ ], - "extra_objects": [ ], - "extra_compile_args": [ ], - "extra_link_args": [ ], - "language": "c++", - } - return exts - -def cython_context(): - try: - from Cython.Distutils import build_ext - except ImportError: - return None - exts = get_default_exts() - exts['define_macros'] += [('PY_SSIZE_T_CLEAN',1)] - exts['sources'] = ["src-lib/libopenzwave/libopenzwave.pyx"] - return exts - -def cpp_context(): - try: - from distutils.command.build_ext import build_ext - except ImportError: - return None - exts = get_default_exts() - exts['define_macros'] += [('PY_SSIZE_T_CLEAN',1)] - exts['sources'] = ["openzwave-embed/open-zwave-master/python-openzwave/src-lib/libopenzwave/libopenzwave.cpp"] - exts["include_dirs"] += [ "src-lib/libopenzwave/" ] - return exts - -def pybind_context(): - exts = get_default_exts() - exts["sources"] = [ "src-lib/libopenzwave/LibZWaveException.cpp", - "src-lib/libopenzwave/Driver.cpp", - "src-lib/libopenzwave/Group.cpp", - "src-lib/libopenzwave/Log.cpp", - "src-lib/libopenzwave/Options.cpp", - "src-lib/libopenzwave/Manager.cpp", - "src-lib/libopenzwave/Notification.cpp", - "src-lib/libopenzwave/Node.cpp", - "src-lib/libopenzwave/Values.cpp", - "src-lib/libopenzwave/libopenzwave.cpp" - ] - exts["include_dirs"] = [ "pybind11/include" ] - exts['extra_compile_args'] += [ "-fvisibility=hidden" ] - return exts - -def system_context(ctx, openzwave=None, static=False): - #System specific section - #~ os.environ["CC"] = "gcc" - #~ os.environ["CXX"] = "g++" - #~ os.environ["PKG_CONFIG_PATH"] = "PKG_CONFIG_PATH:/usr/local/lib/x86_64-linux-gnu/pkgconfig/" - log.info("Found platform {0}".format(sys.platform)) - if static: - ctx['include_dirs'] += [ - "{0}/cpp/src".format(openzwave), - "{0}/cpp/src/value_classes".format(openzwave), - "{0}/cpp/src/platform".format(openzwave) ] - if sys.platform.startswith("win"): - ctx['libraries'] += [ "setupapi", "msvcrt", "ws2_32", "dnsapi" ] +class Template(object): - if static: - ctx['extra_objects'] = [ "{0}/cpp/build/windows/vs2010/Release/openzwave.lib".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/windows".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] + def __init__(self, openzwave=None, cleanozw=False, sysargv=None, flavor="embed", backend="cython"): + self.openzwave = openzwave + self._ctx = None + self.cleanozw = cleanozw + self.flavor = flavor + self.backend = backend + self.sysargv = sysargv + """Specifics options for os ie windows + """ + self.os_options = dict() + + def get_default_exts (self): + exts = { "name": "libopenzwave", + "sources": [ ], + "include_dirs": [ ], + "define_macros": [ ( 'PY_LIB_VERSION', pyozw_version ) ], + "libraries": [ ], + "extra_objects": [ ], + "extra_compile_args": [ ], + "extra_link_args": [ ], + "language": "c++", + } + return exts + + def cython_context(self): + try: + from Cython.Distutils import build_ext + except ImportError: + return None + exts = self.get_default_exts() + exts['define_macros'] += [('PY_SSIZE_T_CLEAN',1)] + exts['sources'] = ["src-lib/libopenzwave/libopenzwave.pyx"] + return exts - elif sys.platform.startswith("cygwin"): + def cpp_context(self): + try: + from distutils.command.build_ext import build_ext + except ImportError: + return None + exts = self.get_default_exts() + exts['define_macros'] += [('PY_SSIZE_T_CLEAN',1)] + exts['sources'] = ["openzwave-embed/open-zwave-master/python-openzwave/src-lib/libopenzwave/libopenzwave.cpp"] + exts["include_dirs"] += [ "src-lib/libopenzwave/" ] + return exts + + def pybind_context(self): + exts = self.get_default_exts() + exts["sources"] = [ "src-lib/libopenzwave/LibZWaveException.cpp", + "src-lib/libopenzwave/Driver.cpp", + "src-lib/libopenzwave/Group.cpp", + "src-lib/libopenzwave/Log.cpp", + "src-lib/libopenzwave/Options.cpp", + "src-lib/libopenzwave/Manager.cpp", + "src-lib/libopenzwave/Notification.cpp", + "src-lib/libopenzwave/Node.cpp", + "src-lib/libopenzwave/Values.cpp", + "src-lib/libopenzwave/libopenzwave.cpp" + ] + exts["include_dirs"] = [ "pybind11/include" ] + exts['extra_compile_args'] += [ "-fvisibility=hidden" ] + return exts + + def system_context(self, ctx, static=False): + #System specific section + #~ os.environ["CC"] = "gcc" + #~ os.environ["CXX"] = "g++" + #~ os.environ["PKG_CONFIG_PATH"] = "PKG_CONFIG_PATH:/usr/local/lib/x86_64-linux-gnu/pkgconfig/" + log.info("Found platform {0}".format(sys.platform)) if static: - ctx['libraries'] += [ "udev", "stdc++",'resolv' ] - ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] + ctx['include_dirs'] += [ + "{0}/cpp/src".format(self.openzwave), + "{0}/cpp/src/value_classes".format(self.openzwave), + "{0}/cpp/src/platform".format(self.openzwave) ] - elif sys.platform.startswith("darwin") : - ctx['extra_link_args'] += [ "-framework", "CoreFoundation", "-framework", "IOKit" ] - ctx['extra_compile_args'] += [ "-stdlib=libc++", "-mmacosx-version-min=10.7" ] + if sys.platform.startswith("win"): + from pyozw_win import get_system_context + get_system_context(ctx, self.os_options, openzwave=os.path.abspath(self.openzwave), static=static) - if static: - ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/mac".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] - - elif sys.platform.startswith("freebsd"): - if static: - ctx['libraries'] += [ "usb", "stdc++" ] - ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] - - elif sys.platform.startswith("sunos"): - if static: - ctx['libraries'] += [ "udev", "stdc++",'resolv' ] - ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] + elif sys.platform.startswith("cygwin"): + if static: + ctx['libraries'] += [ "udev", "stdc++",'resolv' ] + ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(self.openzwave) ] + ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(self.openzwave) ] + else: + import pyozw_pkgconfig + ctx['libraries'] += [ "openzwave" ] + extra = pyozw_pkgconfig.cflags('libopenzwave') + if extra != '': + for ssubstitute in ['', 'value_classes', 'platform']: + ctx['extra_compile_args'] += [ os.path.normpath(os.path.join(extra, ssubstitute)) ] + + elif sys.platform.startswith("darwin") : + ctx['extra_link_args'] += [ "-framework", "CoreFoundation", "-framework", "IOKit" ] + ctx['extra_compile_args'] += [ "-stdlib=libc++", "-mmacosx-version-min=10.7" ] + + if static: + ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(self.openzwave) ] + ctx['include_dirs'] += [ "{0}/cpp/build/mac".format(self.openzwave) ] + else: + import pyozw_pkgconfig + ctx['libraries'] += [ "openzwave" ] + extra = pyozw_pkgconfig.cflags('libopenzwave') + if extra != '': + for ssubstitute in ['', 'value_classes', 'platform']: + ctx['extra_compile_args'] += [ os.path.normpath(os.path.join(extra, ssubstitute)) ] - elif sys.platform.startswith("linux"): - if static: - ctx['libraries'] += [ "udev", "stdc++",'resolv' ] - ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(openzwave) ] - ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(openzwave) ] - else: - import pyozw_pkgconfig - ctx['libraries'] += [ "openzwave" ] - extra = pyozw_pkgconfig.cflags('libopenzwave') - if extra != '': - for ssubstitute in ['/', '/value_classes/', '/platform/']: - ctx['extra_compile_args'] += [ extra.replace('//', ssubstitute) ] + elif sys.platform.startswith("freebsd"): + os.environ["CPPFLAGS"] = "-Wno-unused-private-field" + if static: + ctx['libraries'] += [ "usb", "stdc++" ] + ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(self.openzwave) ] + ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(self.openzwave) ] + else: + import pyozw_pkgconfig + ctx['libraries'] += [ "openzwave" ] + extra = pyozw_pkgconfig.cflags('libopenzwave') + if extra != '': + for ssubstitute in ['', 'value_classes', 'platform']: + ctx['extra_compile_args'] += [ os.path.normpath(os.path.join(extra, ssubstitute)) ] - else: - # Unknown systemm - raise RuntimeError("Can't detect plateform {0}".format(sys.platform)) + elif sys.platform.startswith("sunos"): + if static: + ctx['libraries'] += [ "usb-1.0", "stdc++",'resolv' ] + ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(self.openzwave) ] + ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(self.openzwave) ] + else: + import pyozw_pkgconfig + ctx['libraries'] += [ "openzwave" ] + extra = pyozw_pkgconfig.cflags('libopenzwave') + if extra != '': + for ssubstitute in ['', 'value_classes', 'platform']: + ctx['extra_compile_args'] += [ os.path.normpath(os.path.join(extra, ssubstitute)) ] - return ctx + elif sys.platform.startswith("linux"): + if static: + ctx['libraries'] += [ "udev", "stdc++",'resolv' ] + ctx['extra_objects'] = [ "{0}/libopenzwave.a".format(self.openzwave) ] + ctx['include_dirs'] += [ "{0}/cpp/build/linux".format(self.openzwave) ] + else: + import pyozw_pkgconfig + ctx['libraries'] += [ "openzwave" ] + extra = pyozw_pkgconfig.cflags('libopenzwave') + if extra != '': + for ssubstitute in ['', 'value_classes', 'platform']: + ctx['extra_compile_args'] += [ os.path.normpath(os.path.join(extra, ssubstitute)) ] + + else: + # Unknown systemm + raise RuntimeError("Can't detect plateform {0}".format(sys.platform)) + + return ctx -class Template(object): - - def __init__(self, openzwave=None, cleanozw=False, sysargv=None, flavor="embed", backend="cython"): - self.openzwave = openzwave - self._ctx = None - self.cleanozw = cleanozw - self.flavor = flavor - self.backend = backend - self.sysargv = sysargv - @property def ctx(self): if self._ctx is None: @@ -232,7 +232,7 @@ def build_ext(self): current_template.install_minimal_dependencies() from Cython.Distutils import build_ext as _build_ext return _build_ext - + @property def copy_openzwave_config(self): return True @@ -252,18 +252,23 @@ def finalize_context(self, ctx): else: ctx['define_macros'] += [('PY_LIB_BACKEND', "cython")] return ctx - + def install_requires(self): - return ['Cython'] - + if sys.platform.startswith("win"): + return ['Cython'] + else: + return ['Cython==0.28.6'] + def build_requires(self): - return ['Cython'] - + if sys.platform.startswith("win"): + return ['Cython'] + else: + return ['Cython==0.28.6'] + def build(self): if len(self.ctx['extra_objects']) == 1 and os.path.isfile(self.ctx['extra_objects'][0]): log.info("Use cached build of openzwave") return True - log.info("Build openzwave ... be patient ...") from subprocess import Popen, PIPE from threading import Thread try: @@ -274,9 +279,16 @@ def build(self): io_q = Queue() def stream_watcher(identifier, stream): + # fixes subprocess output lag issue when using python 2.x - for line in stream: - io_q.put((identifier, line)) + if PY3: + dummy_return = b'' + else: + dummy_return = '' + + for line in iter(stream.readline, dummy_return): + if line: + io_q.put((identifier, line)) if not stream.closed: stream.close() @@ -296,23 +308,44 @@ def printer(): if identifier == 'STDERR': sys.stderr.write('{0}\n'.format(line)) log.error('{0}\n'.format(line)) + elif sys.platform.startswith("win"): + progress_bar.write(line) + + if sys.platform.startswith("win"): + progress_bar.close() if sys.platform.startswith("win"): - proc = Popen('make', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + from pyozw_progressbar import ProgressBar + from pyozw_win import get_clean_command, get_build_command + + cwd = os.path.split(self.os_options['solution_path'])[0] + build_command = get_build_command(**self.os_options) + + + log.info("Build openzwave ... be patient ...") + + progress_bar = ProgressBar() + proc = Popen(build_command, stdout=PIPE, stderr=PIPE, cwd=cwd) + elif sys.platform.startswith("cygwin"): + log.info("Build openzwave ... be patient ...") proc = Popen('make', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("darwin"): + log.info("Build openzwave ... be patient ...") proc = Popen('make', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("freebsd"): + log.info("Build openzwave ... be patient ...") proc = Popen('gmake', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("sunos"): - proc = Popen('make', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + log.info("Build openzwave ... be patient ...") + # fixed command issues to Popen + proc = Popen(['make', 'PREFIX=/opt/local'], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) elif sys.platform.startswith("linux"): + log.info("Build openzwave ... be patient ...") proc = Popen('make', stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) else: @@ -329,6 +362,7 @@ def printer(): while tprinter.is_alive(): time.sleep(1) tprinter.join() + return True def install_so(self): @@ -366,19 +400,19 @@ def printer(): sys.stderr.write('{0}\n'.format(line)) log.error('{0}\n'.format(line)) if sys.platform.startswith("win"): - proc = Popen([ 'make', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + proc = Popen([ 'copy', 'OpenZWave.dll' , '%SYSTEM32%\\' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.os_options['vsproject_build'])) + elif sys.platform.startswith("cygwin"): proc = Popen([ 'make', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("darwin"): proc = Popen([ 'make', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("freebsd"): proc = Popen([ 'gmake', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("sunos"): - proc = Popen([ 'make', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + proc = Popen([ 'make', 'PREFIX=/opt/local', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) elif sys.platform.startswith("linux"): proc = Popen([ 'make', 'install' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) @@ -397,45 +431,55 @@ def printer(): while tprinter.is_alive(): time.sleep(1) tprinter.join() - log.info("ldconfig openzwave so ... be patient ...") - try: + + if sys.platform.startswith("win"): + log.info("Register dll ... be patient ...") + proc = Popen([ 'regsvr32', 'OpenZWave.dll' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.os_options['vsproject_build'])) + + elif sys.platform.startswith("cygwin"): import pyozw_pkgconfig ldpath = pyozw_pkgconfig.libs_only_l('libopenzwave')[2:] log.info("ldconfig openzwave in {0} so ... be patient ...".format(ldpath)) - if sys.platform.startswith("win"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - - elif sys.platform.startswith("cygwin"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - - elif sys.platform.startswith("darwin"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - - elif sys.platform.startswith("freebsd"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - - elif sys.platform.startswith("sunos"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - - elif sys.platform.startswith("linux"): - proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - else: - # Unknown systemm - raise RuntimeError("Can't detect plateform {0}".format(sys.platform)) + elif sys.platform.startswith("darwin"): + import pyozw_pkgconfig + ldpath = pyozw_pkgconfig.libs_only_l('libopenzwave')[2:] + log.info("ldconfig openzwave in {0} so ... be patient ...".format(ldpath)) + proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - Thread(target=stream_watcher, name='stdout-watcher', - args=('STDOUT', proc.stdout)).start() - Thread(target=stream_watcher, name='stderr-watcher', - args=('STDERR', proc.stderr)).start() + elif sys.platform.startswith("freebsd"): + import pyozw_pkgconfig + ldpath = pyozw_pkgconfig.libs_only_l('libopenzwave')[2:] + log.info("ldconfig openzwave in {0} so ... be patient ...".format(ldpath)) + proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - tprinter = Thread(target=printer, name='printer') - tprinter.start() - while tprinter.is_alive(): - time.sleep(1) - tprinter.join() - except Exception: - log.info("Can't launch ldconfig") + elif sys.platform.startswith("sunos"): + import pyozw_pkgconfig + ldpath = pyozw_pkgconfig.libs_only_l('libopenzwave')[2:] + log.info("ldconfig openzwave in {0} so ... be patient ...".format(ldpath)) + proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + + elif sys.platform.startswith("linux"): + import pyozw_pkgconfig + ldpath = pyozw_pkgconfig.libs_only_l('libopenzwave')[2:] + log.info("ldconfig openzwave in {0} so ... be patient ...".format(ldpath)) + proc = Popen([ 'ldconfig', ldpath ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + + else: + # Unknown systemm + raise RuntimeError("Can't detect plateform {0}".format(sys.platform)) + + Thread(target=stream_watcher, name='stdout-watcher', + args=('STDOUT', proc.stdout)).start() + Thread(target=stream_watcher, name='stderr-watcher', + args=('STDERR', proc.stderr)).start() + + tprinter = Thread(target=printer, name='printer') + tprinter.start() + while tprinter.is_alive(): + time.sleep(1) + tprinter.join() time.sleep(2.5) log.info("Openzwave so installed and loaded") tprinter = None @@ -444,11 +488,11 @@ def printer(): def clean(self): #Build openzwave try: - if not os.path.isfile(self.openzwave): + if not os.path.isdir(self.openzwave): return True except TypeError: return True - log.info("Clean openzwave ... be patient ...") + log.info("Clean openzwave in %s ... be patient ..." % (self.openzwave) ) from subprocess import Popen, PIPE from threading import Thread try: @@ -481,21 +525,32 @@ def printer(): if identifier == 'STDERR': sys.stderr.write('{0}\n'.format(line)) log.error('{0}\n'.format(line)) - + proc = None if sys.platform.startswith("win"): - proc = Popen([ 'make', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + from pyozw_win import get_clean_command + clean_command = get_clean_command(**self.os_options) + log.info("Clean openzwave project ... be patient ...") + proc = Popen( + clean_command, + stdout=PIPE, + stderr=PIPE, + cwd=os.path.split(self.os_options['solution_path'])[0] + ) + #~ proc.wait() + #~ proc = Popen([ 'regsvr32', '-u', 'OpenZWave.dll' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(os.path.abspath(self.openzwave))) + #~ proc = Popen([ 'del', '/F', '/Q', '/S', '%SYSTEM32%\OpenZWave.dll' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(os.path.abspath(self.openzwave))) + elif sys.platform.startswith("cygwin"): proc = Popen([ 'make', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("darwin"): proc = Popen([ 'make', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("freebsd"): proc = Popen([ 'gmake', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) - + elif sys.platform.startswith("sunos"): - proc = Popen([ 'make', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) + proc = Popen([ 'make', 'PREFIX=/opt/local', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) elif sys.platform.startswith("linux"): proc = Popen([ 'make', 'clean' ], stdout=PIPE, stderr=PIPE, cwd='{0}'.format(self.openzwave)) @@ -504,19 +559,21 @@ def printer(): # Unknown systemm raise RuntimeError("Can't detect plateform {0}".format(sys.platform)) - Thread(target=stream_watcher, name='stdout-watcher', - args=('STDOUT', proc.stdout)).start() - Thread(target=stream_watcher, name='stderr-watcher', - args=('STDERR', proc.stderr)).start() + if proc is not None: + Thread(target=stream_watcher, name='stdout-watcher', + args=('STDOUT', proc.stdout)).start() + Thread(target=stream_watcher, name='stderr-watcher', + args=('STDERR', proc.stderr)).start() - tprinter = Thread(target=printer, name='printer') - tprinter.start() - while tprinter.is_alive(): - time.sleep(1) - tprinter.join() + tprinter = Thread(target=printer, name='printer') + tprinter.start() + while tprinter.is_alive(): + time.sleep(1) + tprinter.join() return True def clean_all(self): + log.info("Clean-all openzwave ... be patient ...") try: from pkg_resources import resource_filename dirn = resource_filename('python_openzwave.ozw_config', '__init__.py') @@ -536,17 +593,26 @@ def clean_all(self): return self.clean() def check_minimal_config(self): - log.info("Found g++ : {0}".format(find_executable("g++"))) - log.info("Found gcc : {0}".format(find_executable("gcc"))) - log.info("Found make : {0}".format(find_executable("make"))) - log.info("Found gmake : {0}".format(find_executable("gmake"))) - exe = find_executable("pkg-config") - log.info("Found pkg-config : {0}".format(exe)) - if exe is not None: - import pyozw_pkgconfig - for lib in self.ctx['libraries'] + ['yaml-0.1', 'libopenzwave', 'python', 'python2', 'python3']: - log.info("Found library {0} : {1}".format(lib, pyozw_pkgconfig.exists(lib))) - + if sys.platform.startswith("win"): + log.info("Found MSBuild.exe : {0}".format(self.os_options['msbuild_path'])) + log.info("Found arch : {0}".format(self.os_options['arch'])) + log.info("Found build configuration : {0}".format(self.os_options['build_type'])) + log.info("Found Visual Studio project : {0}".format(self.os_options['solution_path'])) + log.info("Found build path : {0}".format(self.os_options['build_path'])) + log.info("Found cython : {0}".format(find_executable("cython"))) + else: + log.info("Found g++ : {0}".format(find_executable("g++"))) + log.info("Found gcc : {0}".format(find_executable("gcc"))) + log.info("Found make : {0}".format(find_executable("make"))) + log.info("Found gmake : {0}".format(find_executable("gmake"))) + log.info("Found cython : {0}".format(find_executable("cython"))) + exe = find_executable("pkg-config") + log.info("Found pkg-config : {0}".format(exe)) + if exe is not None: + import pyozw_pkgconfig + for lib in self.ctx['libraries'] + ['yaml-0.1', 'libopenzwave', 'python', 'python2', 'python3']: + log.info("Found library {0} : {1}".format(lib, pyozw_pkgconfig.exists(lib))) + def install_minimal_dependencies(self): if len(self.build_requires()) == 0: return @@ -568,7 +634,7 @@ def install_minimal_dependencies(self): log.info("Minimal dependencies already installed {0}".format(pyreq)) except Exception: log.warn("Can't get package list from pip.") - + def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/master'): #Get openzwave """download an archive to a specific location""" @@ -576,10 +642,10 @@ def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zi dest_file = os.path.join(dest, 'open-zwave.zip') if os.path.exists(self.openzwave): if not self.cleanozw: - log.info("Already have directory %s. Use it. Use --cleanozw to clean it.", self.openzwave) + #~ log.info("Already have directory %s. Use it. Use --cleanozw to clean it.", self.openzwave) return self.openzwave else: - log.info("Already have directory %s but remove and clean it as asked", self.openzwave) + #~ log.info("Already have directory %s but remove and clean it as asked", self.openzwave) self.clean_all() try: os.remove(dest_file) @@ -607,51 +673,59 @@ def clean_openzwave_so(self): for path in ['/usr/local/etc/openzwave', '/usr/local/include/openzwave', '/usr/local/share/doc/openzwave']: try: log.info('Try to remove {0}'.format('/usr/local/etc/openzwave')) - shutil.rmtree(os.path.abspath(self.openzwave)) + shutil.rmtree(self.openzwave) except Exception: pass return True - + def clean_cython(self): try: os.remove('src-lib/libopenzwave/libopenzwave.cpp') except Exception: pass - + class DevTemplate(Template): - + def __init__(self, **args): Template.__init__(self, **args) def get_context(self): opzw_dir = LOCAL_OPENZWAVE if LOCAL_OPENZWAVE is None: - return None + if sys.platform.startswith("win"): + from pyozw_win import get_openzwave + get_openzwave('openzwave') + else: + return None + if not os.path.isdir(opzw_dir): - log.error("Can't find {0}".format(opzw_dir)) - return None + if sys.platform.startswith("win"): + from pyozw_win import get_openzwave + get_openzwave(opzw_dir) + else: + return None self.openzwave = opzw_dir - ctx = cython_context() + ctx = self.cython_context() if ctx is None: log.error("Can't find Cython") return None - ctx = system_context(ctx, openzwave=opzw_dir, static=True) + ctx = self.system_context(ctx, static=True) return ctx def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/master'): return True class GitTemplate(Template): - + def __init__(self, **args): Template.__init__(self, openzwave=os.path.join("openzwave-git", 'open-zwave-master'), **args) def get_context(self): - ctx = cython_context() + ctx = self.cython_context() if ctx is None: log.error("Can't find Cython") return None - ctx = system_context(ctx, openzwave=self.openzwave, static=True) + ctx = self.system_context(ctx, static=True) return ctx def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/master'): @@ -659,31 +733,31 @@ def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zi def clean_all(self): ret = self.clean() - dest,tail = os.path.split(os.path.abspath(self.openzwave)) + dest,tail = os.path.split(self.openzwave) if tail == "openzwave-git": try: log.info('Try to remove {0}'.format(self.openzwave)) - if os.path.isdir(os.path.abspath(self.openzwave)): - shutil.rmtree(os.path.abspath(self.openzwave)) + if os.path.isdir(self.openzwave): + shutil.rmtree(self.openzwave) except Exception: pass elif tail == 'open-zwave-master': try: log.info('Try to remove {0}'.format(dest)) - if os.path.isdir(os.path.abspath(dest)): - shutil.rmtree(os.path.abspath(dest)) + if os.path.isdir(dest): + shutil.rmtree(dest) except Exception: pass return ret class GitSharedTemplate(GitTemplate): - + def get_context(self): - ctx = cython_context() + ctx = self.cython_context() if ctx is None: log.error("Can't find Cython") return None - ctx = system_context(ctx, openzwave=self.openzwave, static=False) + ctx = self.system_context(ctx, static=False) while '' in ctx['extra_compile_args']: ctx['extra_compile_args'].remove('') extra = '-I/usr/local/include/openzwave//' @@ -695,7 +769,7 @@ def get_context(self): @property def copy_openzwave_config(self): - return False + return sys.platform.startswith("win") @property def install_openzwave_so(self): @@ -706,23 +780,22 @@ def clean(self): return GitTemplate.clean(self) class OzwdevTemplate(GitTemplate): - + def __init__(self, **args): Template.__init__(self, openzwave=os.path.join("openzwave-git", 'open-zwave-Dev'), **args) - + def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/Dev'): return Template.get_openzwave(self, url) - class OzwdevSharedTemplate(GitSharedTemplate): - + def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/Dev'): return Template.get_openzwave(self, url) class EmbedTemplate(Template): - - def __init__(self, **args): - Template.__init__(self, openzwave=os.path.join("openzwave-embed", 'open-zwave-master'), **args) + + def __init__(self, backend='cpp', **args): + Template.__init__(self, openzwave=os.path.join("openzwave-embed", 'open-zwave-master'), backend=backend, **args) @property def build_ext(self): @@ -733,8 +806,8 @@ def build_ext(self): return _build_ext def get_context(self): - ctx = cpp_context() - ctx = system_context(ctx, openzwave=self.openzwave, static=True) + ctx = self.cpp_context() + ctx = self.system_context(ctx, static=True) return ctx def install_requires(self): @@ -747,7 +820,7 @@ def get_openzwave(self, url='https://raw.githubusercontent.com/OpenZWave/python- ret = Template.get_openzwave(self, url) shutil.copyfile(os.path.join(self.openzwave,'python-openzwave','openzwave.vers.cpp'), os.path.join(self.openzwave,'cpp','src','vers.cpp')) return ret - + def clean(self): ret = Template.clean(self) try: @@ -759,26 +832,26 @@ def clean(self): def clean_all(self): ret = self.clean() - dest,tail = os.path.split(os.path.abspath(self.openzwave)) + dest,tail = os.path.split(self.openzwave) if tail == "openzwave-embed": try: log.info('Try to remove {0}'.format(self.openzwave)) - shutil.rmtree(os.path.abspath(self.openzwave)) + shutil.rmtree(self.openzwave) except Exception: pass elif tail == 'open-zwave-master': try: log.info('Try to remove {0}'.format(dest)) - shutil.rmtree(os.path.abspath(dest)) + shutil.rmtree(dest) except Exception: pass return ret - + class EmbedSharedTemplate(EmbedTemplate): def get_context(self): - ctx = cpp_context() - ctx = system_context(ctx, openzwave=self.openzwave, static=False) + ctx = self.cpp_context() + ctx = self.system_context(ctx, static=False) while '' in ctx['extra_compile_args']: ctx['extra_compile_args'].remove('') extra = '-I/usr/local/include/openzwave//' @@ -799,17 +872,17 @@ def copy_openzwave_config(self): @property def install_openzwave_so(self): return True - + class SharedTemplate(Template): def __init__(self, **args): Template.__init__(self, **args) def get_context(self): - ctx = cython_context() + ctx = self.cython_context() if ctx is None: log.error("Can't find Cython") return None - ctx = system_context(ctx, static=False) + ctx = self.system_context(ctx, static=False) return ctx def build(self): @@ -817,7 +890,7 @@ def build(self): @property def copy_openzwave_config(self): - return False + return sys.platform.startswith("win") def get_openzwave(self, url='https://codeload.github.com/OpenZWave/open-zwave/zip/master'): return True @@ -828,11 +901,11 @@ def parse_template(sysargv): if '--flavor=dev' in sysargv: index = sysargv.index('--flavor=dev') flavor = sysargv.pop(index) - tmpl = DevTemplate(sysargv=sysargv) + tmpl = DevTemplate(sysargv=sysargv) elif '--flavor=git' in sysargv: index = sysargv.index('--flavor=git') flavor = sysargv.pop(index) - tmpl = GitTemplate(sysargv=sysargv) + tmpl = GitTemplate(sysargv=sysargv) elif '--flavor=git_shared' in sysargv: index = sysargv.index('--flavor=git_shared') flavor = sysargv.pop(index) @@ -840,7 +913,7 @@ def parse_template(sysargv): elif '--flavor=ozwdev' in sysargv: index = sysargv.index('--flavor=ozwdev') flavor = sysargv.pop(index) - tmpl = OzwdevTemplate(sysargv=sysargv) + tmpl = OzwdevTemplate(sysargv=sysargv) elif '--flavor=ozwdev_shared' in sysargv: index = sysargv.index('--flavor=ozwdev_shared') flavor = sysargv.pop(index) @@ -858,20 +931,39 @@ def parse_template(sysargv): flavor = sysargv.pop(index) tmpl = SharedTemplate(sysargv=sysargv) if tmpl is None: - #Default template flavor = 'embed' - tmpl = EmbedTemplate(sysargv=sysargv) + try: + import pyozw_pkgconfig + if pyozw_pkgconfig.exists('libopenzwave'): + try: + from Cython.Distutils import build_ext + flavor = 'shared' + except ImportError: + log.info("Can't find cython") + except: + log.info("Can't find pkg-config") + #Default template + if flavor == 'embed': + log.info("Use embeded package of openzwave") + tmpl = EmbedTemplate(sysargv=sysargv) + elif flavor == 'shared': + log.info("Use precompiled library openzwave") + tmpl = SharedTemplate(sysargv=sysargv) tmpl.flavor = flavor if '--cleanozw' in sysargv: index = sysargv.index('--cleanozw') sysargv.pop(index) tmpl.cleanozw = True + log.info('sysargv', sysargv) + print('sysargv', sysargv) + log.info("Found SETUP_DIR : {0}".format(SETUP_DIR)) + print("Found SETUP_DIR : {0}".format(SETUP_DIR)) return tmpl - + current_template = parse_template(sys.argv) def install_requires(): - pkgs = ['six'] + pkgs = ['six', 'pyserial'] if (sys.version_info > (3, 0)): pkgs.append('PyDispatcher>=2.0.5') else: @@ -879,8 +971,11 @@ def install_requires(): pkgs += current_template.install_requires() return pkgs +def build_requires(): + return current_template.build_requires() + def get_dirs(base): - return [x for x in glob.iglob(os.path.join( base, '*')) if os.path.isdir(x) ] + return [x for x in glob.iglob(os.path.join( base, '*')) if os.path.isdir(x) ] def data_files_config(target, source, pattern): ret = list() @@ -902,21 +997,21 @@ def run(self): build_openzwave.develop = True self.run_command('build_openzwave') _bdist_egg.run(self) - + class build_openzwave(setuptools.Command): - description = 'download an build openzwave' - + description = 'download and build openzwave' + user_options = [ ('openzwave-dir=', None, 'the source directory where openzwave sources should be stored'), ('flavor=', None, 'the flavor of python_openzwave to install'), ] - + def initialize_options(self): self.openzwave_dir = None self.flavor = None - + def finalize_options(self): if self.openzwave_dir is None: if getattr(self, 'develop', False) or not getattr(self, 'install', False): @@ -926,31 +1021,32 @@ def finalize_options(self): build.ensure_finalized() self.openzwave_dir = os.path.join(build.build_lib, current_template.openzwave) self.flavor = current_template.flavor - + def run(self): current_template.check_minimal_config() current_template.get_openzwave() + current_template.clean() current_template.build() if current_template.install_openzwave_so: current_template.install_so() class openzwave_config(setuptools.Command): description = 'Install config files from openzwave' - + user_options = [ ('install-dir=', None, 'the installation directory where openzwave configuration should be stored'), ] - + def initialize_options(self): self.install_dir = None - + def finalize_options(self): if self.install_dir is None: install = self.distribution.get_command_obj('install') install.ensure_finalized() self.install_dir = install.install_lib - + def run(self): if self.install_dir is None: log.warning("Can't install ozw_config to None") @@ -958,11 +1054,19 @@ def run(self): if not current_template.copy_openzwave_config: log.info("Don't install ozw_config for template {0}".format(current_template)) return + log.info("Install ozw_config for template {0}".format(current_template)) dest = os.path.join(self.install_dir, 'python_openzwave', "ozw_config") + if os.path.isdir(dest): + #Try to remove old config + try: + import shutil + shutil.rmtree(dest) + except Exception: + log.exception("Can't remove old config directory") if not os.path.isdir(dest): os.makedirs(dest) self.copy_tree(os.path.join(current_template.openzwave,'config'), dest) - + class build(_build): sub_commands = [('build_openzwave', None)] + _build.sub_commands @@ -984,25 +1088,25 @@ def run(self): current_template.clean_all() else: current_template.clean() - _clean.run(self) + _clean.run(self) class develop(_develop): - description = 'De velop python_openzwave' - + description = 'Develop python_openzwave' + user_options = _develop.user_options + [ ('flavor=', None, 'the flavor of python_openzwave to install'), ] - + def initialize_options(self): self.flavor = None return _develop.initialize_options(self) - + def finalize_options(self): if self.flavor is None: self.flavor = current_template.flavor log.info('flavor {0}'.format(self.flavor)) return _develop.finalize_options(self) - + def run(self): #In case of --uninstall, it will build openzwave to remove it ... stupid. #In develop mode, build is done by the makefile @@ -1013,21 +1117,21 @@ def run(self): class install(_install): description = 'Install python_openzwave' - + user_options = _install.user_options + [ ('flavor=', None, 'the flavor of python_openzwave to install'), ] - + def initialize_options(self): self.flavor = None return _install.initialize_options(self) - + def finalize_options(self): if self.flavor is None: self.flavor = current_template.flavor log.info('flavor {0}'.format(self.flavor)) return _install.finalize_options(self) - + def run(self): build_openzwave = self.distribution.get_command_obj('build_openzwave') build_openzwave.develop = True diff --git a/pyozw_version.py b/pyozw_version.py index 8cb5b710..4b4d3e8b 100644 --- a/pyozw_version.py +++ b/pyozw_version.py @@ -21,7 +21,7 @@ along with python-openzwave. If not, see http://www.gnu.org/licenses. """ -pyozw_version = '0.4.0.34' +pyozw_version = '0.4.19' if "-" in pyozw_version: pyozw_version_short = pyozw_version.split("-") else: diff --git a/pyozw_win.py b/pyozw_win.py new file mode 100644 index 00000000..3f052ace --- /dev/null +++ b/pyozw_win.py @@ -0,0 +1,802 @@ +# -*- coding: utf-8 -*- +""" +This file is part of **python-openzwave** project https://github.com/OpenZWave/python-openzwave. + :platform: Unix, Windows, MacOS X + :sinopsis: openzwave API + +.. moduleauthor: bibi21000 aka Sébastien GALLET + +License : GPL(v3) + +**python-openzwave** is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +**python-openzwave** is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with python-openzwave. If not, see http://www.gnu.org/licenses. + +""" + +import sys +import os +import platform +import shutil +from pyozw_version import pyozw_version + +try: + _winreg = __import__('_winreg') +except ImportError: + _winreg = __import__('winreg') + + +from subprocess import Popen, PIPE + +# this is simply to show that you can build using only VS2017 as a requirement. +VS2017_VCVARSALL = r'"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat"' + +WIN64 = '64' in platform.machine() +PYTHON64 = platform.architecture()[0] == '64bit' and WIN64 +ARCH = 'x64' if PYTHON64 else 'x86' + + +try: + PY3 = not unicode +except NameError: + PY3 = True + +TOOLSETS = { + 15.0: ['v141', '15.0'], # vs2017 + 14.0: ['v140', '14.0'], # vs2015 + 10.0: ['v100', '4.0'], # vs2010 + 4.0: ['v90', '4.0'], # vs2008 +} + + +def setup_build_env_2017(): + proc = Popen( + VS2017_VCVARSALL + ' ' + ARCH + ' && set', + shell=True, + stdout=PIPE, + stderr=PIPE + ) + + test_env = {} + for line in proc.stdout: + if PY3: + line = line.decode("utf-8") + + if '=' in line: + key, value = line.split('=', 1) + test_env[key.strip()] = value.strip() + + for key, value in list(test_env.items()): + if str(os.environ.get(key, None)) != value: + os.environ[key] = value + + os.environ['DISTUTILS_USE_SDK'] = '1' + + +# comment this line to run normally. +setup_build_env_2017() + + +def _get_reg_value(path, key): + d = _read_reg_values(path) + if key in d: + return d[key] + return '' + + +def _read_reg_keys(key): + try: + handle = _winreg.OpenKeyEx( + _winreg.HKEY_LOCAL_MACHINE, + 'SOFTWARE\\Wow6432Node\\Microsoft\\' + key + ) + except _winreg.error: + return [] + res = [] + + for i in range(_winreg.QueryInfoKey(handle)[0]): + res += [_winreg.EnumKey(handle, i)] + + return res + + +def _read_reg_values(key): + try: + handle = _winreg.OpenKeyEx( + _winreg.HKEY_LOCAL_MACHINE, + 'SOFTWARE\\Wow6432Node\\Microsoft\\' + key + ) + except _winreg.error: + return {} + res = {} + for i in range(_winreg.QueryInfoKey(handle)[1]): + name, value, _ = _winreg.EnumValue(handle, i) + res[_convert_mbcs(name)] = _convert_mbcs(value) + + return res + + +def _convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + + +def get_environment(): + from setuptools.msvc import ( + msvc9_query_vcvarsall, + EnvironmentInfo, + msvc14_get_vc_env + ) + + py_version = sys.version_info[:2] + + if py_version >= (3, 5): + env = msvc14_get_vc_env(ARCH) + msbuild_version = 14.0 + env_info = EnvironmentInfo(ARCH) + msbuild_path = _find_file( + 'MSBuild.exe', + env_info.MSBuild[0] + )[0] + + sdks = ('10.0', '8.1', '8.1A', '8.0', '8.0A') + solution_dest = 'vs2015' + + elif (3, 5) > py_version >= (3, 3): + env = msvc9_query_vcvarsall(10.0, ARCH) + msbuild_version = 4.0 + msbuild_path = _get_reg_value( + 'MSBuild\\4.0', + 'MSBuildOverrideTasksPath' + ) + + if msbuild_path: + msbuild_path = _find_file( + 'MSBuild.exe', + msbuild_path + )[0] + + sdks = ('7.1', '7.0A') + solution_dest = 'vs2010' + + elif (3, 3) > py_version >= (2, 6): + env = msvc9_query_vcvarsall(9.0, ARCH) + msbuild_version = 4.0 + msbuild_path = _get_reg_value( + 'MSBuild\\4.0', + 'MSBuildOverrideTasksPath' + ) + + if msbuild_path: + msbuild_path = _find_file( + 'MSBuild.exe', + msbuild_path + )[0] + + sdks = ('6.1', '6.1A', '6.0A') + solution_dest = 'vs2008' + + else: + raise RuntimeError( + 'This library does not support python versions < 2.6' + ) + + for sdk in sdks: + sdk_version = _get_reg_value( + 'Microsoft SDKs\\Windows\\v' + sdk, + 'ProductVersion' + ) + if sdk_version: + sdk_installation_folder = _get_reg_value( + 'Microsoft SDKs\\Windows\\v' + sdk, + 'InstallationFolder' + ) + target_platform = sdk_version + os.environ['WindowsSdkDir'] = sdk_installation_folder + break + else: + raise RuntimeError('Unable to locate suitable SDK %s' % (sdks,)) + + platform_toolset, tools_version = TOOLSETS[msbuild_version] + + return ( + env, + msbuild_version, + msbuild_path, + sdk_installation_folder, + target_platform, + platform_toolset, + tools_version, + solution_dest + ) + + +def _find_file(file_name, path): + res = [] + + for root, dirs, files in os.walk(path): + if ( + ((PYTHON64 and 'amd64' in root) or 'amd64' not in root) and + file_name in files + ): + res.append(os.path.join(root, file_name)) + return res + + +def setup_build_environment(openzwave, build_type): + if 'DISTUTILS_USE_SDK' in os.environ: + target_platform = os.environ['WINDOWSSDKVERSION'].replace('\\', '') + + if 'VS150COMNTOOLS' in os.environ: + msbuild_version = 15.0 + solution_dest = 'vs2017' + + elif 'VS140COMNTOOLS' in os.environ: + msbuild_version = 14.0 + solution_dest = 'vs2015' + else: + raise RuntimeError + + msbuild_path = _find_file('MSBuild.exe', os.environ['VSINSTALLDIR'])[0] + platform_toolset, tools_version = TOOLSETS[msbuild_version] + sdk_installation_folder = os.environ['WINDOWSSDKVERBINPATH'] + os.environ['MSSDK'] = sdk_installation_folder + + else: + ( + env, + msbuild_version, + msbuild_path, + sdk_installation_folder, + target_platform, + platform_toolset, + tools_version, + solution_dest + ) = get_environment() + + if 'WINDOWSSDKVERBINPATH' in env: + sdk_installation_folder = env['WINDOWSSDKVERBINPATH'] + + env['MSSDK'] = sdk_installation_folder + env['DISTUTILS_USE_SDK'] = '1' + + for key, value in env.items(): + os.environ[key] = value + + if 'VS150COMNTOOLS' in os.environ and msbuild_version == 14.0: + platform_toolset = 'v141' + tools_version = '15.0' + msbuild_version = 15.0 + solution_dest = 'vs2017' + + if 'WINDOWSSDKLIBVERSION' in os.environ: + target_platform = ( + os.environ['WINDOWSSDKLIBVERSION'].replace('\\', '') + ) + + if not msbuild_path: + raise RuntimeError( + 'Unable to locate MSBuild to compile OpenZWave' + ) + + project_base_path = os.path.abspath( + os.path.join( + openzwave, + 'cpp', + 'build', + 'windows' + ) + ) + + project_path = os.path.join(project_base_path, solution_dest) + + if PYTHON64: + build_path = os.path.join(project_path, 'x64', build_type) + else: + build_path = os.path.join(project_path, build_type) + + if not os.path.exists(project_path): + shutil.copytree( + os.path.join(project_base_path, 'vs2010'), + project_path + ) + + print('Updating VS solution please wait.') + + if update_vs_project( + os.path.join(project_path, 'OpenZWave.vcxproj'), + tools_version, + platform_toolset, + target_platform + ): + with open(os.path.join(project_path, 'OpenZWave.sln'), 'r') as f: + sln = str(f.read()).replace('\r', '') + + if GLOBAL_SELECTION_TEMPLATE not in sln: + sln = sln.replace( + GLOBAL_SELECTION_KEY, + GLOBAL_SELECTION_TEMPLATE + ) + + with open(os.path.join(project_path, 'OpenZWave.sln'), 'w') as f: + f.write(sln) + + solution_path = os.path.join(project_path, 'OpenZWave.sln') + + return ( + solution_path, + build_path, + msbuild_path, + msbuild_version, + target_platform, + platform_toolset, + tools_version, + sdk_installation_folder + ) + + +def update_vs_project(path, tools_version, platform_toolset, target_platform): + from xml.etree import ElementTree + + vcxproj_xmlns = 'http://schemas.microsoft.com/developer/msbuild/2003' + ElementTree.register_namespace('', vcxproj_xmlns) + + with open(path, 'r') as f: + vcxproj = f.read() + + # the original xml file contains some characters that the xml parser + # does not like, these are non human readable characters and they do not + # need to exist. So we remove them. + for char in (187, 191, 239): + vcxproj = vcxproj.replace(chr(char), '') + + root = ElementTree.fromstring(vcxproj) + + vcxproj_xmlns = '{' + vcxproj_xmlns + '}' + + # there are only 3 things that need to get changed once the solution has + # been fully updated. the tools version, the platform teeolset + # and the windows target platform. if a cached version of openzwave is used + # there is no need to create a whole new solution. so what we do is we set + # an attribute in the root of the xml to inform us if the file has been + # upgraded already. + + root.attrib['ToolsVersion'] = tools_version + + for node in root.findall(vcxproj_xmlns + 'PropertyGroup'): + if ( + 'Label' in node.attrib and + node.attrib['Label'] == 'Configuration' + ): + for sub_node in node: + if ( + sub_node.tag.replace(vcxproj_xmlns, '') == + 'PlatformToolset' + ): + sub_node.text = platform_toolset + break + else: + sub_node = ElementTree.Element('PlatformToolset') + sub_node.text = platform_toolset + node.append(sub_node) + + for node in root.findall(vcxproj_xmlns + 'PropertyGroup'): + if 'Label' in node.attrib and node.attrib['Label'] == 'Globals': + for sub_node in node: + if ( + sub_node.tag.replace(vcxproj_xmlns, '') == + 'WindowsTargetPlatformVersion' + ): + sub_node.text = target_platform + break + else: + sub_node = ElementTree.Element('WindowsTargetPlatformVersion') + sub_node.text = target_platform + node.append(sub_node) + + # this function is the core of upgrading the solution. It burrows down + # into a node through each layer and makes a copy. this copy gets modified + # to become an x64 version. the copy gets returned and then added to the + # xml file + + def iter_node(old_node): + new_node = ElementTree.Element(old_node.tag) + if old_node.text is not None: + new_node.text = old_node.text.replace('Win32', 'x64') + + for key, value in old_node.attrib.items(): + new_node.attrib[key] = value.replace('Win32', 'x64') + for old_sub_node in old_node: + new_node.append(iter_node(old_sub_node)) + return new_node + + # here is the testing to se if the file has been updated before. + if 'PythonOpenZWave' not in root.attrib: + update = True + root.attrib['PythonOpenZWave'] = 'True' + i = 0 + + for node in root[:]: + tag = node.tag.replace(vcxproj_xmlns, '') + + if ( + tag == 'ItemGroup' and + 'Label' in node.attrib and + node.attrib['Label'] == 'ProjectConfigurations' + ): + for sub_item in node[:]: + node.append(iter_node(sub_item)) + + if ( + tag == 'PropertyGroup' and + 'Label' in node.attrib and + node.attrib['Label'] == 'Configuration' + ): + root.insert(i, iter_node(node)) + i += 1 + + if ( + tag == 'ImportGroup' and + 'Label' in node.attrib and + node.attrib['Label'] == 'PropertySheets' + ): + root.insert(i, iter_node(node)) + i += 1 + + if ( + tag == 'PropertyGroup' and + not node.attrib.keys() + ): + j = 0 + for sub_item in node[:]: + if ( + sub_item.tag.replace(vcxproj_xmlns, '') != + '_ProjectFileVersion' + ): + node.insert(j, iter_node(sub_item)) + j += 1 + + if tag == 'ItemDefinitionGroup': + root.insert(i, iter_node(node)) + i += 1 + i += 1 + else: + update = False + + with open(path, 'w')as f: + f.write(xml_tostring(root, vcxproj_xmlns)) + + # we return if the file was updated or not. this is a flag that tells up + # if we need to update the sln file. + return update + + +# this is a custom xml writer. it recursively iterates through an +# ElementTree object creating a formatted string that is as close as i can +# get it to what Visual Studio creates. I did this for consistency as well +# as ease of bug testing + +def xml_tostring(node, xmlns, indent=''): + tag = node.tag.replace(xmlns, '') + no_text = node.text is None or not node.text.strip() + + if indent: + output = '' + else: + output = '\n' + if xmlns: + node.attrib['xmlns'] = xmlns.replace('{', '').replace('}', '') + + if no_text and not list(node) and not node.attrib.keys(): + output += '{0}<{1} />\n'.format(indent, tag) + else: + output += '{0}<{1}'.format(indent, tag) + + for key in sorted(node.attrib.keys()): + output += ' {0}="{1}"'.format(key, str(node.attrib[key])) + + if not list(node) and no_text: + output += ' />\n' + elif not no_text and not list(node): + output += '>{0}\n'.format(node.text, tag) + elif list(node) and no_text: + output += '>\n' + for item in node: + output += xml_tostring(item, xmlns, indent + ' ') + output += '{0}\n'.format(indent, tag) + else: + output += '>\n {0}{1}\n'.format(indent, node.text) + for item in node: + output += xml_tostring(item, xmlns, indent + ' ') + output += '{0}\n'.format(indent, tag) + return output + + +# because we no longer use devenv in favor of msbuild there are only 2 commands +# needed. +# one for clean and the other to build +def get_clean_command(msbuild_path, solution_path, build_type, arch, **_): + clean_template = ( + '"{msbuild_path}" ' + '"{solution_path}" ' + '/property:Configuration={build_type} ' + '/property:Platform={arch} ' + '/t:Clean ' + ) + clean_command = clean_template.format( + msbuild_path=msbuild_path, + solution_path=solution_path, + build_type=build_type, + arch=arch + ) + + return clean_command + + +def get_build_command(msbuild_path, solution_path, build_type, arch, **_): + build_template = ( + '"{msbuild_path}" ' + '"{solution_path}" ' + '/property:Configuration={build_type} ' + '/property:Platform={arch} ' + '/t:Build' + ) + + build_command = build_template.format( + msbuild_path=msbuild_path, + solution_path=solution_path, + build_type=build_type, + arch=arch + ) + + return build_command + + +def get_system_context( + ctx, + options, + openzwave="openzwave", + static=False, + debug=False +): + + + if debug: + print("get_system_context for windows") + + # one feature i added is building a debugging version, this is only going + # to happen if sys.executable ends with _d which identifies that the python + # interpreter is a debugging build. + + if static: + if os.path.splitext(sys.executable)[0].endswith('_d'): + options['build_type'] = 'Debug' + ctx['define_macros'] += [('_DEBUG', 1)] + ctx['libraries'] += ["setupapi", "msvcrtd", "ws2_32", "dnsapi"] + else: + options['build_type'] = 'Release' + ctx['libraries'] += ["setupapi", "msvcrt", "ws2_32", "dnsapi"] + else: + if os.path.splitext(sys.executable)[0].endswith('_d'): + options['build_type'] = 'DebugDLL' + ctx['define_macros'] += [('_DEBUG', 1)] + ctx['libraries'] += ["setupapi", "msvcrtd", "ws2_32", "dnsapi"] + else: + options['build_type'] = 'ReleaseDLL' + ctx['libraries'] += ["setupapi", "msvcrt", "ws2_32", "dnsapi"] + + if PYTHON64: + options['arch'] = "x64" + else: + options['arch'] = 'Win32' + + ( + solution_path, + build_path, + msbuild_path, + msbuild_version, + target_platform, + platform_toolset, + tools_version, + sdk_installation_folder + ) = setup_build_environment(openzwave, options['build_type']) + + options['msbuild_path'] = msbuild_path + options['solution_path'] = solution_path + options['build_path'] = build_path + options['msbuild_version'] = msbuild_version + options['target_platform'] = target_platform + options['platform_toolset'] = platform_toolset + options['tools_version'] = tools_version + options['sdk_installation_folder'] = sdk_installation_folder + + if debug: + print('Platform: %s' % target_platform) + print('Platform architecture %s' % ARCH) + print('Platform toolset: %s' % platform_toolset) + print('MSBuild path: %s' % msbuild_path) + print('MSBuild version: %0.1f' % msbuild_version) + print('MSBuild tools version: %s' % tools_version) + print('SDK installation path: %s' % sdk_installation_folder) + print("Found options %s" % options) + + cpp_path = os.path.join(openzwave, 'cpp') + src_path = os.path.join(cpp_path, 'src') + + if static: + ctx['extra_objects'] = [os.path.join(build_path, 'OpenZWave.lib')] + + ctx['include_dirs'] += [ + src_path, + os.path.join(src_path, 'value_classes'), + os.path.join(src_path, 'platform'), + os.path.join(cpp_path, 'build', 'windows'), + build_path, + ] + else: + ctx['libraries'] += ["OpenZWave"] + + ctx['extra_compile_args'] += [ + src_path, + os.path.join(src_path, 'value_classes'), + os.path.join(src_path, 'platform'), + ] + + ctx['define_macros'] += [ + ('CYTHON_FAST_PYCCALL', 1), + ('_MT', 1), + ('_DLL', 1) + ] + + +GLOBAL_SELECTION_TEMPLATE = ''' Debug|x64 = Debug|x64 + DebugDLL|x64 = DebugDLL|x64 + Release|x64 = Release|x64 + ReleaseDLL|x64 = ReleaseDLL|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|x64.ActiveCfg = Debug|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|x64.Build.0 = Debug|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DebugDLL|x64.ActiveCfg = DebugDLL|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DebugDLL|x64.Build.0 = DebugDLL|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|x64.ActiveCfg = Release|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|x64.Build.0 = Release|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64 + {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64''' + + +GLOBAL_SELECTION_KEY = ''' EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution''' + + +def get_openzwave(opzw_dir): + url = 'https://codeload.github.com/OpenZWave/open-zwave/zip/master' + + from io import BytesIO + try: + from urllib2 import urlopen + except ImportError: + from urllib.request import urlopen + + import zipfile + + base_path = os.path.dirname(__file__) + + print('Downloading openzwave...') + + req = urlopen(url) + dest_file = BytesIO(req.read()) + dest_file.seek(0) + + zip_ref = zipfile.ZipFile(dest_file, 'r') + zip_ref.extractall(base_path) + zip_ref.close() + dest_file.close() + + os.rename( + os.path.join(base_path, zip_ref.namelist()[0]), + opzw_dir + ) + + +if __name__ == '__main__': + from subprocess import Popen, PIPE + from setuptools import setup + from distutils.extension import Extension + + print("Start pyozw_win") + + ctx = dict( + name='libopenzwave', + sources=['src-lib\\libopenzwave\\libopenzwave.pyx'], + include_dirs=['src-lib\\libopenzwave'], + define_macros=[ + ('PY_LIB_VERSION', pyozw_version), + ('PY_SSIZE_T_CLEAN', 1), + ('PY_LIB_FLAVOR', 'dev'), + ('PY_LIB_BACKEND', 'cython') + ], + libraries=[], + extra_objects=[], + extra_compile_args=[], + extra_link_args=[], + language='c++' + ) + + ozw_path = os.path.abspath('openzwave') + + if not os.path.exists(ozw_path): + get_openzwave('openzwave') + + options = dict() + + get_system_context( + ctx, + options, + openzwave=ozw_path, + static=True, + debug=True + ) + + clean = get_clean_command(**options) + build = get_build_command(**options) + + def run(command): + print('Running command:', command) + proc = Popen( + command, + shell=True, + stdout=PIPE, + stderr=PIPE, + cwd=os.path.split(options['solution_path'])[0], + ) + + if PY3: + dummy_return = b'' + else: + dummy_return = '' + + for line in iter(proc.stdout.readline, dummy_return): + if line and PY3: + sys.stdout.write(line.decode("utf-8")) + elif line: + sys.stdout.write(line) + + errcode = proc.returncode + print('\n\nerrcode', errcode, '\n\n') + + for line in iter(proc.stderr.readline, dummy_return): + if line and PY3: + sys.stdout.write(line.decode("utf-8")) + elif line: + sys.stdout.write(line) + + # run(clean) + # run(build) + + print( + 'Library built in %s using compiler %s for arch %s' % + (options['build_path'], options['msbuild_path'], options['arch']) + ) + + setup( + script_args=['build_ext'], + version=pyozw_version, + name='libopenzwave', + description='libopenzwave', + verbose=1, + ext_modules=[Extension(**ctx)], + ) diff --git a/setup-lib.py b/setup-lib.py index a7ea7181..ab9f22a5 100755 --- a/setup-lib.py +++ b/setup-lib.py @@ -36,7 +36,6 @@ from pyozw_version import pyozw_version from pyozw_setup import LOCAL_OPENZWAVE, SETUP_DIR from pyozw_setup import current_template, parse_template, get_dirs, data_files_config, install_requires -from pyozw_setup import get_default_exts, cython_context, cpp_context, pybind_context, system_context, cython_context from pyozw_setup import Template, DevTemplate, GitTemplate, EmbedTemplate, SharedTemplate from pyozw_setup import bdist_egg, build_openzwave, openzwave_config, build, clean, develop, install @@ -49,7 +48,7 @@ author='Sébastien GALLET aka bibi2100 ', author_email='bibi21000@gmail.com', version = pyozw_version, - scripts=['src-lib/scripts/pyozw_check'], + #~ scripts=['src-lib/scripts/pyozw_check'], zip_safe = False, url='https://github.com/OpenZWave/python-openzwave', cmdclass = {'build_ext': current_template.build_ext, @@ -67,7 +66,7 @@ package_dir = {'' : 'src-lib'}, #The following line install config drectory in share/python-openzwave #~ data_files = data_files, - packages = find_packages('src-lib', exclude=["scripts"]), + packages = find_packages('src-lib'), install_requires = install_requires(), ) diff --git a/setup-manager.py b/setup-manager.py index a819d572..5e3403d5 100644 --- a/setup-manager.py +++ b/setup-manager.py @@ -34,8 +34,8 @@ url='https://github.com/OpenZWave/python-openzwave', version = pyozw_version.pyozw_version, zip_safe = False, - scripts=['src-manager/scripts/pyozw_shell'], + #~ scripts=['src-manager/scripts/pyozw_shell'], package_dir = {'' : 'src-manager' }, - packages = find_packages('src-manager', exclude=["scripts"]), + packages = find_packages('src-manager'), install_requires=pyozw_version.install_requires() + [ "urwid>=1.1.1"], ) diff --git a/setup.py b/setup.py index 3c4c9868..7d17e584 100755 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ This file is part of **python-openzwave** project https://github.com/OpenZWave/python-openzwave. - :platform: Unix, Windows, MacOS X + :platform: Unix, Windows, MacOS X, BSD .. moduleauthor:: bibi21000 aka Sébastien GALLET @@ -34,8 +34,7 @@ from distutils.extension import Extension from pyozw_version import pyozw_version from pyozw_setup import LOCAL_OPENZWAVE, SETUP_DIR -from pyozw_setup import current_template, parse_template, get_dirs, data_files_config, install_requires -from pyozw_setup import get_default_exts, cython_context, cpp_context, pybind_context, system_context, cython_context +from pyozw_setup import current_template, parse_template, get_dirs, data_files_config, install_requires, build_requires from pyozw_setup import Template, DevTemplate, GitTemplate, EmbedTemplate, SharedTemplate from pyozw_setup import bdist_egg, build_openzwave, openzwave_config, build, clean, develop, install @@ -58,9 +57,11 @@ 'openzwave_config': openzwave_config, 'clean': clean, 'develop': develop, - 'install': install + 'install': install, }, - scripts=['src-lib/scripts/pyozw_check', 'src-manager/scripts/pyozw_shell'], + #~ scripts=['src-lib/scripts/pyozw_check', 'src-manager/scripts/pyozw_shell'], + entry_points={'console_scripts':['pyozw_check=python_openzwave.scripts.pyozw_check:main', + 'pyozw_shell=python_openzwave.scripts.pyozw_shell:main'] }, ext_modules = [ Extension(**current_template.ctx) ], @@ -85,6 +86,7 @@ "Topic :: Home Automation", "Topic :: System :: Hardware", "Topic :: System :: Hardware :: Hardware Drivers", + "Topic :: Software Development :: Libraries :: Python Modules", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", diff --git a/src-api/openzwave/command.py b/src-api/openzwave/command.py index a487b9fb..4b6d330c 100755 --- a/src-api/openzwave/command.py +++ b/src-api/openzwave/command.py @@ -357,6 +357,73 @@ def can_wake_up(self): else: return False + def get_configs(self, readonly='All', writeonly='All'): + """ + The command 0x70 (COMMAND_CLASS_CONFIGURATION) of this node. + Retrieve the list of configuration parameters. + + Filter rules are : + command_class = 0x70 + genre = "Config" + readonly = "All" (default) or as passed in arg + + :param readonly: whether to retrieve readonly configs + :param writeonly: whether to retrieve writeonly configs + :return: The list of configuration parameters + :rtype: dict() + """ + return self.get_values(class_id=0x70, genre='Config', readonly=readonly, writeonly=writeonly) + + def set_config(self, value_id, value): + """ + The command 0x70 (COMMAND_CLASS_CONFIGURATION) of this node. + Set config to value (using value value_id) + + :param value_id: The value to retrieve state + :type value_id: int + :param value: Appropriate value for given config + :type value: any + """ + if value_id in self.get_configs(readonly=False): + self.values[value_id].data = value + return True + return False + + + def get_config(self, value_id=None): + """ + The command 0x70 (COMMAND_CLASS_CONFIGURATION) of this node. + Set config to value (using value value_id) + + :param value_id: The value to retrieve value. If None, retrieve the first value + :type value_id: int + :return: The level of this battery + :rtype: int + """ + if value_id is None: + for val in self.get_configs(): + return self.values[val].data + elif value_id in self.get_configs(): + return self.values[value_id].data + return None + + def can_set_indicator(self): + """ + Check if node contain the command class 0x87 (COMMAND_CLASS_INDICATOR). + + Filter rules are : + + command_class = 0x87 + + :return: True if the node can set the indicator + :rtype: bool + """ + res = self.get_values(class_id=0x87) + if res is not None and len(res) > 0: + return True + else: + return False + class ZWaveNodeSwitch(ZWaveNodeInterface): """ Represents an interface to switches and dimmers Commands @@ -590,7 +657,7 @@ def set_rgbw(self, value_id, value): :param value_id: The value to retrieve state :type value_id: String - :param value: The level : a RGBW value + :param value: The level : a RGBW value :type value: int """ @@ -768,7 +835,7 @@ def set_thermostat_heating(self, value): """ logger.debug(u"set_thermostat_heating value:%s", value) for v in self.get_thermostats(): - if self.values[v].command_class == 0x43 and self.values[v].label == 'Heating 1': + if self.values[v].command_class == 0x43 and self.values[v].label in ('Heating 1', 'Heating'): self.values[v].data = value return True return False @@ -785,7 +852,7 @@ def set_thermostat_cooling(self, value): """ logger.debug(u"set_thermostat_cooling value:%s", value) for v in self.get_thermostats(): - if self.values[v].command_class == 0x43 and self.values[v].label == 'Cooling 1': + if self.values[v].command_class == 0x43 and self.values[v].label in ('Cooling 1', 'Cooling'): self.values[v].data = value return True return False @@ -888,3 +955,130 @@ def get_protection_items(self, value_id): if value_id in self.get_protections(): return self.values[value_id].data_items return None + + +class ZWaveNodeDoorLock(ZWaveNodeInterface): + """ + Represents an interface to door lock and user codes associated with door locks + """ + + def get_doorlocks(self): + """ + The command 0x62 (COMMAND_CLASS_DOOR_LOCK) of this node. + Retrieves the list of values to consider as doorlocks. + Filter rules are : + + command_class = 0x62 + genre = "User" + type = "Bool" + readonly = False + writeonly = False + + :return: The list of door locks on this node + :rtype: dict() + + """ + return self.get_values(class_id=0x62, genre='User', type='Bool', readonly=False, writeonly=False) + + def set_doorlock(self, value_id, value): + """ + The command 0x62 (COMMAND_CLASS_DOOR_LOCK) of this node. + Sets doorlock to value (using value_id). + + :param value_id: The value to retrieve state from + :type value_id: int + :param value: True or False + :type value: bool + + """ + if value_id in self.get_doorlocks(): + self.values[value_id].data = value + return True + return False + + def get_usercode(self, index): + """ + Retrieve particular usercode value by index. + Certain values such as user codes have index start from 0 + to max number of usercode supported and is useful for getting + usercodes by the index. + + :param index: The index of usercode value + :type index: int + :return: The user code at given index on this node + :rtype: ZWaveValue + + """ + usercode = self.get_usercodes(index) + if len(usercode) == 0: + return None + return list(usercode.values())[0] + + def get_usercodes(self, index='All'): + """ + The command 0x63 (COMMAND_CLASS_USER_CODE) of this node. + Retrieves the list of value to consider as usercodes. + Filter rules are : + + command_class = 0x63 + genre = "User" + type = "Raw" + readonly = False + writeonly = False + + :return: The list of user codes on this node + :rtype: dict() + + """ + return self.get_values(class_id=0x63, type='Raw', genre='User', readonly=False, writeonly=False, index=index) + + def set_usercode(self, value_id, value): + """ + The command 0x63 (COMMAND_CLASS_USER_CODE) of this node. + Sets usercode to value (using value_id). + + :param value_id: The value to retrieve state from + :type value_id: int + :param value: User Code as string + :type value: str + + """ + if value_id in self.get_usercodes(): + self.values[value_id].data = value + return True + return False + + def set_usercode_at_index(self, index, value): + """ + The command 0x63 (COMMAND_CLASS_USER_CODE) of this node. + Sets usercode to value (using index of value) + + :param index: The index of value to retrieve state from + :type index: int + :param value: User Code as string + :type value: str + + """ + usercode = self.get_usercode(index) + if usercode: + usercode.data = value + return True + return False + + + def get_doorlock_logs(self): + """ + The command 0x4c (COMMAND_CLASS_DOOR_LOCK_LOGGING) of this node. + Retrieves the value consisting of log records. + Filter rules are : + + command_class = 0x4c + genre = "User" + type = "String" + readonly = True + + :return: The dict of log records with value_id as key + :rtype: dict() + + """ + return self.get_values(class_id=0x4c, type='String', genre='User', readonly=True) diff --git a/src-api/openzwave/controller.py b/src-api/openzwave/controller.py index a4f0d68a..745740a9 100755 --- a/src-api/openzwave/controller.py +++ b/src-api/openzwave/controller.py @@ -24,15 +24,22 @@ along with python-openzwave. If not, see http://www.gnu.org/licenses. """ -import sys +import os, sys import six if six.PY3: from pydispatch import dispatcher + from urllib.request import urlopen else: from louie import dispatcher + from urllib2 import urlopen +import zipfile +import tempfile +import threading +import shutil +import time + from openzwave.object import ZWaveObject, deprecated from libopenzwave import PyStatDriver, PyControllerState -import threading # Set default logging handler to avoid "No handler found" warnings. import logging @@ -326,6 +333,17 @@ def library_version(self): """ return self._network.manager.getLibraryVersion(self._network.home_id) + @property + def python_library_flavor(self): + """ + The flavor of the python library. + + :return: The python library flavor + :rtype: str + + """ + return self._network.manager.getPythonLibraryFlavor() + @property def python_library_version(self): """ @@ -337,6 +355,23 @@ def python_library_version(self): """ return self._network.manager.getPythonLibraryVersionNumber() + @property + def python_library_config_version(self): + """ + The version of the config for python library. + + :return: The python library config version + :rtype: str + + """ + tversion = "Original %s" % self.library_version + fversion = os.path.join(self.library_config_path, 'pyozw_config.version') + if os.path.isfile(fversion): + with open(fversion, 'r') as f: + val = f.read() + tversion = "Git %s" % val + return tversion + @property def ozw_library_version(self): """ @@ -980,8 +1015,10 @@ def _lock_controller(self): }) def request_controller_status(self): - """Generate a notification with the current status of the controller. + """ + Generate a notification with the current status of the controller. You can check the lock in your code using something like this: + if controllerState in network.controller.STATES_UNLOCKED: hide_cancel_button() show_command_buttons() @@ -1048,6 +1085,7 @@ def to_dict(self, extras=['all']): ret["zw_description"] = self.library_description ret["oz_version"] = self.ozw_library_version ret["py_version"] = self.python_library_version + ret["py_config_version"] = self.python_library_config_version return ret @deprecated @@ -1314,3 +1352,58 @@ def zwcallback(self, args): dispatcher.send(self.SIGNAL_CONTROLLER, \ **{'state': state, 'message': message, 'network': self._network, 'controller': self}) + + def update_ozw_config(self): + """ + Update the openzwave config from github. + Not available for shared flavor as we don't want to update the config of the precompiled config. + + """ + if self.python_library_flavor in ['shared']: + logger.warning(u"Can't update_ozw_config for this flavor (%s)."%self.python_library_flavor) + return + logger.info(u'Update_ozw_config from github.') + dest = tempfile.mkdtemp() + dest_file = os.path.join(dest, 'open-zwave.zip') + try: + req = urlopen('https://codeload.github.com/OpenZWave/open-zwave/zip/master') + with open(dest_file, 'wb') as f: + f.write(req.read()) + zip_ref = zipfile.ZipFile(dest_file, 'r') + zip_ref.extractall(dest) + zip_ref.close() + except Exception: + logger.exception("Can't get zip from github. Cancelling") + try: + shutil.rmtree(dest) + except Exception: + pass + + if os.path.isdir(self.library_config_path): + #Try to remove old config + try: + shutil.rmtree(self.library_config_path) + except Exception: + logger.exception("Can't remove old config directory") + + try: + shutil.copytree(os.path.join(dest, 'open-zwave-master', 'config'), self.library_config_path) + except Exception: + logger.exception("Can't copy to %s", self.library_config_path) + + try: + with open(os.path.join(self.library_config_path, 'pyozw_config.version'), 'w') as f: + f.write(time.strftime("%Y-%m-%d %H:%M")) + except Exception: + logger.exception("Can't update %s", os.path.join(self.library_config_path, 'pyozw_config.version')) + + try: + with open(os.path.join(self.library_config_path, '__init__.py'), 'a') as f: + f.write("#This file is part of **python-openzwave** project https://github.com/OpenZWave/python-openzwave.") + except Exception: + logger.exception("Can't create %s", os.path.join(self.library_config_path, '__init__.py')) + + shutil.rmtree(dest) + + + diff --git a/src-api/openzwave/group.py b/src-api/openzwave/group.py index 177c3992..22c96d62 100755 --- a/src-api/openzwave/group.py +++ b/src-api/openzwave/group.py @@ -44,7 +44,7 @@ class ZWaveGroup(ZWaveObject): Also used to retrieve information about the library, ... """ - def __init__(self, group_index, network=None, node_id=None): + def __init__(self, group_index, network, node_id): """ Initialize driver object diff --git a/src-api/openzwave/network.py b/src-api/openzwave/network.py index 59ab530f..91fa48b9 100755 --- a/src-api/openzwave/network.py +++ b/src-api/openzwave/network.py @@ -30,11 +30,10 @@ import six if six.PY3: from pydispatch import dispatcher - import _thread as thread else: from louie import dispatcher - import thread import threading + import libopenzwave import openzwave from openzwave.object import ZWaveException, ZWaveTypeException, ZWaveObject @@ -43,7 +42,6 @@ from openzwave.option import ZWaveOption from openzwave.scene import ZWaveScene from openzwave.singleton import Singleton -import json # Set default logging handler to avoid "No handler found" warnings. import logging @@ -64,10 +62,10 @@ def emit(self, record): class ZWaveNetwork(ZWaveObject): """ - The network objet = homeid. + The network object = homeid. It contains a reference to the manager and the controller. - It dispatch the following louie signals : + It dispatches the following louie signals : * SIGNAL_NETWORK_FAILED = 'NetworkFailed' * SIGNAL_NETWORK_STARTED = 'NetworkStarted' @@ -101,8 +99,12 @@ class ZWaveNetwork(ZWaveObject): * SIGNAL_NODE_QUERIES_COMPLETE = 'NodeQueriesComplete' * SIGNAL_AWAKE_NODES_QUERIED = 'AwakeNodesQueried' * SIGNAL_ALL_NODES_QUERIED = 'AllNodesQueried' + * SIGNAL_ALL_NODES_QUERIED_SOME_DEAD = 'AllNodesQueriedSomeDead' * SIGNAL_MSG_COMPLETE = 'MsgComplete' * SIGNAL_ERROR = 'Error' + * SIGNAL_NOTIFICATION = 'Notification' + * SIGNAL_CONTROLLER_COMMAND = 'ControllerCommand' + * SIGNAL_CONTROLLER_WAITING = 'ControllerWaiting' The table presented below sets notifications in the order they might typically be received, and grouped into a few logically related categories. Of course, given the variety @@ -221,10 +223,10 @@ class ZWaveNetwork(ZWaveObject): * ValueRemoved : Sent when a value associated with a node has been removed. * Group : Sent when a node’s group association has changed. * NodeRemoved : Sent when a node has been removed from the ZWave network. - * NodeEvent : Sent when a node sends a Basic_Set command to the controller. This notification can be generated by certain sensors, for example, motion detectors, to indicate that an event has been sensed. + * NodeEvent : Sent when a node sends a Basic_Set command to the controller. This notification can be generated by certain sensors, for example, motion detectors, to indicate that an event has been sensed. * PollingEnabled : Sent when node/value polling has been enabled. * PollingDisabled : Sent when node/value polling has been disabled. - * DriverReset : Sent to indicate when a controller has been reset. This notification is intended to replace the potentially hundreds of notifications representing each value and node removed from the network. + * DriverReset : Sent to indicate when a controller has been reset. This notification is intended to replace the potentially hundreds of notifications representing each value and node removed from the network. About the use of louie signals : For network, python-openzwave send the following louie signal : @@ -300,8 +302,8 @@ def __init__(self, options, log=None, autostart=True, kvals=True): :type log: :param autostart: should we start the network. :type autostart: bool - :param autostart: Enable kvals (use pysqlite) - :type autostart: bool + :param kvals: Enable kvals (use pysqlite) + :type kvals: bool """ logger.debug("Create network object.") @@ -674,7 +676,7 @@ def heal(self, upNodeRoute=False): """ if self.network.state < self.network.STATE_AWAKED: - logger.warning(u'Network state must a minimum set to awake') + logger.warning(u'Network must be awake') return False self.manager.healNetwork(self.home_id, upNodeRoute) return True diff --git a/src-api/openzwave/node.py b/src-api/openzwave/node.py index 09ae4878..1c399d80 100755 --- a/src-api/openzwave/node.py +++ b/src-api/openzwave/node.py @@ -24,12 +24,13 @@ """ import sys +from libopenzwave import PyStatNode from openzwave.object import ZWaveObject from openzwave.group import ZWaveGroup from openzwave.value import ZWaveValue from openzwave.command import ZWaveNodeBasic, ZWaveNodeSwitch from openzwave.command import ZWaveNodeSensor, ZWaveNodeThermostat -from openzwave.command import ZWaveNodeSecurity +from openzwave.command import ZWaveNodeSecurity, ZWaveNodeDoorLock # Set default logging handler to avoid "No handler found" warnings. import logging @@ -46,7 +47,7 @@ def emit(self, record): class ZWaveNode(ZWaveObject, ZWaveNodeBasic, ZWaveNodeSwitch, ZWaveNodeSensor, ZWaveNodeThermostat, - ZWaveNodeSecurity): + ZWaveNodeSecurity, ZWaveNodeDoorLock): """ Represents a single Node within the Z-Wave Network. @@ -249,6 +250,8 @@ def capabilities(self): caps.add('security') if self.is_beaming_device: caps.add('beaming') + if self.is_zwave_plus: + caps.add('zwave_plus') if self.node_id == self._network.controller.node_id: for cap in self._network.controller.capabilities: caps.add(cap) @@ -419,8 +422,8 @@ def get_values_for_command_class(self, class_id): #print class_id return self.get_values(class_id=class_id) - def get_values(self, class_id='All', genre='All', \ - type='All', readonly='All', writeonly='All'): + def get_values(self, class_id='All', genre='All', type='All', \ + readonly='All', writeonly='All', index='All', label='All'): """ Retrieve the set of values. You can optionnaly filter for a command class, a genre and/or a type. You can also filter readonly and writeonly params. @@ -438,6 +441,10 @@ def get_values(self, class_id='All', genre='All', \ :type readonly: 'All' or True or False :param writeonly: Is this value writeonly :type writeonly: 'All' or True or False + :param index: Index of value within all the values + :type index: int + :param label: Label of the value as set by openzwave + :type label: str :rtype: set() of Values """ @@ -448,7 +455,9 @@ def get_values(self, class_id='All', genre='All', \ (genre == 'All' or self.values[value].genre == genre) and \ (type == 'All' or self.values[value].type == type) and \ (readonly == 'All' or self.values[value].is_read_only == readonly) and \ - (writeonly == 'All' or self.values[value].is_write_only == writeonly): + (writeonly == 'All' or self.values[value].is_write_only == writeonly) and \ + (index == 'All' or self.values[value].index == index) and \ + (label == 'All' or self.values[value].label == label): ret[value] = self.values[value] return ret @@ -1047,3 +1056,45 @@ def type(self): :rtype: str """ return self._network.manager.getNodeType(self.home_id, self.object_id) + + @property + def stats(self): + """ + Retrieve statistics for node. + + Statistics: + + * sentCnt : Number of messages sent from this node. + * sentFailed : Number of sent messages failed + * retries : Number of message retries + * receivedCnt : Number of messages received from this node. + * receivedDups : Number of duplicated messages received; + * receivedUnsolicited : Number of messages received unsolicited + * lastRequestRTT : Last message request RTT + * lastResponseRTT : Last message response RTT + * sentTS : Last message sent time + * receivedTS : Last message received time + * averageRequestRTT : Average Request round trip time. + * averageResponseRTT : Average Response round trip time. + * quality : Node quality measure + * lastReceivedMessage[254] : Place to hold last received message + * errors : Count errors for dead node detection + + :return: Statistics of the node + :rtype: dict() + + """ + return self._network.manager.getNodeStatistics(self.home_id, self.object_id) + + def get_stats_label(self, stat): + """ + Retrieve label of the statistic for node. + + :param stat: The code of the stat label to retrieve. + :type stat: + :return: The label or the stat. + :rtype: str + + """ + #print "stat = %s" % stat + return PyStatNode[stat] diff --git a/src-api/openzwave/option.py b/src-api/openzwave/option.py index 8ee3e709..7fc68990 100755 --- a/src-api/openzwave/option.py +++ b/src-api/openzwave/option.py @@ -43,16 +43,42 @@ def emit(self, record): logger = logging.getLogger('openzwave') logger.addHandler(NullHandler()) + +VENDOR_IDS = ('0658',) + + +def _get_z_stick(): + try: + import serial.tools.list_ports + except ImportError: + return None + + for port in serial.tools.list_ports.comports(include_links=False): + if port.vid is None: + continue + if port.product is not None and 'Zigbee' in port.product: + continue + if port.interface is not None and 'Zigbee' in port.interface: + continue + if port.description is not None and 'Zigbee' in port.description: + continue + + for vid in VENDOR_IDS: + if vid.upper() == hex(port.vid)[2:].upper().zfill(4): + return port.device + return None + + class ZWaveOption(libopenzwave.PyOptions): """ Represents a Zwave option used to start the manager. """ - def __init__(self, device=None, config_path=None, user_path=".", cmd_line=""): + def __init__(self, device=None, config_path=None, user_path=None, cmd_line=None): """ Create an option object and check that parameters are valid. - :param device: The device to use + :param device: The device to use or None for auto detection (pyserial needs to be installed for auto detection). :type device: str :param config_path: The openzwave config directory. If None, try to configure automatically. :type config_path: str @@ -62,7 +88,13 @@ def __init__(self, device=None, config_path=None, user_path=".", cmd_line=""): :type cmd_line: str """ + if device is None: + device = _get_z_stick() + if platform_system() == 'Windows': + if device and not device.startswith('\\\\.\\'): + device = '\\\\.\\' + device + self._device = device else: #For linux @@ -80,8 +112,6 @@ def __init__(self, device=None, config_path=None, user_path=".", cmd_line=""): import sys, traceback raise ZWaveException(u"Error when retrieving device %s : %s" % (device, traceback.format_exception(*sys.exc_info()))) libopenzwave.PyOptions.__init__(self, config_path=config_path, user_path=user_path, cmd_line=cmd_line) - self._user_path = user_path - self._config_path = config_path def set_log_file(self, logfile): """ diff --git a/src-api/openzwave/scene.py b/src-api/openzwave/scene.py index 2d5a722e..5911c9b8 100755 --- a/src-api/openzwave/scene.py +++ b/src-api/openzwave/scene.py @@ -42,7 +42,7 @@ class ZWaveScene(ZWaveObject): Represents a single scene within the Z-Wave Network """ - def __init__(self, scene_id, network=None): + def __init__(self, scene_id, network): """ Initialize zwave scene diff --git a/src-api/openzwave/value.py b/src-api/openzwave/value.py index 46793800..8f4498d9 100755 --- a/src-api/openzwave/value.py +++ b/src-api/openzwave/value.py @@ -555,8 +555,10 @@ def to_dict(self, extras=['all']): :rtype: dict() """ + attrs = [] if 'all' in extras: - extras = ['kvals'] + extras = ['kvals'] + attrs = ['data_items', 'command_class', 'is_read_only', 'is_write_only', 'type', 'index'] ret={} ret['label'] = self.label ret['value_id'] = self.value_id @@ -564,6 +566,9 @@ def to_dict(self, extras=['all']): ret['units'] = self.units ret['genre'] = self.genre ret['data'] = self.data + + for k in attrs: + ret[k] = getattr(self, k) if 'kvals' in extras and self.network.dbcon is not None: vals = self.kvals for key in vals.keys(): diff --git a/src-lib/libopenzwave/libopenzwave.pyx b/src-lib/libopenzwave/libopenzwave.pyx index 50487f9f..2753a7d5 100644 --- a/src-lib/libopenzwave/libopenzwave.pyx +++ b/src-lib/libopenzwave/libopenzwave.pyx @@ -320,7 +320,7 @@ PyOptionList = { 'IntervalBetweenPolls' : {'doc' : "If false, try to execute the entire poll list within the PollInterval time frame. If true, wait for PollInterval milliseconds between polls.", 'type' : "Bool"}, 'SuppressValueRefresh' : {'doc' : "If true, notifications for refreshed (but unchanged) values will not be sent.", 'type' : "Bool"}, 'PerformReturnRoutes' : {'doc' : "If true, return routes will be updated.", 'type' : "Bool"}, - 'NetworkKey' : {'doc' : ".", 'type' : "String"}, + 'NetworkKey' : {'doc' : "Key used to negotiate and communicate with devices that support Security Command Class", 'type' : "String"}, 'RefreshAllUserCodes' : {'doc' : "If true, during startup, we refresh all the UserCodes the device reports it supports. If False, we stop after we get the first 'Available' slot (Some devices have 250+ usercode slots! - That makes our Session Stage Very Long ).", 'type' : "Bool"}, 'RetryTimeout' : {'doc' : "How long do we wait to timeout messages sent.", 'type' : "Int"}, 'EnableSIS' : {'doc' : "Automatically become a SUC if there is no SUC on the network.", 'type' : "Bool"}, @@ -354,6 +354,24 @@ PyStatDriver = { 'broadcastWriteCnt' : "Number of broadcasts sent", } +PyStatNode = { + 'sentCnt' : "Number of messages sent from this node", + 'sentFailed' : "Number of sent messages failed", + 'retries' : "Number of message retries", + 'receivedCnt' : "Number of messages received from this node", + 'receivedDups' : "Number of duplicated messages received", + 'receivedUnsolicited' : "Number of messages received unsolicited", + 'lastRequestRTT' : "Last message request RTT", + 'lastResponseRTT' : "Last message response RTT", + 'sentTS' : "Last message sent time", + 'receivedTS' : "Last message received time", + 'averageRequestRTT' : "Average Request round trip time", + 'averageResponseRTT' : "Average Response round trip time", + 'quality' : "Node quality measure", + 'lastReceivedMessage' : "Place to hold last received message", + 'errors' : "Count errors for dead node detection", + } + PyLogLevels = { 'Invalid' : {'doc':'Invalid Log Status', 'value':0}, 'None' : {'doc':'Disable all logging', 'value':1}, @@ -646,13 +664,13 @@ cdef class PyOptions: Manage options manager """ - cdef str _config_path - cdef str _user_path - cdef str _cmd_line + cdef readonly str _config_path + cdef readonly str _user_path + cdef readonly str _cmd_line cdef Options *options - def __init__(self, config_path=None, user_path=".", cmd_line=""): + def __init__(self, config_path=None, user_path=None, cmd_line=None): """ Create an option object and check that parameters are valid. @@ -1061,7 +1079,7 @@ sleeping) have been polled, an "AllNodesQueried" notification is sent. 0x56: 'COMMAND_CLASS_CRC_16_ENCAP', 0x5A: 'COMMAND_CLASS_DEVICE_RESET_LOCALLY', 0x5B: 'COMMAND_CLASS_CENTRAL_SCENE', - 0x5E: 'COMMAND_CLASS_ZWAVE_PLUS_INFO', + 0x5E: 'COMMAND_CLASS_ZWAVEPLUS_INFO', 0x60: 'COMMAND_CLASS_MULTI_INSTANCE/CHANNEL', 0x61: 'COMMAND_CLASS_DISPLAY', 0x62: 'COMMAND_CLASS_DOOR_LOCK', @@ -1366,6 +1384,19 @@ Get the version of the Z-Wave API library used by a controller. cdef string c_string = self.manager.GetLibraryVersion(homeid) return cstr_to_str(c_string.c_str()) + def getPythonLibraryFlavor(self): + ''' +.. _getPythonLibraryFlavor: + +Get the flavor of the python library. + +:return: A string containing the python library flavor. For example, "embed". +:rtype: str +:see: getLibraryTypeName_, getLibraryVersion_, getOzwLibraryVersion_, getOzwLibraryLongVersion + + ''' + return "%s" % (PY_LIB_FLAVOR_STRING) + def getPythonLibraryVersion(self): ''' .. _getPythonLibraryVersion: @@ -1797,10 +1828,6 @@ Statistics: * averageResponseRTT #Average Reponse round trip time. * quality # Node quality measure * lastReceivedMessage[254] # Place to hold last received message - * ccData # List of statistic - * commandClassId # Num of commandClass id. - * sentCnt # Number of messages sent from this CommandClass. - * receivedCnt # Number of messages received from this CommandClass. :param homeId: The Home ID of the Z-Wave controller. :type homeId: int @@ -1833,16 +1860,6 @@ Statistics: ret['lastReceivedMessage'] = [] for i in range( 0, 254) : ret['lastReceivedMessage'] .append(data.m_lastReceivedMessage[i]) - listccdata =[] - while not data.m_ccData.empty() : - ccd = {} - temp = data.m_ccData.back() - ccd['commandClassId'] = temp.m_commandClassId - ccd['sentCnt'] = temp.m_sentCnt - ccd['receivedCnt'] = temp.m_receivedCnt - listccdata.append(ccd) - data.m_ccData.pop_back(); - ret['ccData'] = listccdata return ret def requestNodeDynamic(self, homeid, nodeid): diff --git a/src-lib/libopenzwave/node.pxd b/src-lib/libopenzwave/node.pxd index f8e076f1..9f99d72d 100755 --- a/src-lib/libopenzwave/node.pxd +++ b/src-lib/libopenzwave/node.pxd @@ -18,8 +18,6 @@ along with python-openzwave. If not, see http://www.gnu.org/licenses. """ from libc.stdint cimport uint32_t, int32_t, int16_t, uint8_t, int8_t -from libcpp.vector cimport vector -#from libcpp.string cimport string from mylibc cimport string cdef extern from "Node.h" namespace "OpenZWave::Node": @@ -46,15 +44,15 @@ cdef extern from "Node.h" namespace "OpenZWave::Node": uint32_t m_receivedCnt # Number of messages received from this node. uint32_t m_receivedDups # Number of duplicated messages received; uint32_t m_receivedUnsolicited # Number of messages received unsolicited + uint32_t m_lastRequestRTT # Last message request RTT + uint32_t m_lastResponseRTT # Last message response RTT string m_sentTS # Last message sent time string m_receivedTS # Last message received time - uint32_t m_lastRequestRTT # Last message request RTT uint32_t m_averageRequestRTT # Average Request Round Trip Time (ms). - uint32_t m_lastResponseRTT # Last message response RTT uint32_t m_averageResponseRTT #Average Reponse round trip time. uint8_t m_quality # Node quality measure uint8_t m_lastReceivedMessage[254] # Place to hold last received message - vector[CommandClassData] m_ccData # List of statistic on each command_class + uint8_t m_errors # Count errors for dead node detection ctypedef NodeData NodeData_t diff --git a/src-manager/pyozwman/ozwsh_widgets.py b/src-manager/pyozwman/ozwsh_widgets.py index 8b2725fc..9c892614 100755 --- a/src-manager/pyozwman/ozwsh_widgets.py +++ b/src-manager/pyozwman/ozwsh_widgets.py @@ -428,9 +428,11 @@ def read_lines(self): self.lines.append(urwid.Text( " %s:%s" % (groups[group].index,groups[group].label), align='left')) self.size += 1 for assoc in groups[group].associations: - self.lines.append(AssociationItem(assoc, \ - self.window.network.nodes[assoc].name - )) + if assoc in self.window.network.nodes: + aname = self.window.network.nodes[assoc].name + else: + aname = "[%d missing]" % (assoc) + self.lines.append(AssociationItem(assoc, aname)) self.size += 1 self._modified() @@ -478,7 +480,7 @@ def remove(self, param, value): self.window.status_bar.update(status="Invalid index or node ID %s/%s" % (param, value)) return False if param in self.window.network.nodes[self.node_id].groups: - if value in self.window.network.nodes[self.node_id].groups : + if value in self.window.network.nodes[self.node_id].groups[param].associations : self.window.network.nodes[self.node_id].groups[param].remove_association(value) self.window.status_bar.update(status='Group %s updated' % param) return True @@ -1340,7 +1342,7 @@ def add(self, param, value): def set(self, param, value): values = self.window.network.nodes[self.node_id].values try: - param = long(param) + param = int(param) except: ok = False for val in values: @@ -1373,7 +1375,7 @@ def set(self, param, value): def poll(self, param, value): values = self.window.network.nodes[self.node_id].values try: - param = long(param) + param = int(param) except: ok = False for val in values: @@ -1973,7 +1975,7 @@ def cd(self, directory): def delete(self, value): valueid = None try: - valueid = long(value) + valueid = int(value) except: ok = False try: diff --git a/src-python_openzwave/python_openzwave/scripts/__init__.py b/src-python_openzwave/python_openzwave/scripts/__init__.py new file mode 100755 index 00000000..240ad6d1 --- /dev/null +++ b/src-python_openzwave/python_openzwave/scripts/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +__license__ = """ + +This file is part of **python-openzwave** project https://github.com/OpenZWave/python-openzwave. + +License : GPL(v3) + +**python-openzwave** is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +**python-openzwave** is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with python-openzwave. If not, see http://www.gnu.org/licenses. +""" +__copyright__ = "Copyright © 2012-2015 Sébastien GALLET aka bibi21000" +__author__ = 'Sébastien GALLET aka bibi21000' +__email__ = 'bibi21000@gmail.com' + +try: + __import__('pkg_resources').declare_namespace("openzwave") +except: + # bootstrapping + pass diff --git a/src-lib/scripts/pyozw_check b/src-python_openzwave/python_openzwave/scripts/pyozw_check.py similarity index 56% rename from src-lib/scripts/pyozw_check rename to src-python_openzwave/python_openzwave/scripts/pyozw_check.py index 003770db..0d888a2f 100644 --- a/src-lib/scripts/pyozw_check +++ b/src-python_openzwave/python_openzwave/scripts/pyozw_check.py @@ -32,6 +32,8 @@ args = None def imports(args): + if args.timeout is None: + args.timeout = 2 if args.output == 'txt': print("-------------------------------------------------------------------------------") print("Import libs") @@ -51,6 +53,8 @@ def imports(args): print("Try to get python_openzwave full version") print(manager.getPythonLibraryVersion()) print("Try to get openzwave version") + print(manager.getPythonLibraryVersion()) + print("Try to get openzwave version") print(manager.getOzwLibraryVersion()) print("Try to get default config path") print(libopenzwave.configPath()) @@ -61,7 +65,7 @@ def imports(args): time.sleep(0.5) print("Try to import openzwave (API)") import openzwave - + elif args.output == 'raw': import libopenzwave from libopenzwave import PyLogLevels @@ -92,19 +96,21 @@ def zwcallback(zwargs): if notify_type == "DriverReady": global home_id home_id = zwargs['homeId'] - + #~ print("Received {0} : {1}".format(notify_type,libopenzwave.PyNotifications[notify_type].doc)) if args.output == 'txt': print("Received {0}".format(notify_type)) def init_device(args): global home_id + if args.timeout is None: + args.timeout = 15 if args.output == 'txt': print("-------------------------------------------------------------------------------") print("Intialize device {0}".format(args.device)) import libopenzwave print("Try to get options") - options = libopenzwave.PyOptions(user_path=".", cmd_line="--logging true") + options = libopenzwave.PyOptions(config_path=args.config_path, user_path=args.user_path, cmd_line="--logging true") options.lock() time.sleep(1.0) print("Try to get manager") @@ -146,7 +152,7 @@ def init_device(args): print("{0:08x}".format(home_id)) elif args.output == 'raw': import libopenzwave - options = libopenzwave.PyOptions(user_path=".", cmd_line="--logging false") + options = libopenzwave.PyOptions(config_path=args.config_path, user_path=args.user_path, cmd_line="--logging false") options.lock() time.sleep(1.0) manager = libopenzwave.PyManager() @@ -171,14 +177,95 @@ def init_device(args): manager.destroy() time.sleep(0.2) options.destroy() - + +def list_nodes(args): + global home_id + if args.timeout is None: + args.timeout = 60*60*4+1 + import openzwave + from openzwave.node import ZWaveNode + from openzwave.value import ZWaveValue + from openzwave.scene import ZWaveScene + from openzwave.controller import ZWaveController + from openzwave.network import ZWaveNetwork + from openzwave.option import ZWaveOption + + #Define some manager options + print("-------------------------------------------------------------------------------") + print("Define options for device {0}".format(args.device)) + options = ZWaveOption(device=args.device, config_path=args.config_path, user_path=args.user_path) + options.set_log_file("OZW_Log.log") + options.set_append_log_file(False) + options.set_console_output(False) + options.set_save_log_level("Debug") + options.set_logging(True) + options.lock() + + print("Start network") + network = ZWaveNetwork(options, log=None) + + delta = 0.5 + for i in range(0, int(args.timeout/delta)): + time.sleep(delta) + if network.state >= network.STATE_AWAKED: + break + + print("-------------------------------------------------------------------------------") + print("Network is awaked. Talk to controller.") + print("Get python_openzwave version : {}".format(network.controller.python_library_version)) + print("Get python_openzwave config version : {}".format(network.controller.python_library_config_version)) + print("Get python_openzwave flavor : {}".format(network.controller.python_library_flavor)) + print("Get openzwave version : {}".format(network.controller.ozw_library_version)) + print("Get config path : {}".format(network.controller.library_config_path)) + print("Controller capabilities : {}".format(network.controller.capabilities)) + print("Controller node capabilities : {}".format(network.controller.node.capabilities)) + print("Nodes in network : {}".format(network.nodes_count)) + + print("-------------------------------------------------------------------------------") + if args.timeout > 1800: + print("You defined a really long timneout. Please use --help to change this feature.") + print("Wait for network ready ({0}s)".format(args.timeout)) + for i in range(0, int(args.timeout/delta)): + time.sleep(delta) + if network.state == network.STATE_READY: + break + print("-------------------------------------------------------------------------------") + if network.state == network.STATE_READY: + print("Network is ready. Get nodes") + elif network.state == network.STATE_AWAKED: + print("Network is awake. Some sleeping devices may miss. You can increase timeout to get them. But will continue.") + else: + print("Network is still starting. You MUST increase timeout. But will continue.") + + for node in network.nodes: + + print("------------------------------------------------------------") + print("{} - Name : {} ( Location : {} )".format(network.nodes[node].node_id, network.nodes[node].name, network.nodes[node].location)) + print(" {} - Ready : {} / Awake : {} / Failed : {}".format(network.nodes[node].node_id, network.nodes[node].is_ready, network.nodes[node].is_awake, network.nodes[node].is_failed)) + print(" {} - Manufacturer : {} ( id : {} )".format(network.nodes[node].node_id, network.nodes[node].manufacturer_name, network.nodes[node].manufacturer_id)) + print(" {} - Product : {} ( id : {} / type : {} / Version : {})".format(network.nodes[node].node_id, network.nodes[node].product_name, network.nodes[node].product_id, network.nodes[node].product_type, network.nodes[node].version)) + print(" {} - Command classes : {}".format(network.nodes[node].node_id, network.nodes[node].command_classes_as_string)) + print(" {} - Capabilities : {}".format(network.nodes[node].node_id, network.nodes[node].capabilities)) + print(" {} - Neighbors : {} / Power level : {}".format(network.nodes[node].node_id, network.nodes[node].neighbors, network.nodes[node].get_power_level())) + print(" {} - Is sleeping : {} / Can wake-up : {} / Battery level : {}".format(network.nodes[node].node_id, network.nodes[node].is_sleeping, network.nodes[node].can_wake_up(), network.nodes[node].get_battery_level())) + + print("------------------------------------------------------------") + print("Driver statistics : {}".format(network.controller.stats)) + print("------------------------------------------------------------") + print("Stop network") + network.stop() + print("Exit") + def pyozw_parser(): parser = argparse.ArgumentParser(description='Run python_openzwave basics checks.') parser.add_argument('-o', '--output', action='store', help='The format (txt, raw, ...)', choices=['txt', 'raw'], default='txt') - parser.add_argument('-d', '--device', action='store', help='The device port', default='/dev/ttyUSB0') + parser.add_argument('-d', '--device', action='store', help='The device port', default=None) parser.add_argument('-m', '--imports', action='store_true', help='Import all libs', default=True) parser.add_argument('-i', '--init_device', action='store_true', help='Intialize the device', default=False) - parser.add_argument('-t', '--timeout', action='store',type=int, help='The default timeout for zwave network sniffing', default=10) + parser.add_argument('-l', '--list_nodes', action='store_true', help='List the nodes on zwave network', default=False) + parser.add_argument('-t', '--timeout', action='store',type=int, help='The default timeout for zwave network sniffing', default=None) + parser.add_argument('--config_path', action='store', help='The config_path for openzwave', default=None) + parser.add_argument('--user_path', action='store', help='The user_path for openzwave', default=".") return parser def main(): @@ -187,8 +274,11 @@ def main(): args = parser.parse_args() if args.init_device: init_device(args) + elif args.list_nodes: + list_nodes(args) elif args.imports: imports(args) + if __name__ == '__main__': main() diff --git a/src-manager/scripts/pyozw_shell b/src-python_openzwave/python_openzwave/scripts/pyozw_shell.py similarity index 98% rename from src-manager/scripts/pyozw_shell rename to src-python_openzwave/python_openzwave/scripts/pyozw_shell.py index fd365333..b6b67fb7 100755 --- a/src-manager/scripts/pyozw_shell +++ b/src-python_openzwave/python_openzwave/scripts/pyozw_shell.py @@ -49,7 +49,7 @@ def main(): '-d', '--device', dest='device', type="str", - default="/dev/ttyUSB0", + default=None, help="The path to your ZWave device") parser.add_option( diff --git a/tests/api/common.py b/tests/api/common.py index 18a74dff..b771cf64 100644 --- a/tests/api/common.py +++ b/tests/api/common.py @@ -30,7 +30,6 @@ import unittest import threading import logging -import json as mjson import shutil from nose.plugins.skip import SkipTest import libopenzwave @@ -51,7 +50,7 @@ from louie import dispatcher from tests.common import SLEEP -from tests.common import TestPyZWave +from tests.common import TestPyZWave, json_dumps, json_loads class TestApi(TestPyZWave): """ @@ -68,7 +67,6 @@ def setUpClass(self): self.options.set_save_log_level(self.ozwlog) self.options.set_logging(True) self.options.lock() - dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE) self.network = ZWaveNetwork(self.options) self.node_result = None self.ctrl_command_result = None @@ -86,11 +84,12 @@ def tearDownClass(self): self.network = None def setUp(self): + dispatcher.connect(self.node_update, ZWaveNetwork.SIGNAL_NODE) self.node_result = None self.ctrl_command_result = None self.ctrl_command_signal = None self.wait_for_network_state(self.network.STATE_AWAKED, 1) - time.sleep(1.0) + time.sleep(2.0) self.wait_for_queue() self.active_nodes = {} for node in self.network.nodes: @@ -98,6 +97,9 @@ def setUp(self): self.active_nodes[node] = self.network.nodes[node] print('active nodes : %s' % self.active_nodes) + def tearDown(self): + dispatcher.disconnect(self.node_update, ZWaveNetwork.SIGNAL_NODE) + def wait_for_queue(self): for i in range(0,60): if self.network.controller.send_queue_count <= 0: diff --git a/tests/api/test_battery.py b/tests/api/test_command.py similarity index 67% rename from tests/api/test_battery.py rename to tests/api/test_command.py index 4e8a506a..264fe0d3 100644 --- a/tests/api/test_battery.py +++ b/tests/api/test_command.py @@ -55,17 +55,37 @@ from tests.api.common import TestApi from tests.common import TestPyZWave -class TestBattery(TestApi): +class TestCommand(TestApi): def test_010_battery_item(self): ran = False for node in self.active_nodes: for val in self.active_nodes[node].get_battery_levels() : ran = True - self.assertTrue(isinstance(self.network.controller.get_battery_level(val), integer_types)) + self.assertTrue(isinstance(self.active_nodes[node].get_battery_level(val), + six.integer_types)) if ran == False : self.skipTest("No battery found") + def test_020_config_item(self): + ran = False + for node in self.active_nodes: + for val in self.active_nodes[node].get_configs() : + ran = True + self.assertNotEqual(self.active_nodes[node].get_config(val), None) + if ran == False : + self.skipTest("No config param found") + + def test_030_door_locks(self): + ran = False + for node in self.active_nodes: + for val in self.active_nodes[node].get_doorlocks() : + ran = True + self.assertNotEqual(self.active_nodes[node].get_usercodes(), None) + self.assertNotEqual(self.active_nodes[node].get_doorlock_logs(), None) + if ran == False : + self.skipTest("No door_locks found") + if __name__ == '__main__': sys.argv.append('-v') unittest.main() diff --git a/tests/api/test_controller.py b/tests/api/test_controller.py index d75ae96f..5254c2a3 100644 --- a/tests/api/test_controller.py +++ b/tests/api/test_controller.py @@ -59,6 +59,7 @@ def test_010_controller(self): self.assertTrue(isinstance(self.network.controller.name, string_types)) self.assertTrue(isinstance(self.network.controller.ozw_library_version, string_types)) self.assertTrue(isinstance(self.network.controller.python_library_version, string_types)) + self.assertTrue(isinstance(self.network.controller.python_library_flavor, string_types)) self.assertTrue(isinstance(self.network.controller.library_description, string_types)) def test_020_controller_capabilities(self): @@ -71,6 +72,17 @@ def test_030_controller_send_queue(self): def test_040_controller_stats(self): self.assertEqual(type(self.network.controller.stats), type(dict())) + def test_050_controller_update_ozw_config(self): + #Remove old config version + try: + os.remove(os.path.join(self.network.controller.library_config_path, 'pyozw_config.version')) + except: + pass + self.assertTrue(self.network.controller.python_library_config_version.startswith('Original')) + if not ( self.network.controller.python_library_flavor in ['shared']): + self.network.controller.update_ozw_config() + self.assertTrue(self.network.controller.python_library_config_version.startswith('Git')) + def test_110_controller_soft_reset(self): time.sleep(5) self.network.controller.soft_reset() diff --git a/tests/api/test_controller_command.py b/tests/api/test_controller_command.py index 047fca19..0e5c3b51 100644 --- a/tests/api/test_controller_command.py +++ b/tests/api/test_controller_command.py @@ -64,9 +64,10 @@ def tearDownClass(self): super(TestControllerCommand, self).tearDownClass() def setUp(self): - self.wait_for_network_state(self.network.STATE_READY, 1) - self.wait_for_queue() - self.ctrl_state_result = None + # ~ self.wait_for_network_state(self.network.STATE_READY, 1) + # ~ self.wait_for_queue() + # ~ self.ctrl_state_result = None + TestApi.setUp(self) dispatcher.connect(self.ctrl_message, ZWaveNetwork.SIGNAL_CONTROLLER_COMMAND) dispatcher.connect(self.ctrl_waiting, ZWaveNetwork.SIGNAL_CONTROLLER_WAITING) time.sleep(2.0) @@ -106,9 +107,10 @@ def test_005_request_controller_status(self): def test_010_command_send_node_information_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: - node_id = max(self.network.nodes.keys()) + # ~ node_id = max(self.network.nodes.keys()) + # ~ node_id = self.active_nodes.keys()[1] ret = self.network.controller.send_node_information(node_id) self.assertTrue(ret) current = None @@ -120,7 +122,9 @@ def test_010_command_send_node_information_nodes(self): break else: time.sleep(1.0) + print(self.ctrl_command_signal) self.assertEqual(current, self.network.controller.STATE_COMPLETED) + self.assertEqual(self.ctrl_command_signal['node_id'], node_id) def test_015_command_send_node_information_controller(self): self.ctrl_state_result = None @@ -140,7 +144,8 @@ def test_015_command_send_node_information_controller(self): def test_020_command_request_node_neighbor_update_nodes(self): self.wipTest() self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: ret = self.network.controller.request_node_neighbor_update(node_id) self.assertTrue(ret) @@ -173,7 +178,7 @@ def test_025_command_request_node_neighbor_update_controller(self): def test_030_command_request_network_update_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.request_network_update(node_id) @@ -206,7 +211,7 @@ def test_035_command_request_network_update_controller(self): def test_040_command_delete_all_return_routes_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.delete_all_return_routes(node_id) @@ -239,7 +244,7 @@ def test_045_command_delete_all_return_routes_controller(self): def test_050_command_assign_return_route_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.assign_return_route(node_id) @@ -272,7 +277,7 @@ def test_055_command_assign_return_route_controller(self): def test_060_command_has_node_failed_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.has_node_failed(node_id) @@ -287,10 +292,11 @@ def test_060_command_has_node_failed_nodes(self): else: time.sleep(1.0) self.assertEqual(current, self.network.controller.STATE_NODEOK) + self.assertEqual(self.ctrl_command_signal['node_id'], node_id) def test_070_command_remove_failed_node_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.remove_failed_node(node_id) @@ -308,7 +314,7 @@ def test_070_command_remove_failed_node_nodes(self): def test_080_command_replace_failed_node_nodes(self): self.ctrl_state_result = None - node_ids = [ k for k in self.network.nodes.keys() if k != self.network.controller.node_id ] + node_ids = [ k for k in self.active_nodes.keys() if k != self.network.controller.node_id ] for node_id in node_ids: node_id = max(self.network.nodes.keys()) ret = self.network.controller.replace_failed_node(node_id) diff --git a/tests/api/test_network.py b/tests/api/test_network.py index b0ed1806..17db3cd4 100644 --- a/tests/api/test_network.py +++ b/tests/api/test_network.py @@ -34,7 +34,6 @@ import random import socket import re -import json import six if six.PY3: from pydispatch import dispatcher @@ -52,7 +51,7 @@ from tests.common import pyozw_version from tests.common import SLEEP from tests.api.common import TestApi -from tests.common import TestPyZWave +from tests.common import TestPyZWave, json_dumps, json_loads class TestNetwork(TestApi): @@ -82,14 +81,14 @@ def test_120_network_poll(self): def test_200_network_to_dict(self): dnetwork = self.network.to_dict() self.assertEqual(type(dnetwork), type(dict())) - res = json.dumps(dnetwork) + res = json_dumps(dnetwork) self.assertNotEqual(res, None) self.assertTrue(len(res)>0) def test_220_network_nodes_to_dict(self): dnodes = self.network.nodes_to_dict() self.assertEqual(type(dnodes), type(dict())) - res = json.dumps(dnodes) + res = json_dumps(dnodes) self.assertNotEqual(res, None) self.assertTrue(len(res)>0) diff --git a/tests/api/test_node.py b/tests/api/test_node.py index 3972dad7..9bd33f73 100644 --- a/tests/api/test_node.py +++ b/tests/api/test_node.py @@ -60,14 +60,19 @@ def test_020_node_capabilities(self): node_id = max(self.network.nodes.keys()) self.assertEqual(type(self.network.nodes[node_id].capabilities), type(set())) + def test_030_node_statistics(self): + node_id = max(self.network.nodes.keys()) + self.assertEqual(type(self.network.nodes[node_id].stats), type(dict())) + def test_310_node(self): node_id = max(self.network.nodes.keys()) self.assertTrue(isinstance(self.network.nodes[node_id].node_id, integer_types)) self.assertTrue(self.network.nodes[node_id].node_id > 0) def test_330_node_neighbors(self): - node_id = max(self.network.nodes.keys()) - self.assertEqual(type(self.network.nodes[node_id].neighbors), type(set())) + #~ node_id = max(self.network.nodes.keys()) + for node_id in self.active_nodes: + self.assertEqual(type(self.network.nodes[node_id].neighbors), type(set())) def test_340_node_baud_rate(self): node_id = max(self.network.nodes.keys()) diff --git a/tests/api/test_nodes.py b/tests/api/test_nodes.py index 9fba5ae7..9fe5baa1 100644 --- a/tests/api/test_nodes.py +++ b/tests/api/test_nodes.py @@ -34,7 +34,6 @@ import random import socket import re -import json import six if six.PY3: from pydispatch import dispatcher @@ -52,7 +51,7 @@ from tests.common import pyozw_version from tests.common import SLEEP from tests.api.common import TestApi -from tests.common import TestPyZWave +from tests.common import TestPyZWave, json_dumps, json_loads class TestNodes(TestApi): @@ -73,9 +72,13 @@ def test_110_nodes_heal(self): def test_200_nodes_to_dict(self): for node in self.active_nodes: try : - nodes = self.active_nodes[node].to_dict() - self.assertEqual(type(nodes), type(dict())) - res = json.dumps(nodes) + noded = self.active_nodes[node].to_dict() + self.assertEqual(type(noded), type(dict())) + self.assertTrue('values' in noded) + self.assertTrue('groups' in noded) + self.assertTrue('neighbors' in noded) + self.assertTrue('capabilities' in noded) + res = json_dumps(noded) except TypeError: res = None self.assertNotEqual(res, None) @@ -84,7 +87,7 @@ def test_210_controller_to_dict(self): try : nodes = self.network.controller.to_dict() self.assertEqual(type(nodes), type(dict())) - res = json.dumps(nodes) + res = json_dumps(nodes) except TypeError: res = None self.assertNotEqual(res, None) @@ -93,8 +96,9 @@ def test_220_nodes_groups_to_dict(self): for node in self.active_nodes: try : groups = self.active_nodes[node].groups_to_dict() + self.assertTrue(type(groups), type(dict())) self.assertEqual(type(groups), type(dict())) - res = json.dumps(groups) + res = json_dumps(groups) except TypeError: res = None self.assertNotEqual(res, None) diff --git a/tests/api/test_scene.py b/tests/api/test_scene.py index 45143f06..22f3229e 100644 --- a/tests/api/test_scene.py +++ b/tests/api/test_scene.py @@ -50,8 +50,7 @@ from tests.common import pyozw_version from tests.common import SLEEP from tests.api.common import TestApi -from tests.common import TestPyZWave -import json +from tests.common import TestPyZWave, json_dumps, json_loads class TestScene(TestApi): count = 0 @@ -83,7 +82,7 @@ def test_005_scene_add_remove(self): def test_010_scenes_to_dict(self): dscenes = self.network.scenes_to_dict() self.assertEqual(type(dscenes), type(dict())) - res = json.dumps(dscenes) + res = json_dumps(dscenes) self.assertNotEqual(res, None) self.assertTrue(len(res)>0) @@ -93,7 +92,7 @@ def test_020_scene_to_dict(self): try : scene = scenes[scene].to_dict() self.assertEqual(type(scene), type(dict())) - res = json.dumps(scene) + res = json_dumps(scene) except TypeError: res = None self.assertNotEqual(res, None) diff --git a/tests/api/test_switch.py b/tests/api/test_switch.py index 5b277fe7..697bfff4 100644 --- a/tests/api/test_switch.py +++ b/tests/api/test_switch.py @@ -26,7 +26,9 @@ """ -import os, shutil +import os +import shutil +import sys import time import unittest from pprint import pprint diff --git a/tests/api/test_value.py b/tests/api/test_value.py index ee9e8cd1..77c23192 100644 --- a/tests/api/test_value.py +++ b/tests/api/test_value.py @@ -53,8 +53,7 @@ from tests.common import pyozw_version from tests.common import SLEEP from tests.api.common import TestApi -from tests.common import TestPyZWave -import json +from tests.common import TestPyZWave, json_dumps, json_loads class TestValue(TestApi): @@ -62,11 +61,15 @@ def test_200_values_to_dict(self): for node in self.active_nodes: for value in self.active_nodes[node].values: val = self.active_nodes[node].values[value].to_dict() + print(val) self.assertEqual(type(val), type(dict())) - try : - res = json.dumps(val) - except TypeError: - res = None + self.assertTrue('data_items' in val) + self.assertTrue('command_class' in val) + self.assertTrue('is_read_only' in val) + self.assertTrue('is_write_only' in val) + self.assertTrue('type' in val) + self.assertTrue('index' in val) + res = json_dumps(val) self.assertNotEqual(res, None) def test_210_values_check_data(self): diff --git a/tests/common.py b/tests/common.py index 03c12ff7..badec123 100644 --- a/tests/common.py +++ b/tests/common.py @@ -25,19 +25,36 @@ """ -#The common sleep dealy to wait for network -#We wait 1*SLEEP for network.STATE_AWAKED -#After that we wait 1*SLEEP for network.STATE_READY -SLEEP = 45 - -import sys, os +import os +import shutil +import sys import time import unittest import threading import logging -import json as mjson +import json +#~ import bson import six +#The common sleep dealy to wait for network +#We wait 1*SLEEP for network.STATE_AWAKED +#After that we wait 1*SLEEP for network.STATE_READY +SLEEP = 45 + +class SetEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, set): + return list(obj) + return json.JSONEncoder.default(self, obj) + +def json_dumps(data_as_object): + #~ return json.dumps(data_as_object, default=json_util.default) + return json.dumps(data_as_object, cls=SetEncoder) + +def json_loads(data_as_string): + #~ return json.loads(data_as_string, object_hook=json_util.object_hook) + return json.loads(data_as_string) + from nose.plugins.skip import SkipTest sys.path.insert(1, os.path.abspath('..')) @@ -50,7 +67,7 @@ class TestPyZWave(unittest.TestCase): """ device = "/dev/ttyUSB0" ozwlog = "Debug" - ozwout = False + ozwout = True pylog = logging.DEBUG userpath = ".tests_user_path" @@ -75,6 +92,7 @@ def setUpClass(self): except: pass + @classmethod def skipTest(self, message): """Skip a test """ diff --git a/tests/lib/autobuild/test_lib.py b/tests/lib/autobuild/test_lib.py index 0436a4c5..e7e05eae 100644 --- a/tests/lib/autobuild/test_lib.py +++ b/tests/lib/autobuild/test_lib.py @@ -56,8 +56,14 @@ def test_010_options_exceptions(self): shutil.rmtree(self.userpath) except: pass - os.makedirs(self.userpath) - os.makedirs(fake_config_dir) + try: + os.makedirs(self.userpath) + except: + pass + try: + os.makedirs(fake_config_dir) + except: + pass os.chmod(fake_config_dir, stat.S_IREAD|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) with self.assertRaises(libopenzwave.LibZWaveException): options = libopenzwave.PyOptions(config_path=fake_config_dir, user_path=None, cmd_line=None) @@ -66,8 +72,14 @@ def test_010_options_exceptions(self): shutil.rmtree(self.userpath) except: pass - os.makedirs(self.userpath) - os.makedirs(fake_config_dir) + try: + os.makedirs(self.userpath) + except: + pass + try: + os.makedirs(fake_config_dir) + except: + pass os.chmod(fake_config_dir, stat.S_IREAD|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWRITE|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) with self.assertRaises(libopenzwave.LibZWaveException): options = libopenzwave.PyOptions(config_path=fake_config_dir, user_path=None, cmd_line=None) diff --git a/tests/lib/common.py b/tests/lib/common.py index d5277d4c..2f10f621 100644 --- a/tests/lib/common.py +++ b/tests/lib/common.py @@ -30,7 +30,6 @@ import unittest import threading import logging -import json as mjson import shutil from nose.plugins.skip import SkipTest @@ -115,7 +114,6 @@ def tearDownClass(self): super(TestPyZWave, self).tearDownClass() def start_lib(self): - if self.options is None: self.options = libopenzwave.PyOptions(config_path="openzwave/config", \ user_path=self.userpath, cmd_line="--logging false") @@ -142,15 +140,19 @@ def start_lib(self): @classmethod def stop_lib(self): if self.manager is not None: + print("Remove driver") self.manager.removeDriver(self.device) - time.sleep(1.0) + time.sleep(2.0) + print("Remove watcher") self.manager.removeWatcher(self.zwcallback) - time.sleep(1.0) + time.sleep(2.0) + print("Destroy manager") self.manager.destroy() time.sleep(1.0) self.manager = None if self.options is not None: self.options.destroy() + print("Destroy options") time.sleep(1.0) self.options = None self.homeid = None @@ -238,11 +240,12 @@ def zwcallback(self, args): print('Error in manager callback : %s' % traceback.format_exception(*sys.exc_info())) def wait_for_ready(self): - for i in range(0,15): + for i in range(0,20): if self.ready == True: break else: time.sleep(1.0) + print("Network ready : %s"%self.ready) def wait_for_queue(self): for i in range(0,60): diff --git a/tests/lib/test_driver.py b/tests/lib/test_driver.py index c3e2de74..087033cd 100644 --- a/tests/lib/test_driver.py +++ b/tests/lib/test_driver.py @@ -34,7 +34,7 @@ import random import socket import libopenzwave -from common import TestLib +from .common import TestLib import re from tests.common import pyozw_version from six import string_types @@ -55,9 +55,6 @@ def setUp(self): user_path=self.userpath, cmd_line="--logging false") self.options.lock() - def tearDown(self): - self.stop_lib() - def test_100_start(self): time.sleep(1.0) self.manager = libopenzwave.PyManager() diff --git a/tests/lib/test_node.py b/tests/lib/test_node.py index df93cebd..b7b504fc 100644 --- a/tests/lib/test_node.py +++ b/tests/lib/test_node.py @@ -33,7 +33,7 @@ import datetime import random import socket -from common import TestLib +from .common import TestLib import re from tests.common import pyozw_version from six import string_types @@ -50,10 +50,11 @@ def emit(self, record): class TestNode(TestLib): - - def test_100_controller_name(self): + def setUp(self): self.start_lib() self.wait_for_ready() + + def skip_100_controller_name(self): oldname = self.manager.getNodeName(self.homeid, 1) self.assertTrue(isinstance(oldname, string_types)) self.manager.setNodeName(self.homeid, 1, "test lib name") @@ -61,8 +62,6 @@ def test_100_controller_name(self): self.assertTrue(isinstance(newname, string_types)) def test_101_controller_name_accent(self): - self.start_lib() - self.wait_for_ready() oldname = self.manager.getNodeName(self.homeid, 1) self.assertTrue(isinstance(oldname, string_types)) self.manager.setNodeName(self.homeid, 1, "test lib name éé") diff --git a/tests/manager/autobuild/test_manager.py b/tests/manager/autobuild/test_manager.py index e81e1185..d8568016 100644 --- a/tests/manager/autobuild/test_manager.py +++ b/tests/manager/autobuild/test_manager.py @@ -32,7 +32,7 @@ import sys import time import logging -import json as mjson +import unittest from tests.manager.common import TestManager diff --git a/tests/manager/common.py b/tests/manager/common.py index 89356f06..926cee57 100644 --- a/tests/manager/common.py +++ b/tests/manager/common.py @@ -29,7 +29,6 @@ import sys, os import time import logging -import json as mjson from tests.common import SLEEP from tests.common import TestPyZWave diff --git a/tests/web/autobuild/test_web.py b/tests/web/autobuild/test_web.py index ddfa4f8d..52488258 100644 --- a/tests/web/autobuild/test_web.py +++ b/tests/web/autobuild/test_web.py @@ -32,16 +32,16 @@ import sys import time import logging -import json as mjson +import unittest -from tests.web.common import FlaskTestBase +#~ from tests.web.common import FlaskTestBase -class FlaskTest(FlaskTestBase): +#~ class FlaskTest(FlaskTestBase): - def test_000_import_listener(self): - self.skipPython3() - from pyozwweb.app.listener import ListenerThread, start_listener, stop_listener - from pyozwweb.app import run_app, create_app + #~ def test_000_import_listener(self): + #~ self.skipPython3() + #~ from pyozwweb.app.listener import ListenerThread, start_listener, stop_listener + #~ from pyozwweb.app import run_app, create_app if __name__ == '__main__': sys.argv.append('-v') diff --git a/tests/web/common.py b/tests/web/common.py index 655f54bd..bb869546 100644 --- a/tests/web/common.py +++ b/tests/web/common.py @@ -29,7 +29,6 @@ import sys, os import time import logging -import json as mjson from flask import Flask diff --git a/tests/web/test_server.py b/tests/web/test_server.py index 1ada13f4..b5833cfe 100644 --- a/tests/web/test_server.py +++ b/tests/web/test_server.py @@ -32,49 +32,49 @@ import sys import time import logging -import json as mjson +import unittest -from flask.ext.socketio import SocketIO, emit, join_room, leave_room, close_room, disconnect -from flask.ext.socketio.test_client import SocketIOTestClient -from tests.web.common import FlaskTestCase +#~ from flask.ext.socketio import SocketIO, emit, join_room, leave_room, close_room, disconnect +#~ from flask.ext.socketio.test_client import SocketIOTestClient +#~ from tests.web.common import FlaskTestCase -class FlaskServerTest(FlaskTestCase): +#~ class FlaskServerTest(FlaskTestCase): - def test_000_server_start(self): - rv = self.client.get('/') - self.assertTrue('Welcome to PyOzwWeb' in rv.data) + #~ def test_000_server_start(self): + #~ rv = self.client.get('/') + #~ self.assertTrue('Welcome to PyOzwWeb' in rv.data) - def test_001_error_404(self): - rv = self.client.get('/bad_page') - self.assertEqual(rv.status,'404 NOT FOUND') + #~ def test_001_error_404(self): + #~ rv = self.client.get('/bad_page') + #~ self.assertEqual(rv.status,'404 NOT FOUND') - def test_100_home_is_up(self): - rv = self.client.get('/') - self.assertEqual(rv.status,'200 OK') + #~ def test_100_home_is_up(self): + #~ rv = self.client.get('/') + #~ self.assertEqual(rv.status,'200 OK') - def test_200_controller_is_up(self): - rv = self.client.get('/controller') - self.assertEqual(rv.status,'200 OK') + #~ def test_200_controller_is_up(self): + #~ rv = self.client.get('/controller') + #~ self.assertEqual(rv.status,'200 OK') - def test_300_values_is_up(self): - rv = self.client.get('/values') - self.assertEqual(rv.status,'200 OK') + #~ def test_300_values_is_up(self): + #~ rv = self.client.get('/values') + #~ self.assertEqual(rv.status,'200 OK') - def test_400_controller_is_up(self): - rv = self.client.get('/debug') - self.assertEqual(rv.status,'200 OK') + #~ def test_400_controller_is_up(self): + #~ rv = self.client.get('/debug') + #~ self.assertEqual(rv.status,'200 OK') - def test_500_node_is_up(self): - rv = self.client.get('/node/1') - self.assertEqual(rv.status,'200 OK') + #~ def test_500_node_is_up(self): + #~ rv = self.client.get('/node/1') + #~ self.assertEqual(rv.status,'200 OK') - def test_600_map_is_up(self): - rv = self.client.get('/map') - self.assertEqual(rv.status,'200 OK') + #~ def test_600_map_is_up(self): + #~ rv = self.client.get('/map') + #~ self.assertEqual(rv.status,'200 OK') - def test_700_scenes_is_up(self): - rv = self.client.get('/scenes') - self.assertEqual(rv.status,'200 OK') + #~ def test_700_scenes_is_up(self): + #~ rv = self.client.get('/scenes') + #~ self.assertEqual(rv.status,'200 OK') #def test_500_socketio_home(self): # rv = self.app.get('/socketio/')