Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7571d99
Convert to python 3 by minor syntax change and conversion to 'request…
Mar 19, 2023
94ab3a7
Restore info.plist and change ServerApiVersion to 3.0
Mar 20, 2023
f14dd80
Conversion to py3 and Generation 3. PowerView3 passes tests.
Mar 6, 2023
45e555e
- New Action: Stop Shade for gen 3 only.
Mar 22, 2023
180ee1b
- Many revisions to plugin.py that support both generation 2 and 3.
Mar 22, 2023
962c66c
Add two tests for the two versions of powerview. The tests are design…
Mar 22, 2023
2f57c7b
Specify new state showing the amount the shade is open. Update shade …
Mar 24, 2023
9cac8bb
Fix error "PowerView() takes no arguments".
Apr 21, 2023
6fbd36a
Add description of the Stop Shade Action to the ReadMe.
Apr 21, 2023
73b5f0c
Fix support for V2 hubs, especially with positioning. Added Shade con…
Apr 24, 2023
f9a9d94
Another fix to support for positioning with V2 hubs.
Apr 24, 2023
89194ec
Fix "exception in device_start_comm(...): 'position2'".
Apr 24, 2023
cec1081
Add some default values in UI. Tweak the documentation.
Apr 25, 2023
d12dd0d
Fix missing generation state on V2 shades.
Apr 30, 2023
d06b354
Fix defaults on Set Position values.
May 2, 2023
639ee91
Ignore all .pytest folders.
May 2, 2023
b07782c
Improve performance by eliminating a call to the hub that is not alwa…
May 2, 2023
c8d5a68
Revised how tests are run. Added mocking versions of both V2 and V3 h…
Jun 2, 2023
2ddafe9
Revised logging. Attempt to get results to print, but not yet done.
Jun 9, 2023
1f71dfd
Revised tests to mock both hub types. Fixed bad tests. Revised loggin…
Jun 23, 2023
00ed643
Exported pytest's report to a separate log file: pvTestReport.log in …
Jun 25, 2023
50fd958
Bump the plugin version number to 2.0.4.
Jun 25, 2023
d2cd591
Revised tests to improve the tests. Fixed bad tests. Revised logging …
Jul 20, 2023
017645a
Final revisions to tests so all tests pass. Fixes as needed.
Jul 24, 2023
9c6856c
Major revisions to tests so that all tests can run no matter what hub…
sdf-cnicorp Nov 4, 2023
b43c664
Revise runConcurrentThread to avoid server communication errors. Twea…
sdf-cnicorp Mar 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
.DS_Store
*.pyc
.idea/
**/.pytest_cache/
/PowerView.indigoPlugin/Contents/Packages/
38 changes: 19 additions & 19 deletions PowerView.indigoPlugin/Contents/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PluginVersion</key>
<string>1.0.0</string>
<key>ServerApiVersion</key>
<string>2.0</string>
<key>IwsApiVersion</key>
<string>1.0.0</string>
<key>CFBundleDisplayName</key>
<string>PowerView</string>
<key>CFBundleIdentifier</key>
<string>net.segment7.powerview</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>https://github.com/drbrain/indigo-powerview</string>
</dict>
</array>
<key>PluginVersion</key>
<string>2.0.5</string>
<key>ServerApiVersion</key>
<string>3.0</string>
<key>IwsApiVersion</key>
<string>1.0.0</string>
<key>CFBundleDisplayName</key>
<string>PowerView</string>
<key>CFBundleIdentifier</key>
<string>net.segment7.powerview</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>https://github.com/drbrain/indigo-powerview</string>
</dict>
</array>
</dict>
</plist>
46 changes: 46 additions & 0 deletions PowerView.indigoPlugin/Contents/Menu Items/Run Tests with Hub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python

import logging
import sys
try:
import indigo
except ImportError:
pass


def do_live_hub():
hub3 = None
hub2 = None

menu_items = "../../../../../../../Plugins/PowerView.indigoPlugin/Contents/Menu Items"
# ########### menu_items = "/Users/sfyfe/Documents/Projects/indigo-powerview/PowerView.indigoPlugin/Contents/Menu Items"
sys.path.insert(1, menu_items)
runner = __import__("Run Tests")

for dev in indigo.devices.iter("net.segment7.powerview.PowerViewHub"):
if dev.states.get('generation', 0) == 3:
hub3 = dev.address

elif dev.states.get('generation', 0) == 2:
hub2 = dev.address

else:
logger.warning("PowerView Hub '{}' has not been updated with the latest PowerView plugin. Assuming it is a V2 hub.".format(dev.name))

logger.debug(f"About to run tests with gen3 hub {hub3} and/or version 2 hub {hub2}.")
return runner.run_tests(hub3, hub2)


