diff options
Diffstat (limited to 'python-motionblinds.spec')
| -rw-r--r-- | python-motionblinds.spec | 982 |
1 files changed, 982 insertions, 0 deletions
diff --git a/python-motionblinds.spec b/python-motionblinds.spec new file mode 100644 index 0000000..f6ca66d --- /dev/null +++ b/python-motionblinds.spec @@ -0,0 +1,982 @@ +%global _empty_manifest_terminate_build 0 +Name: python-motionblinds +Version: 0.6.17 +Release: 1 +Summary: Python library for interfacing with Motion Blinds +License: MIT +URL: https://github.com/starkillerOG/motion-blinds +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/78/1a/abd4896ecbdce29c3d42db0ec54eecb7b3ed936fa251df35c1ebf072b778/motionblinds-0.6.17.tar.gz +BuildArch: noarch + +Requires: python3-pycryptodomex + +%description +# motion-blinds +Python library for interfacing with Motion Blinds + +This library allows you to control Motion Blinds from Coulisse B.V. +This library is primarly writen to be used with HomeAssistant but can also be used stand alone. + +[](https://github.com/sponsors/starkillerOG) + +For products see https://motion-blinds.com or https://coulisse.com/products/motion. + +Shops that sell these blinds: +- [Hornbach](https://www.hornbach.nl/) +- [Smart Blinds](https://www.smartblinds.nl/) + +## Other brands of blinds +This python library is primarly written for the Motion Blinds, but some other manufacturers use the same API and therefore this library also works with those brands. +The following brands have been reported to also work with this python library: +- [Motion Blinds](https://motionblinds.com/) +- [Smart Blinds](https://www.smartblinds.nl/) +- [Dooya](http://www.dooya.com/) +- [Brel Home](https://www.brel-home.nl/) +- [Bloc Blinds](https://www.blocblinds.com/) +- [AMP Motorization](https://www.ampmotorization.com/) +- [Bliss Automation - Alta Window Fashions](https://www.altawindowfashions.com/product/automation/bliss-automation/) +- [3 Day Blinds](https://www.3dayblinds.com/) +- [Diaz](https://www.diaz.be/en/) +- [Gaviota](https://www.gaviotagroup.com/en/) +- [Havana Shade](https://havanashade.com/) +- [Hurrican Shutters Wholesale](https://www.hurricaneshutterswholesale.com/) +- [Inspired Shades](https://www.inspired-shades.com/) +- [iSmartWindow](https://www.ismartwindow.co.nz/) +- [Martec](https://www.martec.co.nz/) +- [Raven Rock MFG](https://www.ravenrockmfg.com/) +- [ScreenAway](https://www.screenaway.com.au/) +- [Smart Home](https://www.smart-home.hu) +- [Uprise Smart Shades](http://uprisesmartshades.com) + +## Installation + +Use pip: + +```$ pip install motionblinds``` + +or + +```$ pip install --use-wheel motionblinds``` + +## Retrieving Key +The Motion Blinds API uses a 16 character key that can be retrieved from the official "Motion Blinds" app for [Ios](https://apps.apple.com/us/app/motion-blinds/id1437234324) or [Android](https://play.google.com/store/apps/details?id=com.coulisse.motion). +Open the app, click the 3 dots in the top right corner, go to "settings", go to "Motion APP About", Please quickly tap this "Motion APP About" page 5 times, a popup will apear that gives you the key. + + + + +Please note that "-" characters need to be included in the key when providing it to this library. +The key needs to be simular to "12ab345c-d67e-8f" + +## Usage + +For creation of a device you could use the following lines of codes (using a correct IP of the gateway and Key retrieved from the App) +``` +from motionblinds import MotionGateway +m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +``` +This library is not polling. Thus you need to populate the connected blinds using the GetDeviceList method and update device information using the Update method. +Note that multicast pushes from the gateway can be processed to retrieve instant status updates (see Multicast pushes section) +``` +m.GetDeviceList() +m.Update() +``` +Note that GetDeviceList needs to be run before using Update since the device_type, mac and token are retrieved using the GetDeviceList method. +Once the connected blinds are discoverd using the GetDeviceList method, they can be listed by the device_list property: +``` +m.device_list +``` +This will return a dict with as key the mac_adress of the blind and as value a MotionBlind device that can be used to retreive information of that blind and control that blind. + +Some example code that will print the information of the gateway and all conected blinds: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +{'abcdefghujkl0001': <MotionBlind mac: abcdefghujkl0001, type: None, status: None, position: None %, angle: None, limit: None, battery: None, RSSI: None dBm>} +>>> m.Update() +>>> print(m) +<MotionGateway ip: 192.168.1.100, mac: abcdefghujkl, protocol: 0.9, N_devices: 1, status: Working, RSSI: -71 dBm> +>>> for blind in m.device_list.values(): +>>> blind.Update() +>>> print(blind) +<MotionBlind mac: abcdefghujkl0001, type: RollerBlind, status: Stopped, position: 0 %, angle: 0, limit: Limits, battery: 1195, RSSI: -82 dBm> +``` + +To open a blind the following example code can be used: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +>>> m.Update() +>>> blind_1 = list(m.device_list.values())[0] +>>> blind_1.Update() +>>> blind_1.Open() +``` +Instead of blind_1.Open() you can also use blind_1.Close(), blind_1.Stop(), blind_1.Set_position(50) or blind_1.Set_angle(90) + +## Multicast pushes +This library allows to listen for multicast pushes from the gateway (in a parallel thread or using asyncio) and process these pushes to get instant updates of the gateway and connected blinds status. +To use this parallel pushes processing a MotionMulticast/AsyncMotionMulticast class object needs to be initilized. +The MotionMulticast.Start_listen()/AsyncMotionMulticast.Start_listen() and MotionMulticast.Stop_listen()/AsyncMotionMulticast.Stop_listen() can then be used to start and stop the parallel thread that is listening for incoming pushes. +The MotionMulticast/AsyncMotionMulticast class object can be supplied to the MotionGateway class to let it update that gateway and its connected blinds. +Externall callbacks can be registered for both gateway devices and blind devices (see tables below) +If UDP multicast messages are not coming through, try using the IP adress of the host running the code as the interface instead of "any". +### Parallel thread +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using a parallel thread: +``` +import time +from motionblinds import MotionMulticast, MotionGateway + +def callback_func_gateway(): + print(m) + +def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + +motion_multicast = MotionMulticast(interface = "any") +motion_multicast.Start_listen() + +m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) +m.GetDeviceList() +m.Update() + +m.Register_callback("1", callback_func_gateway) +for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + +time.sleep(30) + +motion_multicast.Stop_listen() +``` +### Asyncio +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using asyncio: +``` +import asyncio +from motionblinds import AsyncMotionMulticast, MotionGateway + +async def asyncio_demo(loop): + def callback_func_gateway(): + print(m) + + def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + + motion_multicast = AsyncMotionMulticast(interface = "any") + await motion_multicast.Start_listen() + + m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) + await loop.run_in_executor(None, m.GetDeviceList) + await loop.run_in_executor(None, m.Update) + + m.Register_callback("1", callback_func_gateway) + for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + + await asyncio.sleep(30) + + motion_multicast.Stop_listen() + +if __name__ == "__main__": + loop = asyncio.get_event_loop() + loop.run_until_complete(asyncio_demo(loop)) +``` + +## Discovery +Motion Gateways can be discovered on your network using the MotionDiscovery class. +The following example will try to discover gateways for 10 seconds and then print a dict containg the gateways and their connected blinds that were discovered. + +``` +>>> from motionblinds import MotionDiscovery +>>> d = MotionDiscovery() +>>> motion_gateways = d.discover() +>>> print(motion_gateways) + +{'192.168.1.100': { + 'msgType': 'GetDeviceListAck', + 'mac': 'abcdefghujkl', + 'deviceType': '02000002', + 'ProtocolVersion': '0.9', + 'token': '12345A678B9CDEFG', + 'data': [ + {'mac': 'abcdefghujkl', 'deviceType': '02000002'}, + {'mac': 'abcdefghujkl0001', 'deviceType': '10000000'}, + {'mac': 'abcdefghujkl0002', 'deviceType': '10000000'} + ] +}} +``` + +## Gateway device +A gateway device (that was asigned to variable 'm') has the following methods and properties: + +| method | arguments | argument type | explanation | +| ------------------------------- | ------------ | ---------------- | ---------------------------------------------------------------------------------- | +| "m.GetDeviceList()" | - | - | Get the device list from the Motion Gateway and update the properties listed below | +| "m.Update()" | - | - | Get the status of the Motion Gateway and update the properties listed below | +| "m.Check_gateway_multicast()" | - | - | Check if multicast messages can be received with the configured multicast listener | +| "m.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the gateway | +| "m.Remove_callback("1") | id | string | Remove a external callback using its id | +| "m.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the gateway | + +| property | value type | explanation | +| ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| "m.available" | boolean | Return if the gateway is available | +| "m.status" | string | Return gateway status: from GatewayStatus enum | +| "m.N_devices" | int | Return the number of connected child devices | +| "m.RSSI" | int | Return the Wi-Fi connection strength of the gateway in dBm | +| "m.token" | string | Return the Token | +| "m.access_token" | string | Return the AccessToken | +| "m.mac" | string | Return the mac address of the gateway | +| "m.device_type" | string | Return the device type of the gateway | +| "m.protocol" | string | Return the protocol version of the gateway | +| "m.firmware" | string | Return the firmware version of the gateway | +| "m.device_list" | dict | Return a dict containing all blinds connected to the gateway, The keys in the dict are the mac adresses of the blinds. | + +## Blind device +A blind device (that was asigned to variable 'blind_1') has the following methods and properties, arguments between () are optional: + +| method | arguments | argument type | explanation | +| ------------------------------------- | --------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| "blind_1.Update_from_cache()" | - | - | Get the status of the blind from the cache of the Motion Gateway, No 433MHz radio communication with the blind takes place | +| "blind_1.Update_trigger()" | - | - | Get the status of the blind from the cache of the Motion Gateway and request a 433MHz radio communication with the blind for a new status (not awaited) | +| "blind_1.Update()" | - | - | Get the status of the blind from the blind through the Motion Gateway (WiFi) using 433MHz radio communication between the gateway and the blind | +| "blind_1.Stop()" | - | - | Stop the motion of the blind | +| "blind_1.Open()" | - | - | Open the blind/move the blind up | +| "blind_1.Close()" | - | - | Close the blind/move the blind down | +| "blind_1.Set_position(50)" | postion, (angle), (restore_angle) | int (0-100), int (0-180), boolean | Set the position of the blind, optionaly set angle or restore current angle | +| "blind_1.Set_angle(90)" | angle | int (0-180) | Set the angle/rotation of the blind | +| "blind_1.Jog_up()" | - | - | Open the blind/move the blind one step up | +| "blind_1.Jog_down()" | - | - | Close the blind/move the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | ---------- | ----------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | string | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | string | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | int | Return the current position of the blind in % (0-100) | +| "blind_1.angle" | int | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | double | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | double | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + +## Top Down Bottom Up (TDBU) device +A TDBU blind device has two motors designated by "T" = Top and "B" = Bottom to control the two parts of the blind. +Both parts can be controlled together using "C" = Combined as the motor. +The TDBU device (that was asigned to variable 'blind_1') has the following methods and properties: + +| method | arguments | argument type | explanation | +| --------------------------------------------------- | ---------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------- | +| "blind_1.Update()" | - | - | Get the status of the blind from the Motion Gateway | +| "blind_1.Stop(motor = 'B')" | motor | 'B', 'T' or 'C' | Stop the motion of Bottom or Top motor of the blind | +| "blind_1.Open(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind up | +| "blind_1.Close(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind down | +| "blind_1.Set_position(50, motor = 'B', width = 20)" | position, motor, width | int (0-100), 'B', 'T' or 'C', int (0-100) | Set the position of the Bottom or Top motor of the blind, optionaly specify width | +| "blind_1.Set_scaled_position(50, motor = 'B')" | position, motor | int (0-100), 'B', 'T' or 'C' | Set the position of the motor of the blind within the alowed space in which it can move | +| "blind_1.Set_angle(90, motor = 'B')" | angle, motor | int (0-180), 'B', 'T' or 'C' | Set the angle/rotation of the Bottom or Top motor of the blind | +| "blind_1.Jog_up(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step up | +| "blind_1.Jog_down(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | {"T": string, "B": string} | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | {"T": string, "B": string} | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | {"T": int, "B": int, "C": double} | Return the current position of the blind in % (0-100) | +| "blind_1.scaled_position" | {"T": double, "B": double, "C": double} | Return the current position of the blind, scaled to the alowed space in which it can move, in % (0-100) | +| "blind_1.width" | int | Return the area that is covered by the blind in % (0-100) | +| "blind_1.angle" | {"T": int, "B": int} | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | {"T": double, "B": double} | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | {"T": double, "B": double} | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + + +%package -n python3-motionblinds +Summary: Python library for interfacing with Motion Blinds +Provides: python-motionblinds +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-motionblinds +# motion-blinds +Python library for interfacing with Motion Blinds + +This library allows you to control Motion Blinds from Coulisse B.V. +This library is primarly writen to be used with HomeAssistant but can also be used stand alone. + +[](https://github.com/sponsors/starkillerOG) + +For products see https://motion-blinds.com or https://coulisse.com/products/motion. + +Shops that sell these blinds: +- [Hornbach](https://www.hornbach.nl/) +- [Smart Blinds](https://www.smartblinds.nl/) + +## Other brands of blinds +This python library is primarly written for the Motion Blinds, but some other manufacturers use the same API and therefore this library also works with those brands. +The following brands have been reported to also work with this python library: +- [Motion Blinds](https://motionblinds.com/) +- [Smart Blinds](https://www.smartblinds.nl/) +- [Dooya](http://www.dooya.com/) +- [Brel Home](https://www.brel-home.nl/) +- [Bloc Blinds](https://www.blocblinds.com/) +- [AMP Motorization](https://www.ampmotorization.com/) +- [Bliss Automation - Alta Window Fashions](https://www.altawindowfashions.com/product/automation/bliss-automation/) +- [3 Day Blinds](https://www.3dayblinds.com/) +- [Diaz](https://www.diaz.be/en/) +- [Gaviota](https://www.gaviotagroup.com/en/) +- [Havana Shade](https://havanashade.com/) +- [Hurrican Shutters Wholesale](https://www.hurricaneshutterswholesale.com/) +- [Inspired Shades](https://www.inspired-shades.com/) +- [iSmartWindow](https://www.ismartwindow.co.nz/) +- [Martec](https://www.martec.co.nz/) +- [Raven Rock MFG](https://www.ravenrockmfg.com/) +- [ScreenAway](https://www.screenaway.com.au/) +- [Smart Home](https://www.smart-home.hu) +- [Uprise Smart Shades](http://uprisesmartshades.com) + +## Installation + +Use pip: + +```$ pip install motionblinds``` + +or + +```$ pip install --use-wheel motionblinds``` + +## Retrieving Key +The Motion Blinds API uses a 16 character key that can be retrieved from the official "Motion Blinds" app for [Ios](https://apps.apple.com/us/app/motion-blinds/id1437234324) or [Android](https://play.google.com/store/apps/details?id=com.coulisse.motion). +Open the app, click the 3 dots in the top right corner, go to "settings", go to "Motion APP About", Please quickly tap this "Motion APP About" page 5 times, a popup will apear that gives you the key. + + + + +Please note that "-" characters need to be included in the key when providing it to this library. +The key needs to be simular to "12ab345c-d67e-8f" + +## Usage + +For creation of a device you could use the following lines of codes (using a correct IP of the gateway and Key retrieved from the App) +``` +from motionblinds import MotionGateway +m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +``` +This library is not polling. Thus you need to populate the connected blinds using the GetDeviceList method and update device information using the Update method. +Note that multicast pushes from the gateway can be processed to retrieve instant status updates (see Multicast pushes section) +``` +m.GetDeviceList() +m.Update() +``` +Note that GetDeviceList needs to be run before using Update since the device_type, mac and token are retrieved using the GetDeviceList method. +Once the connected blinds are discoverd using the GetDeviceList method, they can be listed by the device_list property: +``` +m.device_list +``` +This will return a dict with as key the mac_adress of the blind and as value a MotionBlind device that can be used to retreive information of that blind and control that blind. + +Some example code that will print the information of the gateway and all conected blinds: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +{'abcdefghujkl0001': <MotionBlind mac: abcdefghujkl0001, type: None, status: None, position: None %, angle: None, limit: None, battery: None, RSSI: None dBm>} +>>> m.Update() +>>> print(m) +<MotionGateway ip: 192.168.1.100, mac: abcdefghujkl, protocol: 0.9, N_devices: 1, status: Working, RSSI: -71 dBm> +>>> for blind in m.device_list.values(): +>>> blind.Update() +>>> print(blind) +<MotionBlind mac: abcdefghujkl0001, type: RollerBlind, status: Stopped, position: 0 %, angle: 0, limit: Limits, battery: 1195, RSSI: -82 dBm> +``` + +To open a blind the following example code can be used: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +>>> m.Update() +>>> blind_1 = list(m.device_list.values())[0] +>>> blind_1.Update() +>>> blind_1.Open() +``` +Instead of blind_1.Open() you can also use blind_1.Close(), blind_1.Stop(), blind_1.Set_position(50) or blind_1.Set_angle(90) + +## Multicast pushes +This library allows to listen for multicast pushes from the gateway (in a parallel thread or using asyncio) and process these pushes to get instant updates of the gateway and connected blinds status. +To use this parallel pushes processing a MotionMulticast/AsyncMotionMulticast class object needs to be initilized. +The MotionMulticast.Start_listen()/AsyncMotionMulticast.Start_listen() and MotionMulticast.Stop_listen()/AsyncMotionMulticast.Stop_listen() can then be used to start and stop the parallel thread that is listening for incoming pushes. +The MotionMulticast/AsyncMotionMulticast class object can be supplied to the MotionGateway class to let it update that gateway and its connected blinds. +Externall callbacks can be registered for both gateway devices and blind devices (see tables below) +If UDP multicast messages are not coming through, try using the IP adress of the host running the code as the interface instead of "any". +### Parallel thread +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using a parallel thread: +``` +import time +from motionblinds import MotionMulticast, MotionGateway + +def callback_func_gateway(): + print(m) + +def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + +motion_multicast = MotionMulticast(interface = "any") +motion_multicast.Start_listen() + +m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) +m.GetDeviceList() +m.Update() + +m.Register_callback("1", callback_func_gateway) +for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + +time.sleep(30) + +motion_multicast.Stop_listen() +``` +### Asyncio +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using asyncio: +``` +import asyncio +from motionblinds import AsyncMotionMulticast, MotionGateway + +async def asyncio_demo(loop): + def callback_func_gateway(): + print(m) + + def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + + motion_multicast = AsyncMotionMulticast(interface = "any") + await motion_multicast.Start_listen() + + m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) + await loop.run_in_executor(None, m.GetDeviceList) + await loop.run_in_executor(None, m.Update) + + m.Register_callback("1", callback_func_gateway) + for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + + await asyncio.sleep(30) + + motion_multicast.Stop_listen() + +if __name__ == "__main__": + loop = asyncio.get_event_loop() + loop.run_until_complete(asyncio_demo(loop)) +``` + +## Discovery +Motion Gateways can be discovered on your network using the MotionDiscovery class. +The following example will try to discover gateways for 10 seconds and then print a dict containg the gateways and their connected blinds that were discovered. + +``` +>>> from motionblinds import MotionDiscovery +>>> d = MotionDiscovery() +>>> motion_gateways = d.discover() +>>> print(motion_gateways) + +{'192.168.1.100': { + 'msgType': 'GetDeviceListAck', + 'mac': 'abcdefghujkl', + 'deviceType': '02000002', + 'ProtocolVersion': '0.9', + 'token': '12345A678B9CDEFG', + 'data': [ + {'mac': 'abcdefghujkl', 'deviceType': '02000002'}, + {'mac': 'abcdefghujkl0001', 'deviceType': '10000000'}, + {'mac': 'abcdefghujkl0002', 'deviceType': '10000000'} + ] +}} +``` + +## Gateway device +A gateway device (that was asigned to variable 'm') has the following methods and properties: + +| method | arguments | argument type | explanation | +| ------------------------------- | ------------ | ---------------- | ---------------------------------------------------------------------------------- | +| "m.GetDeviceList()" | - | - | Get the device list from the Motion Gateway and update the properties listed below | +| "m.Update()" | - | - | Get the status of the Motion Gateway and update the properties listed below | +| "m.Check_gateway_multicast()" | - | - | Check if multicast messages can be received with the configured multicast listener | +| "m.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the gateway | +| "m.Remove_callback("1") | id | string | Remove a external callback using its id | +| "m.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the gateway | + +| property | value type | explanation | +| ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| "m.available" | boolean | Return if the gateway is available | +| "m.status" | string | Return gateway status: from GatewayStatus enum | +| "m.N_devices" | int | Return the number of connected child devices | +| "m.RSSI" | int | Return the Wi-Fi connection strength of the gateway in dBm | +| "m.token" | string | Return the Token | +| "m.access_token" | string | Return the AccessToken | +| "m.mac" | string | Return the mac address of the gateway | +| "m.device_type" | string | Return the device type of the gateway | +| "m.protocol" | string | Return the protocol version of the gateway | +| "m.firmware" | string | Return the firmware version of the gateway | +| "m.device_list" | dict | Return a dict containing all blinds connected to the gateway, The keys in the dict are the mac adresses of the blinds. | + +## Blind device +A blind device (that was asigned to variable 'blind_1') has the following methods and properties, arguments between () are optional: + +| method | arguments | argument type | explanation | +| ------------------------------------- | --------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| "blind_1.Update_from_cache()" | - | - | Get the status of the blind from the cache of the Motion Gateway, No 433MHz radio communication with the blind takes place | +| "blind_1.Update_trigger()" | - | - | Get the status of the blind from the cache of the Motion Gateway and request a 433MHz radio communication with the blind for a new status (not awaited) | +| "blind_1.Update()" | - | - | Get the status of the blind from the blind through the Motion Gateway (WiFi) using 433MHz radio communication between the gateway and the blind | +| "blind_1.Stop()" | - | - | Stop the motion of the blind | +| "blind_1.Open()" | - | - | Open the blind/move the blind up | +| "blind_1.Close()" | - | - | Close the blind/move the blind down | +| "blind_1.Set_position(50)" | postion, (angle), (restore_angle) | int (0-100), int (0-180), boolean | Set the position of the blind, optionaly set angle or restore current angle | +| "blind_1.Set_angle(90)" | angle | int (0-180) | Set the angle/rotation of the blind | +| "blind_1.Jog_up()" | - | - | Open the blind/move the blind one step up | +| "blind_1.Jog_down()" | - | - | Close the blind/move the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | ---------- | ----------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | string | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | string | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | int | Return the current position of the blind in % (0-100) | +| "blind_1.angle" | int | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | double | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | double | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + +## Top Down Bottom Up (TDBU) device +A TDBU blind device has two motors designated by "T" = Top and "B" = Bottom to control the two parts of the blind. +Both parts can be controlled together using "C" = Combined as the motor. +The TDBU device (that was asigned to variable 'blind_1') has the following methods and properties: + +| method | arguments | argument type | explanation | +| --------------------------------------------------- | ---------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------- | +| "blind_1.Update()" | - | - | Get the status of the blind from the Motion Gateway | +| "blind_1.Stop(motor = 'B')" | motor | 'B', 'T' or 'C' | Stop the motion of Bottom or Top motor of the blind | +| "blind_1.Open(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind up | +| "blind_1.Close(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind down | +| "blind_1.Set_position(50, motor = 'B', width = 20)" | position, motor, width | int (0-100), 'B', 'T' or 'C', int (0-100) | Set the position of the Bottom or Top motor of the blind, optionaly specify width | +| "blind_1.Set_scaled_position(50, motor = 'B')" | position, motor | int (0-100), 'B', 'T' or 'C' | Set the position of the motor of the blind within the alowed space in which it can move | +| "blind_1.Set_angle(90, motor = 'B')" | angle, motor | int (0-180), 'B', 'T' or 'C' | Set the angle/rotation of the Bottom or Top motor of the blind | +| "blind_1.Jog_up(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step up | +| "blind_1.Jog_down(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | {"T": string, "B": string} | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | {"T": string, "B": string} | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | {"T": int, "B": int, "C": double} | Return the current position of the blind in % (0-100) | +| "blind_1.scaled_position" | {"T": double, "B": double, "C": double} | Return the current position of the blind, scaled to the alowed space in which it can move, in % (0-100) | +| "blind_1.width" | int | Return the area that is covered by the blind in % (0-100) | +| "blind_1.angle" | {"T": int, "B": int} | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | {"T": double, "B": double} | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | {"T": double, "B": double} | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + + +%package help +Summary: Development documents and examples for motionblinds +Provides: python3-motionblinds-doc +%description help +# motion-blinds +Python library for interfacing with Motion Blinds + +This library allows you to control Motion Blinds from Coulisse B.V. +This library is primarly writen to be used with HomeAssistant but can also be used stand alone. + +[](https://github.com/sponsors/starkillerOG) + +For products see https://motion-blinds.com or https://coulisse.com/products/motion. + +Shops that sell these blinds: +- [Hornbach](https://www.hornbach.nl/) +- [Smart Blinds](https://www.smartblinds.nl/) + +## Other brands of blinds +This python library is primarly written for the Motion Blinds, but some other manufacturers use the same API and therefore this library also works with those brands. +The following brands have been reported to also work with this python library: +- [Motion Blinds](https://motionblinds.com/) +- [Smart Blinds](https://www.smartblinds.nl/) +- [Dooya](http://www.dooya.com/) +- [Brel Home](https://www.brel-home.nl/) +- [Bloc Blinds](https://www.blocblinds.com/) +- [AMP Motorization](https://www.ampmotorization.com/) +- [Bliss Automation - Alta Window Fashions](https://www.altawindowfashions.com/product/automation/bliss-automation/) +- [3 Day Blinds](https://www.3dayblinds.com/) +- [Diaz](https://www.diaz.be/en/) +- [Gaviota](https://www.gaviotagroup.com/en/) +- [Havana Shade](https://havanashade.com/) +- [Hurrican Shutters Wholesale](https://www.hurricaneshutterswholesale.com/) +- [Inspired Shades](https://www.inspired-shades.com/) +- [iSmartWindow](https://www.ismartwindow.co.nz/) +- [Martec](https://www.martec.co.nz/) +- [Raven Rock MFG](https://www.ravenrockmfg.com/) +- [ScreenAway](https://www.screenaway.com.au/) +- [Smart Home](https://www.smart-home.hu) +- [Uprise Smart Shades](http://uprisesmartshades.com) + +## Installation + +Use pip: + +```$ pip install motionblinds``` + +or + +```$ pip install --use-wheel motionblinds``` + +## Retrieving Key +The Motion Blinds API uses a 16 character key that can be retrieved from the official "Motion Blinds" app for [Ios](https://apps.apple.com/us/app/motion-blinds/id1437234324) or [Android](https://play.google.com/store/apps/details?id=com.coulisse.motion). +Open the app, click the 3 dots in the top right corner, go to "settings", go to "Motion APP About", Please quickly tap this "Motion APP About" page 5 times, a popup will apear that gives you the key. + + + + +Please note that "-" characters need to be included in the key when providing it to this library. +The key needs to be simular to "12ab345c-d67e-8f" + +## Usage + +For creation of a device you could use the following lines of codes (using a correct IP of the gateway and Key retrieved from the App) +``` +from motionblinds import MotionGateway +m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +``` +This library is not polling. Thus you need to populate the connected blinds using the GetDeviceList method and update device information using the Update method. +Note that multicast pushes from the gateway can be processed to retrieve instant status updates (see Multicast pushes section) +``` +m.GetDeviceList() +m.Update() +``` +Note that GetDeviceList needs to be run before using Update since the device_type, mac and token are retrieved using the GetDeviceList method. +Once the connected blinds are discoverd using the GetDeviceList method, they can be listed by the device_list property: +``` +m.device_list +``` +This will return a dict with as key the mac_adress of the blind and as value a MotionBlind device that can be used to retreive information of that blind and control that blind. + +Some example code that will print the information of the gateway and all conected blinds: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +{'abcdefghujkl0001': <MotionBlind mac: abcdefghujkl0001, type: None, status: None, position: None %, angle: None, limit: None, battery: None, RSSI: None dBm>} +>>> m.Update() +>>> print(m) +<MotionGateway ip: 192.168.1.100, mac: abcdefghujkl, protocol: 0.9, N_devices: 1, status: Working, RSSI: -71 dBm> +>>> for blind in m.device_list.values(): +>>> blind.Update() +>>> print(blind) +<MotionBlind mac: abcdefghujkl0001, type: RollerBlind, status: Stopped, position: 0 %, angle: 0, limit: Limits, battery: 1195, RSSI: -82 dBm> +``` + +To open a blind the following example code can be used: +``` +>>> from motionblinds import MotionGateway +>>> m = MotionGateway(ip = "192.168.1.100", key = "12ab345c-d67e-8f") +>>> m.GetDeviceList() +>>> m.Update() +>>> blind_1 = list(m.device_list.values())[0] +>>> blind_1.Update() +>>> blind_1.Open() +``` +Instead of blind_1.Open() you can also use blind_1.Close(), blind_1.Stop(), blind_1.Set_position(50) or blind_1.Set_angle(90) + +## Multicast pushes +This library allows to listen for multicast pushes from the gateway (in a parallel thread or using asyncio) and process these pushes to get instant updates of the gateway and connected blinds status. +To use this parallel pushes processing a MotionMulticast/AsyncMotionMulticast class object needs to be initilized. +The MotionMulticast.Start_listen()/AsyncMotionMulticast.Start_listen() and MotionMulticast.Stop_listen()/AsyncMotionMulticast.Stop_listen() can then be used to start and stop the parallel thread that is listening for incoming pushes. +The MotionMulticast/AsyncMotionMulticast class object can be supplied to the MotionGateway class to let it update that gateway and its connected blinds. +Externall callbacks can be registered for both gateway devices and blind devices (see tables below) +If UDP multicast messages are not coming through, try using the IP adress of the host running the code as the interface instead of "any". +### Parallel thread +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using a parallel thread: +``` +import time +from motionblinds import MotionMulticast, MotionGateway + +def callback_func_gateway(): + print(m) + +def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + +motion_multicast = MotionMulticast(interface = "any") +motion_multicast.Start_listen() + +m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) +m.GetDeviceList() +m.Update() + +m.Register_callback("1", callback_func_gateway) +for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + +time.sleep(30) + +motion_multicast.Stop_listen() +``` +### Asyncio +An example code to listen for pushes for 30 seconds and print out gateway or blind information when a push comes in (when a blind finishes moving) using asyncio: +``` +import asyncio +from motionblinds import AsyncMotionMulticast, MotionGateway + +async def asyncio_demo(loop): + def callback_func_gateway(): + print(m) + + def callback_func_blind(): + for blind in m.device_list.values(): + print(blind) + + motion_multicast = AsyncMotionMulticast(interface = "any") + await motion_multicast.Start_listen() + + m = MotionGateway(ip="192.168.1.100", key="12ab345c-d67e-8f", multicast = motion_multicast) + await loop.run_in_executor(None, m.GetDeviceList) + await loop.run_in_executor(None, m.Update) + + m.Register_callback("1", callback_func_gateway) + for blind in m.device_list.values(): + blind.Register_callback("1", callback_func_blind) + + await asyncio.sleep(30) + + motion_multicast.Stop_listen() + +if __name__ == "__main__": + loop = asyncio.get_event_loop() + loop.run_until_complete(asyncio_demo(loop)) +``` + +## Discovery +Motion Gateways can be discovered on your network using the MotionDiscovery class. +The following example will try to discover gateways for 10 seconds and then print a dict containg the gateways and their connected blinds that were discovered. + +``` +>>> from motionblinds import MotionDiscovery +>>> d = MotionDiscovery() +>>> motion_gateways = d.discover() +>>> print(motion_gateways) + +{'192.168.1.100': { + 'msgType': 'GetDeviceListAck', + 'mac': 'abcdefghujkl', + 'deviceType': '02000002', + 'ProtocolVersion': '0.9', + 'token': '12345A678B9CDEFG', + 'data': [ + {'mac': 'abcdefghujkl', 'deviceType': '02000002'}, + {'mac': 'abcdefghujkl0001', 'deviceType': '10000000'}, + {'mac': 'abcdefghujkl0002', 'deviceType': '10000000'} + ] +}} +``` + +## Gateway device +A gateway device (that was asigned to variable 'm') has the following methods and properties: + +| method | arguments | argument type | explanation | +| ------------------------------- | ------------ | ---------------- | ---------------------------------------------------------------------------------- | +| "m.GetDeviceList()" | - | - | Get the device list from the Motion Gateway and update the properties listed below | +| "m.Update()" | - | - | Get the status of the Motion Gateway and update the properties listed below | +| "m.Check_gateway_multicast()" | - | - | Check if multicast messages can be received with the configured multicast listener | +| "m.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the gateway | +| "m.Remove_callback("1") | id | string | Remove a external callback using its id | +| "m.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the gateway | + +| property | value type | explanation | +| ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| "m.available" | boolean | Return if the gateway is available | +| "m.status" | string | Return gateway status: from GatewayStatus enum | +| "m.N_devices" | int | Return the number of connected child devices | +| "m.RSSI" | int | Return the Wi-Fi connection strength of the gateway in dBm | +| "m.token" | string | Return the Token | +| "m.access_token" | string | Return the AccessToken | +| "m.mac" | string | Return the mac address of the gateway | +| "m.device_type" | string | Return the device type of the gateway | +| "m.protocol" | string | Return the protocol version of the gateway | +| "m.firmware" | string | Return the firmware version of the gateway | +| "m.device_list" | dict | Return a dict containing all blinds connected to the gateway, The keys in the dict are the mac adresses of the blinds. | + +## Blind device +A blind device (that was asigned to variable 'blind_1') has the following methods and properties, arguments between () are optional: + +| method | arguments | argument type | explanation | +| ------------------------------------- | --------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| "blind_1.Update_from_cache()" | - | - | Get the status of the blind from the cache of the Motion Gateway, No 433MHz radio communication with the blind takes place | +| "blind_1.Update_trigger()" | - | - | Get the status of the blind from the cache of the Motion Gateway and request a 433MHz radio communication with the blind for a new status (not awaited) | +| "blind_1.Update()" | - | - | Get the status of the blind from the blind through the Motion Gateway (WiFi) using 433MHz radio communication between the gateway and the blind | +| "blind_1.Stop()" | - | - | Stop the motion of the blind | +| "blind_1.Open()" | - | - | Open the blind/move the blind up | +| "blind_1.Close()" | - | - | Close the blind/move the blind down | +| "blind_1.Set_position(50)" | postion, (angle), (restore_angle) | int (0-100), int (0-180), boolean | Set the position of the blind, optionaly set angle or restore current angle | +| "blind_1.Set_angle(90)" | angle | int (0-180) | Set the angle/rotation of the blind | +| "blind_1.Jog_up()" | - | - | Open the blind/move the blind one step up | +| "blind_1.Jog_down()" | - | - | Close the blind/move the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | ---------- | ----------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | string | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | string | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | int | Return the current position of the blind in % (0-100) | +| "blind_1.angle" | int | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | double | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | double | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + +## Top Down Bottom Up (TDBU) device +A TDBU blind device has two motors designated by "T" = Top and "B" = Bottom to control the two parts of the blind. +Both parts can be controlled together using "C" = Combined as the motor. +The TDBU device (that was asigned to variable 'blind_1') has the following methods and properties: + +| method | arguments | argument type | explanation | +| --------------------------------------------------- | ---------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------- | +| "blind_1.Update()" | - | - | Get the status of the blind from the Motion Gateway | +| "blind_1.Stop(motor = 'B')" | motor | 'B', 'T' or 'C' | Stop the motion of Bottom or Top motor of the blind | +| "blind_1.Open(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind up | +| "blind_1.Close(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind down | +| "blind_1.Set_position(50, motor = 'B', width = 20)" | position, motor, width | int (0-100), 'B', 'T' or 'C', int (0-100) | Set the position of the Bottom or Top motor of the blind, optionaly specify width | +| "blind_1.Set_scaled_position(50, motor = 'B')" | position, motor | int (0-100), 'B', 'T' or 'C' | Set the position of the motor of the blind within the alowed space in which it can move | +| "blind_1.Set_angle(90, motor = 'B')" | angle, motor | int (0-180), 'B', 'T' or 'C' | Set the angle/rotation of the Bottom or Top motor of the blind | +| "blind_1.Jog_up(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step up | +| "blind_1.Jog_down(motor = 'B')" | motor | 'B', 'T' or 'C' | Move the Bottom or Top motor of the blind one step down | +| "blind_1.Register_callback("1", func) | id, callback | string, function | Register a external callback function for updates of the blind | +| "blind_1.Remove_callback("1") | id | string | Remove a external callback using its id | +| "blind_1.Clear_callbacks() | - | - | Remove all external registered callbacks for updates of the blind | + +| property | value type | explanation | +| ------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| "blind_1.device_type" | string | Return the device type which is a 8 character number | +| "blind_1.blind_type" | string | Return the type of the blind from BlindType enum | +| "blind_1.type" | enum | Return the type of the blind as a BlindType enum | +| "blind_1.mac" | string | Return the mac address of the blind | +| "blind_1.available" | boolean | Return if the blind is available | +| "blind_1.status" | {"T": string, "B": string} | Return the current status of the blind from BlindStatus enum | +| "blind_1.limit_status" | {"T": string, "B": string} | Return the current status of the limit detection of the blind from LimitStatus enum | +| "blind_1.position" | {"T": int, "B": int, "C": double} | Return the current position of the blind in % (0-100) | +| "blind_1.scaled_position" | {"T": double, "B": double, "C": double} | Return the current position of the blind, scaled to the alowed space in which it can move, in % (0-100) | +| "blind_1.width" | int | Return the area that is covered by the blind in % (0-100) | +| "blind_1.angle" | {"T": int, "B": int} | Return the current angle of the blind 0-180 | +| "blind_1.battery_voltage" | {"T": double, "B": double} | Return the current battery voltage of the blind in V | +| "blind_1.battery_level" | {"T": double, "B": double} | Return the current battery level of the blind in % | +| "blind_1.is_charging" | boolean | Return if the blind is currently charging its battery | +| "blind_1.RSSI" | int | Return the radio connection strength of the blind to the gateway in dBm | +| "blind_1.wireless_mode" | enum | Return the wireless mode of the blind as a WirelessMode enum | +| "blind_1.wireless_name" | string | Return the wireless mode of the blind from WirelessMode enum | +| "blind_1.voltage_mode" | enum | Return the voltage mode of the blind as a VoltageMode enum | +| "blind_1.voltage_name" | string | Return the voltage mode of the blind from VoltageMode enum | + + +%prep +%autosetup -n motionblinds-0.6.17 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-motionblinds -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Fri May 05 2023 Python_Bot <Python_Bot@openeuler.org> - 0.6.17-1 +- Package Spec generated |
