diff --git a/README.rst b/README.rst index a500188..c7ada83 100644 --- a/README.rst +++ b/README.rst @@ -19,18 +19,124 @@ pySonoffLAN :alt: Updates +Control Sonoff devices running original firmware, in LAN mode. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Interface for Sonoff devices running original Itead firmware, in LAN mode. +This module provides a way to interface with Sonoff smart home devices, +such as smart switches (e.g. Sonoff Basic), plugs (e.g. Sonoff S20), +and wall switches (e.g. Sonoff Touch), when these devices are in LAN Mode. +LAN Mode is a feature introduced by manufacturer Itead, to allow operation +locally when their servers are unavailable. +Further details can be found in the `eWeLink LAN Mode guide`__. + +__ https://help.ewelink.cc/hc/en-us/articles/360007134171-LAN-Mode-Tutorial + +Since mid 2018, the firmware Itead have shipped with most Sonoff devices +has provided this feature, allowing devices to be controlled directly +on the local network using a WebSocket connection on port 8081. + +The feature is designed to only be used when there is no connection +to the Itead cloud servers, (e.g. if your internet connection is down, +or their servers are down). +As such, it is only enabled when the device is connected to your WiFi +network, but *unable to reach the Itead servers*. + +Most users will only be able to use this by **deliberately +blocking internet access** to their Sonoff devices. * Free software: MIT license * Documentation: https://pysonofflan.readthedocs.io. - Features -------- -* TODO +* Discover all devices on local network (192.168.0.0/24, 192.168.1.0/24) +* Discover IP address for device with known Device ID (from eWeLink app) +* Read device state +* Switch device ON/OFF +* Listen for state changes announced by the device (e.g. by physical switch) +* Activate inching/momentary device, with variable ON time (e.g. 1s) + +Command-Line Usage +------------------ +:: + + Usage: pysonofflan [OPTIONS] COMMAND [ARGS]... + + A cli tool for controlling Sonoff Smart Switches/Plugs in LAN Mode. + + Options: + --host TEXT IP address or hostname of the device to connect to. + --device_id TEXT Device ID of the device to connect to. + --inching TEXT Number of seconds of "on" time if this is an + Inching/Momentary switch. + -v, --verbosity LVL Either CRITICAL, ERROR, WARNING, INFO or DEBUG + --help Show this message and exit. + + Commands: + discover Discover devices in the network (takes ~1... + listen Connect to device, print state, then print... + off Turn the device off. + on Turn the device on. + state Connect to device and print current state. + +Install / Usage Example +======================= +:: + + $ pip install pysonofflan + + $ pysonofflan discover + 2019-01-31 00:45:32,074 - info: Attempting to discover Sonoff LAN Mode devices on the local network, please wait... + 2019-01-31 00:46:24,007 - info: Found Sonoff LAN Mode device at IP 192.168.0.77 + + $ pysonofflan --host 192.168.0.77 state + 2019-01-31 00:41:34,931 - info: Initialising SonoffSwitch with host 192.168.0.77 + 2019-01-31 00:41:35,016 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:41:35,016 - info: State: OFF + + $ pysonofflan --host 192.168.0.77 on + 2019-01-31 00:49:40,334 - info: Initialising SonoffSwitch with host 192.168.0.77 + 2019-01-31 00:49:40,508 - info: + 2019-01-31 00:49:40,508 - info: Initial state: + 2019-01-31 00:49:40,508 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:49:40,508 - info: State: OFF + 2019-01-31 00:49:40,508 - info: + 2019-01-31 00:49:40,508 - info: New state: + 2019-01-31 00:49:40,508 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:49:40,508 - info: State: ON + +Library Usage +------------------ + +All common, shared functionality is available through :code:`SonoffSwitch` class:: + + x = SonoffSwitch("192.168.1.50") + +Upon instantiating the SonoffSwitch class, a connection is +initiated and device state is populated, but no further action is taken. + +For most use cases, you'll want to make use of the :code:`callback_after_update` +parameter to do something with the device after a connection has been +initialised, for example:: + + async def print_state_callback(device): + if device.basic_info is not None: + print("ON" if device.is_on else "OFF") + device.shutdown_event_loop() + + SonoffSwitch( + host="192.168.1.50", + callback_after_update=print_state_callback + ) + +This example simply connects to the device, prints whether it is currently +"ON" or "OFF", then closes the connection. Note, the callback must be +asynchronous. + +Module-specific errors are raised as Exceptions, and are expected +to be handled by the user of the library. Credits ------- diff --git a/docs/usage.rst b/docs/usage.rst index 5bb5e29..0720290 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -2,6 +2,87 @@ Usage ===== +Command-Line Usage +------------------ +:: + + Usage: pysonofflan [OPTIONS] COMMAND [ARGS]... + + A cli tool for controlling Sonoff Smart Switches/Plugs in LAN Mode. + + Options: + --host TEXT IP address or hostname of the device to connect to. + --device_id TEXT Device ID of the device to connect to. + --inching TEXT Number of seconds of "on" time if this is an + Inching/Momentary switch. + -v, --verbosity LVL Either CRITICAL, ERROR, WARNING, INFO or DEBUG + --help Show this message and exit. + + Commands: + discover Discover devices in the network (takes ~1... + listen Connect to device, print state, then print... + off Turn the device off. + on Turn the device on. + state Connect to device and print current state. + +Install / Usage Example +======================= +:: + + $ pip install pysonofflan + + $ pysonofflan discover + 2019-01-31 00:45:32,074 - info: Attempting to discover Sonoff LAN Mode devices on the local network, please wait... + 2019-01-31 00:46:24,007 - info: Found Sonoff LAN Mode device at IP 192.168.0.77 + + $ pysonofflan --host 192.168.0.77 state + 2019-01-31 00:41:34,931 - info: Initialising SonoffSwitch with host 192.168.0.77 + 2019-01-31 00:41:35,016 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:41:35,016 - info: State: OFF + + $ pysonofflan --host 192.168.0.77 on + 2019-01-31 00:49:40,334 - info: Initialising SonoffSwitch with host 192.168.0.77 + 2019-01-31 00:49:40,508 - info: + 2019-01-31 00:49:40,508 - info: Initial state: + 2019-01-31 00:49:40,508 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:49:40,508 - info: State: OFF + 2019-01-31 00:49:40,508 - info: + 2019-01-31 00:49:40,508 - info: New state: + 2019-01-31 00:49:40,508 - info: == Device: 10006866e9 (192.168.0.77) == + 2019-01-31 00:49:40,508 - info: State: ON + +Library Usage +------------------ + To use pySonoffLAN in a project:: import pysonofflan + + +All common, shared functionality is available through :code:`SonoffSwitch` class:: + + x = SonoffSwitch("192.168.1.50") + +Upon instantiating the SonoffSwitch class, a connection is +initiated and device state is populated, but no further action is taken. + +For most use cases, you'll want to make use of the :code:`callback_after_update` +parameter to do something with the device after a connection has been +initialised, for example:: + + async def print_state_callback(device): + if device.basic_info is not None: + print("ON" if device.is_on else "OFF") + device.shutdown_event_loop() + + SonoffSwitch( + host="192.168.1.50", + callback_after_update=print_state_callback + ) + +This example simply connects to the device, prints whether it is currently +"ON" or "OFF", then closes the connection. Note, the callback must be +asynchronous. + +Module-specific errors are raised as Exceptions, and are expected +to be handled by the user of the library. diff --git a/pysonofflan/__init__.py b/pysonofflan/__init__.py index ee0feef..f4f5503 100644 --- a/pysonofflan/__init__.py +++ b/pysonofflan/__init__.py @@ -25,10 +25,24 @@ All common, shared functionality is available through `SonoffDevice` class: - x = SonoffDevice("192.168.1.1") - print(x.sys_info) + x = SonoffSwitch("192.168.1.50") -For device type specific actions `SonoffSwitch` must be used instead. +Upon instantiating the SonoffSwitch class, a connection is +initiated and device state is populated, but no further action is taken. + +For most use cases, you'll want to make use of the `callback_after_update` +parameter to send a command to the device after a connection has been +initialised, for example: + + async def state_callback(device): + if device.basic_info is not None: + print("ON" if device.is_on else "OFF") + device.shutdown_event_loop() + + SonoffSwitch( + host="192.168.1.50", + callback_after_update=state_callback + ) Module-specific errors are raised as Exceptions and are expected to be handled by the user of the library. @@ -37,6 +51,7 @@ __author__ = """Andrew Beveridge""" __email__ = 'andrew@beveridge.uk' __version__ = '0.1.0' +__url__ = 'https://github.com/beveradb/pysonofflan' # flake8: noqa from .client import SonoffLANModeClient