if __name__ == '__main__':
logger = logging.getLogger("wsgmac.com.test.powerview")
indigo.server.log("Run Tests with Hub: Starting PowerView Tests", level=logging.INFO) # log to Indigo Event Log
logger.debug("'Run Tests with Hubs' begins, using live hubs, if available")
count_passed, count_failed, count_errored, count_skipped = do_live_hub()

if count_failed == 0 and count_errored == 0:
indigo.server.log(f"PowerView Tests Complete. All tests PASSED.", level=logging.INFO)
else:
indigo.server.log(f"PowerView Tests Complete. Passed: {count_passed}, Failed: {count_failed}" +
(f", Broken: {count_errored}" if count_errored else "") +
(f", Skipped: {count_skipped}" if count_skipped else "") +
". See pvTestReport.log in the PowerView Logs folder for details.", level=logging.INFO)
78 changes: 78 additions & 0 deletions PowerView.indigoPlugin/Contents/Menu Items/Run Tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/python3

import contextlib
import datetime
import logging
import logging.handlers
import os
import sys
try:
import indigo
except ImportError:
pass


class add_path:
def __init__(self, path):
self.path = path

def __enter__(self):
sys.path.insert(0, self.path)

def __exit__(self, exc_type, exc_value, traceback):
try:
sys.path.remove(self.path)
except ValueError:
pass


def run_tests(hub3, hub2):
now = datetime.datetime.now()
# Scripts run from Menu Items start with cwd:
# /Library/Application Support/Perceptive Automation/Indigo 2022.2/IndigoPluginHost3.app/
# Contents/Resources/PlugIns/ScriptExecutor.indigoPlugin/Contents/Server Plugin
indigo_base = os.path.abspath("../../../../../../../")
# indigo_base = os.path.abspath("/Library/Application Support/Perceptive Automation/Indigo 2022.2")
plugin_path = os.path.abspath(os.path.join(indigo_base, "Plugins/PowerView.indigoPlugin/"))

test_details_file_name = os.path.join(indigo_base, "Logs/net.segment7.powerview/pvTestDetails.log")
fh = logging.handlers.TimedRotatingFileHandler(test_details_file_name, when='midnight', backupCount=10, encoding='utf-8')
log_format = "%(asctime)s.%(msecs).0f)\t%(levelname)s \t%(funcName)s\t\t%(message)s"
fh.setFormatter(logging.Formatter(fmt=log_format, datefmt='%y-%m-%d %H:%M:%S'))
fh.setLevel(logging.DEBUG)
logger = logging.getLogger("wsgmac.com.test.powerview") # most of the logging during the tests go to a file
logger.setLevel(logging.DEBUG)
logger.addHandler(fh)

os.chdir(plugin_path)
logger.debug("Run Tests at {} with hub3={} and hub2={}".format(now.strftime("%Y-%m-%d %H:%M:%S"), hub3, hub2))

with add_path(os.path.abspath("./Contents/Server Plugin/pv_tests/")):
logger.debug("Sys.path={}\n\n".format(sys.path))
import pv_runner # Will be found now that the folder has been added to the sys.path.

try:
with open(os.path.join(indigo_base, "Logs/net.segment7.powerview/pvTestReport.log"), 'w') as std_file:
with contextlib.redirect_stdout(std_file):
passed, failed, errored, skipped = pv_runner.run_tests(hub3, hub2)
except:
logger.exception("Run Tests: Tests Failed")

logger.debug("Run Tests: Tests Complete")
logger.debug("==============================================================================\n\n\n")

return passed, failed, errored, skipped


if __name__ == '__main__':
indigo.server.log("Run Tests: Starting PowerView Tests", level=logging.INFO) # log to Indigo Event Log

count_passed, count_failed, count_errored, count_skipped = run_tests(hub3=None, hub2=None)

if count_failed == 0 and count_errored == 0:
indigo.server.log(f"PowerView Tests Complete. All tests PASSED.", level=logging.INFO)
else:
indigo.server.log(f"PowerView Tests Complete. Passed: {count_passed}, Failed: {count_failed}" +
(f", Broken: {count_errored}" if count_errored else "") +
(f", Skipped: {count_skipped}" if count_skipped else "") +
". See pvTestReport.log in the PowerView Logs folder for details.", level=logging.INFO)
116 changes: 70 additions & 46 deletions PowerView.indigoPlugin/Contents/Server Plugin/Actions.xml
Original file line number Diff line number Diff line change
@@ -1,49 +1,73 @@
<?xml version="1.0"?>
<Actions>
<Action id="activateScene" deviceFilter="self.PowerViewHub">
<Name>Activate Scene</Name>
<CallbackMethod>activateScene</CallbackMethod>
<ConfigUI>
<Field id="sceneId" type="menu">
<Label>Scenes</Label>
<List class="self" method="listScenes"/>
</Field>
</ConfigUI>
</Action>
<Action id="activateSceneCollection" deviceFilter="self.PowerViewHub">
<Name>Activate Scene Collection</Name>
<CallbackMethod>activateSceneCollection</CallbackMethod>
<ConfigUI>
<Field id="sceneCollectionId" type="menu">
<Label>ScenesCollection</Label>
<List class="self" method="listSceneCollections"/>
</Field>
</ConfigUI>
</Action>
<Action id="calibrateShade" deviceFilter="self.PowerViewShade">
<Name>Calibrate Shade</Name>
<CallbackMethod>calibrateShade</CallbackMethod>
</Action>
<Action id="jogShade" deviceFilter="self.PowerViewShade">
<Name>Jog Shade</Name>
<CallbackMethod>jogShade</CallbackMethod>
</Action>
<Action id="setShadePosition" deviceFilter="self.PowerViewShade">
<Name>Set Shade Position</Name>
<CallbackMethod>setShadePosition</CallbackMethod>
<ConfigUI>
<Field id="top" type="textfield">
<Label>Top</Label>
</Field>
<Field type="label" id="topDescription">
<Label>Position of top of shade (for top-down). 0–65535</Label>
</Field>
<Field id="bottom" type="textfield">
<Label>Bottom</Label>
</Field>
<Field type="label" id="bottomDescription">
<Label>Position of bottom of shade (for bottom-up). 0–65535</Label>
</Field>
</ConfigUI>
</Action>
<SupportURL>https://github.com/sdf-cnicorp/indigo-powerview#supported-actions</SupportURL>
<Action id="activateScene" deviceFilter="self.PowerViewHub">
<Name>Activate Scene</Name>
<CallbackMethod>activateScene</CallbackMethod>
<ConfigUI>
<SupportURL>https://github.com/sdf-cnicorp/indigo-powerview#activate-scene</SupportURL>
<Field id="sceneId" type="menu" defaultValue="0">
<Label>Scenes</Label>
<List class="self" method="listScenes"/>
</Field>
</ConfigUI>
</Action>
<Action id="activateSceneCollection" deviceFilter="self.PowerViewHub">
<Name>Activate Scene Collection</Name>
<CallbackMethod>activateSceneCollection</CallbackMethod>
<ConfigUI>
<SupportURL>https://github.com/sdf-cnicorp/indigo-powerview#activate-scene-collection</SupportURL>
<Field id="sceneCollectionId" type="menu" defaultValue="0">
<Label>ScenesCollection</Label>
<List class="self" method="listSceneCollections"/>
</Field>
</ConfigUI>
</Action>
<Action id="calibrateShade" deviceFilter="self.PowerViewShade">
<Name>Calibrate Shade</Name>
<CallbackMethod>calibrateShade</CallbackMethod>
</Action>
<Action id="jogShade" deviceFilter="self.PowerViewShade">
<Name>Jog Shade</Name>
<CallbackMethod>jogShade</CallbackMethod>
</Action>
<Action id="stopShade" deviceFilter="self.PowerViewShade">
<Name>Stop Shade</Name>
<CallbackMethod>stopShade</CallbackMethod>
</Action>
<Action id="setShadePosition" deviceFilter="self.PowerViewShade">
<Name>Set Shade Position</Name>
<CallbackMethod>setShadePosition</CallbackMethod>
<ConfigUI>
<SupportURL>https://github.com/sdf-cnicorp/indigo-powerview#set-shade-position</SupportURL>
<Field id="current" type="button">
<Label>Lookup Current Position?:</Label>
<Title>Current Position</Title>
<CallbackMethod>getCurrentPosition</CallbackMethod>
</Field>
<Field id="lblNumbers" type="label">
<Label>Enter a value as a percentage the shade is open, 0-100.</Label>
</Field>
<Field id="enablePri" type="checkbox" hidden="true" defaultValue="true"/>
<Field id="enableSec" type="checkbox" hidden="true" defaultValue="true"/>
<Field id="enableTlt" type="checkbox" hidden="true" defaultValue="true"/>
<Field id="enableVel" type="checkbox" hidden="true" defaultValue="true"/>
<Field id="primary" type="textfield" enabledBindingId="enablePri" defaultValue="0"
tooltip="Disabled since the chosen shade does not support this setting.">
<Label>Primary (Bottom):</Label>
</Field>
<Field id="secondary" type="textfield" enabledBindingId="enableSec" defaultValue="0"
tooltip="Disabled since the chosen shade does not support this setting.">
<Label>Secondary (Top):</Label>
</Field>
<Field id="tilt" type="textfield" enabledBindingId="enableTlt" defaultValue="0"
tooltip="Disabled since the chosen shade does not support this setting.">
<Label>Tilt:</Label>
</Field>
<Field id="velocity" type="textfield" enabledBindingId="enableVel" defaultValue="0"
tooltip="Disabled since the chosen shade does not support this setting.">
<Label>Velocity:</Label>
</Field>
</ConfigUI>
</Action>
</Actions>
Loading