reorganize
This commit is contained in:
parent
72482d0162
commit
b8efa3badb
@ -1,10 +0,0 @@
|
||||
[Dolphin]
|
||||
HeaderColumnWidths=546,72,94,222
|
||||
PreviewsShown=true
|
||||
Timestamp=2018,10,22,11,49,21
|
||||
Version=4
|
||||
ViewMode=1
|
||||
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_type,CustomizedDetails
|
||||
|
||||
[Settings]
|
||||
HiddenFilesShown=true
|
11
old/.idea/LED-Server.iml
generated
11
old/.idea/LED-Server.iml
generated
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.6.5 (/usr/bin/python3.6)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||
</component>
|
||||
</module>
|
21
old/.idea/deployment.xml
generated
21
old/.idea/deployment.xml
generated
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" serverName="pi@jugendraum">
|
||||
<serverData>
|
||||
<paths name="pi@home">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping deploy="/home/pi/LED-Server" local="$PROJECT_DIR$" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
<paths name="pi@jugendraum">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping deploy="/home/pi/LED-Server" local="$PROJECT_DIR$" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
</serverData>
|
||||
</component>
|
||||
</project>
|
4
old/.idea/misc.xml
generated
4
old/.idea/misc.xml
generated
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.5 (/usr/bin/python3.6)" project-jdk-type="Python SDK" />
|
||||
</project>
|
8
old/.idea/modules.xml
generated
8
old/.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/LED-Server.iml" filepath="$PROJECT_DIR$/.idea/LED-Server.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
685
old/.idea/workspace.xml
generated
685
old/.idea/workspace.xml
generated
@ -1,685 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b0eeb174-91a6-4ace-80d1-586f86189e2c" name="Default" comment="" />
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="TRACKING_ENABLED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="CoverageDataManager">
|
||||
<SUITE FILE_PATH="coverage/LED_Server$__main__.coverage" NAME="__main__ Coverage Results" MODIFIED="1538853952332" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||
<SUITE FILE_PATH="coverage/LED_Server$test.coverage" NAME="test Coverage Results" MODIFIED="1537290859304" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="DatabaseView">
|
||||
<option name="SHOW_INTERMEDIATE" value="true" />
|
||||
<option name="GROUP_SCHEMA" value="true" />
|
||||
<option name="GROUP_CONTENTS" value="false" />
|
||||
<option name="SORT_POSITIONED" value="false" />
|
||||
<option name="SHOW_TABLE_DETAILS" value="true" />
|
||||
<option name="SHOW_EMPTY_GROUPS" value="false" />
|
||||
<option name="AUTO_SCROLL_FROM_SOURCE" value="false" />
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file leaf-file-name="config.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/config.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="153">
|
||||
<caret line="25" column="38" lean-forward="true" selection-start-line="25" selection-start-column="38" selection-end-line="25" selection-end-column="38" />
|
||||
<folding>
|
||||
<element signature="e#46#80#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="__main__.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/__main__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="170">
|
||||
<caret line="13" column="0" lean-forward="true" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#0#22#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="on.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/effects/on.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="85">
|
||||
<caret line="6" column="39" lean-forward="false" selection-start-line="6" selection-start-column="39" selection-end-line="6" selection-end-column="39" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="RGBStrip.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStrip.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="284">
|
||||
<caret line="45" column="0" lean-forward="true" selection-start-line="45" selection-start-column="0" selection-end-line="45" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="RGBStripController.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStripController.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="23" lean-forward="false" selection-start-line="0" selection-start-column="23" selection-end-line="0" selection-end-column="23" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="off.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/effects/off.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="51">
|
||||
<caret line="4" column="44" lean-forward="false" selection-start-line="4" selection-start-column="44" selection-end-line="4" selection-end-column="44" />
|
||||
<folding>
|
||||
<element signature="e#0#36#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="BaseEffect.py" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/util/BaseEffect.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="151">
|
||||
<caret line="38" column="16" lean-forward="false" selection-start-line="38" selection-start-column="16" selection-end-line="38" selection-end-column="16" />
|
||||
<folding>
|
||||
<element signature="e#0#11#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="test.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/test.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="663">
|
||||
<caret line="41" column="13" lean-forward="false" selection-start-line="41" selection-start-column="13" selection-end-line="41" selection-end-column="13" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="RGBStripGroup.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStripGroup.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="187">
|
||||
<caret line="11" column="8" lean-forward="false" selection-start-line="11" selection-start-column="8" selection-end-line="11" selection-end-column="8" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="HTML File" />
|
||||
<option value="JavaScript File" />
|
||||
<option value="Python Script" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>*</find>
|
||||
<find>audio_in()</find>
|
||||
<find>21</find>
|
||||
<find>setB</find>
|
||||
<find>ur</find>
|
||||
<find>effectParamsQueue</find>
|
||||
</findStrings>
|
||||
<replaceStrings>
|
||||
<replace>#</replace>
|
||||
</replaceStrings>
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/util/SocketServer.py" />
|
||||
<option value="$PROJECT_DIR$/util/LedControllerService.py" />
|
||||
<option value="$PROJECT_DIR$/util/LedController.py" />
|
||||
<option value="$PROJECT_DIR$/util/effectThread.py" />
|
||||
<option value="$PROJECT_DIR$/effects/cops.py" />
|
||||
<option value="$PROJECT_DIR$/effects/__init__.py" />
|
||||
<option value="$PROJECT_DIR$/effects/effect_fade.py" />
|
||||
<option value="$PROJECT_DIR$/htdocs/inhel.html" />
|
||||
<option value="$PROJECT_DIR$/htdocs/js/tether.min.js" />
|
||||
<option value="$PROJECT_DIR$/util/__init__.py" />
|
||||
<option value="$PROJECT_DIR$/loader.py" />
|
||||
<option value="$PROJECT_DIR$/server.py" />
|
||||
<option value="$PROJECT_DIR$/__init__.py" />
|
||||
<option value="$PROJECT_DIR$/cache/activergbindex.cache" />
|
||||
<option value="$PROJECT_DIR$/util/admin.py" />
|
||||
<option value="$PROJECT_DIR$/effects/Lightshow.py" />
|
||||
<option value="$PROJECT_DIR$/cache/Lightshow.py" />
|
||||
<option value="$PROJECT_DIR$/test.sh" />
|
||||
<option value="$PROJECT_DIR$/htdocs/index.html" />
|
||||
<option value="$PROJECT_DIR$/effects/Test.py" />
|
||||
<option value="$PROJECT_DIR$/effects/Fade.py" />
|
||||
<option value="$PROJECT_DIR$/effects/Cops.py" />
|
||||
<option value="$PROJECT_DIR$/effects/Off.py" />
|
||||
<option value="$PROJECT_DIR$/lightshowpi/config/defaults.cfg" />
|
||||
<option value="$PROJECT_DIR$/util/serialConfig.py" />
|
||||
<option value="$PROJECT_DIR$/util/virtGPIO.py" />
|
||||
<option value="$PROJECT_DIR$/util/Loader.py" />
|
||||
<option value="$PROJECT_DIR$/util/EffectThread.py" />
|
||||
<option value="$PROJECT_DIR$/util/LedControl.py" />
|
||||
<option value="$PROJECT_DIR$/util/WebServer.py" />
|
||||
<option value="$PROJECT_DIR$/test.py" />
|
||||
<option value="$PROJECT_DIR$/effects/on.py" />
|
||||
<option value="$PROJECT_DIR$/util/RGBStripController.py" />
|
||||
<option value="$PROJECT_DIR$/effects/off.py" />
|
||||
<option value="$PROJECT_DIR$/util/RGBStripGroup.py" />
|
||||
<option value="$PROJECT_DIR$/config.py" />
|
||||
<option value="$PROJECT_DIR$/util/RGBStrip.py" />
|
||||
<option value="$PROJECT_DIR$/__main__.py" />
|
||||
<option value="$PROJECT_DIR$/util/BaseEffect.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsFlowSettings">
|
||||
<service-enabled>false</service-enabled>
|
||||
<exe-path />
|
||||
<annotation-enable>false</annotation-enable>
|
||||
<other-services-enabled>false</other-services-enabled>
|
||||
<auto-save>true</auto-save>
|
||||
</component>
|
||||
<component name="JsGulpfileManager">
|
||||
<detection-done>true</detection-done>
|
||||
<sorting>DEFINITION_ORDER</sorting>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="width" value="1366" />
|
||||
<option name="height" value="768" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<autoscrollToSource />
|
||||
<autoscrollFromSource />
|
||||
<sortByType />
|
||||
<manualOrder />
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="LED-Server" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="LED-Server" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="LED-Server" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="LED-Server" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="effects" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="LED-Server" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="LED-Server" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="htdocs" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="LED-Server" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="LED-Server" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="util" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
<pane id="Scratches" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
|
||||
<property name="DefaultHtmlFileTemplate" value="HTML File" />
|
||||
<property name="run.code.analysis.last.selected.profile" value="pProject Default" />
|
||||
<property name="last_opened_file_path" value="/usr/bin/python3.6" />
|
||||
</component>
|
||||
<component name="PyConsoleOptionsProvider">
|
||||
<option name="myPythonConsoleState">
|
||||
<console-settings module-name="LED-Server" is-module-sdk="true">
|
||||
<option name="myUseModuleSdk" value="true" />
|
||||
<option name="myModuleName" value="LED-Server" />
|
||||
</console-settings>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/effects" />
|
||||
<recent name="$PROJECT_DIR$/util" />
|
||||
</key>
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/cache" />
|
||||
<recent name="$PROJECT_DIR$/util" />
|
||||
<recent name="$PROJECT_DIR$/htdocs" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Python.__main__">
|
||||
<configuration name="__main__" type="PythonConfigurationType" factoryName="Python" singleton="true" temporary="true">
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<module name="LED-Server" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/__main__.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
</configuration>
|
||||
<configuration name="index.html" type="JavascriptDebugType" factoryName="JavaScript Debug" temporary="true" nameIsGenerated="true" uri="http://localhost:63342/LED-Server/htdocs/index.html" />
|
||||
<configuration name="test" type="PythonConfigurationType" factoryName="Python" temporary="true">
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<module name="LED-Server" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/test.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
</configuration>
|
||||
<list size="3">
|
||||
<item index="0" class="java.lang.String" itemvalue="JavaScript Debug.index.html" />
|
||||
<item index="1" class="java.lang.String" itemvalue="Python.__main__" />
|
||||
<item index="2" class="java.lang.String" itemvalue="Python.test" />
|
||||
</list>
|
||||
<recent_temporary>
|
||||
<list size="3">
|
||||
<item index="0" class="java.lang.String" itemvalue="Python.__main__" />
|
||||
<item index="1" class="java.lang.String" itemvalue="Python.test" />
|
||||
<item index="2" class="java.lang.String" itemvalue="JavaScript Debug.index.html" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="ShelveChangesManager" show_recycled="false">
|
||||
<option name="remove_strategy" value="false" />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="b0eeb174-91a6-4ace-80d1-586f86189e2c" name="Default" comment="" />
|
||||
<created>1502053329033</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1502053329033</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="32" width="1366" height="736" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.1621212" sideWeight="0.5" order="1" side_tool="false" content_ui="combo" />
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32954547" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3286334" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3305921" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32986537" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="File Transfer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32401314" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Inspection Results" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32894737" sideWeight="0.5" order="12" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.329718" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="VcsContentAnnotationSettings">
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
<breakpoints>
|
||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||
<url>file://$PROJECT_DIR$/test.py</url>
|
||||
<line>1</line>
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||
<url>file://$PROJECT_DIR$/__main__.py</url>
|
||||
<line>31</line>
|
||||
<option name="timeStamp" value="1" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||
<url>file://$PROJECT_DIR$/__main__.py</url>
|
||||
<line>27</line>
|
||||
<option name="timeStamp" value="2" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
||||
<url>file://$PROJECT_DIR$/__main__.py</url>
|
||||
<line>24</line>
|
||||
<option name="timeStamp" value="3" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
<option name="time" value="4" />
|
||||
</breakpoint-manager>
|
||||
<watches-manager />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/util/LedControl.py" />
|
||||
<entry file="file://$PROJECT_DIR$/config.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="34">
|
||||
<caret line="2" column="0" lean-forward="false" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#46#80#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStrip.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="15" lean-forward="false" selection-start-line="0" selection-start-column="15" selection-end-line="0" selection-end-column="15" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/SocketServer.py" />
|
||||
<entry file="file://$PROJECT_DIR$/util/LedControllerService.py" />
|
||||
<entry file="file://$USER_HOME$/.PyCharm2017.2/system/python_stubs/-770027826/_socket.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="266">
|
||||
<caret line="568" column="8" lean-forward="false" selection-start-line="568" selection-start-column="8" selection-end-line="568" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/css/bootstrap.min.css">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/js/html5shiv.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/js/respond.min.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="85">
|
||||
<caret line="5" column="73" lean-forward="true" selection-start-line="5" selection-start-column="73" selection-end-line="5" selection-end-column="73" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/js/tether.min.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="24989" lean-forward="false" selection-start-line="0" selection-start-column="24989" selection-end-line="0" selection-end-column="24989" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/js/jquery-3.2.1.min.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.PyCharm2017.2/system/remote_sources/-770027826/201544331/SocketServer.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="296">
|
||||
<caret line="333" column="13" lean-forward="true" selection-start-line="333" selection-start-column="13" selection-end-line="333" selection-end-column="13" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/.PyCharm2017.2/system/remote_sources/-770027826/201544331/BaseHTTPServer.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="397">
|
||||
<caret line="103" column="36" lean-forward="true" selection-start-line="103" selection-start-column="36" selection-end-line="103" selection-end-column="36" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/admin.py" />
|
||||
<entry file="file://$PROJECT_DIR$/lightshowpi/py/synchronized_lights.py" />
|
||||
<entry file="file://$PROJECT_DIR$/test.sh">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="493">
|
||||
<caret line="29" column="3" lean-forward="false" selection-start-line="29" selection-start-column="3" selection-end-line="29" selection-end-column="3" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/LedControl.py.out" />
|
||||
<entry file="file://$PROJECT_DIR$/lightshowpi/install.sh" />
|
||||
<entry file="file://$PROJECT_DIR$/htdocs/index.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="391">
|
||||
<caret line="23" column="45" lean-forward="false" selection-start-line="23" selection-start-column="45" selection-end-line="23" selection-end-column="45" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cache/activergbindex.cache">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="5" lean-forward="false" selection-start-line="0" selection-start-column="5" selection-end-line="0" selection-end-column="5" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/effects/Test.py" />
|
||||
<entry file="file:///usr/share/applications/org.kde.konsole.desktop">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lightshowpi/config/defaults.cfg" />
|
||||
<entry file="file://$PROJECT_DIR$/util/serialConfig.py" />
|
||||
<entry file="file://$PROJECT_DIR$/util/Loader.py" />
|
||||
<entry file="file://$PROJECT_DIR$/util/WebServer.py" />
|
||||
<entry file="file://$PROJECT_DIR$/util/EffectThread.py" />
|
||||
<entry file="file://$PROJECT_DIR$/effects/Off.py" />
|
||||
<entry file="file://$PROJECT_DIR$/effects/Fade.py" />
|
||||
<entry file="file://$PROJECT_DIR$/effects/__init__.py" />
|
||||
<entry file="file://$PROJECT_DIR$/lightshowpi/py/examples/pwm_example.py" />
|
||||
<entry file="file://$PROJECT_DIR$/lightshowpi/py/hardware_controller.py" />
|
||||
<entry file="file://$PROJECT_DIR$/effects/Cops.py" />
|
||||
<entry file="file://$PROJECT_DIR$/cache/Lightshow.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="306">
|
||||
<caret line="19" column="29" lean-forward="false" selection-start-line="19" selection-start-column="29" selection-end-line="20" selection-end-column="29" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cache/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/LedControl.py" />
|
||||
<entry file="file://$PROJECT_DIR$/util/__init__.py" />
|
||||
<entry file="file://$USER_HOME$/.PyCharm2017.2/system/remote_sources/660800692/201545290/glob.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/virtGPIO.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="2023">
|
||||
<caret line="167" column="47" lean-forward="false" selection-start-line="167" selection-start-column="47" selection-end-line="167" selection-end-column="47" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/effects/on.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="85">
|
||||
<caret line="6" column="39" lean-forward="false" selection-start-line="6" selection-start-column="39" selection-end-line="6" selection-end-column="39" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$APPLICATION_HOME_DIR$/helpers/python-skeletons/multiprocessing/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="60">
|
||||
<caret line="48" column="6" lean-forward="false" selection-start-line="48" selection-start-column="6" selection-end-line="48" selection-end-column="6" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file:///usr/lib/python3.6/multiprocessing/process.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="215">
|
||||
<caret line="257" column="0" lean-forward="false" selection-start-line="257" selection-start-column="0" selection-end-line="257" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStripGroup.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="187">
|
||||
<caret line="11" column="8" lean-forward="false" selection-start-line="11" selection-start-column="8" selection-end-line="11" selection-end-column="8" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/effects/off.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="51">
|
||||
<caret line="4" column="44" lean-forward="false" selection-start-line="4" selection-start-column="44" selection-end-line="4" selection-end-column="44" />
|
||||
<folding>
|
||||
<element signature="e#0#36#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/test.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="663">
|
||||
<caret line="41" column="13" lean-forward="false" selection-start-line="41" selection-start-column="13" selection-end-line="41" selection-end-column="13" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStrip.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="284">
|
||||
<caret line="45" column="0" lean-forward="true" selection-start-line="45" selection-start-column="0" selection-end-line="45" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/RGBStripController.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="23" lean-forward="false" selection-start-line="0" selection-start-column="23" selection-end-line="0" selection-end-column="23" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/config.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="153">
|
||||
<caret line="25" column="38" lean-forward="true" selection-start-line="25" selection-start-column="38" selection-end-line="25" selection-end-column="38" />
|
||||
<folding>
|
||||
<element signature="e#46#80#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/__main__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="170">
|
||||
<caret line="13" column="0" lean-forward="true" selection-start-line="13" selection-start-column="0" selection-end-line="13" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#0#22#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/BaseEffect.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="151">
|
||||
<caret line="38" column="16" lean-forward="false" selection-start-line="38" selection-start-column="16" selection-end-line="38" selection-end-column="16" />
|
||||
<folding>
|
||||
<element signature="e#0#11#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
def main():
|
||||
try:
|
||||
os.chdir(os.path.dirname(sys.argv[0]))
|
||||
|
||||
# i want some external providers the effects can interact with. for example the music reaction.
|
||||
# Idea is: eg a Pi with a soundcard processing input via pyaudio and sending this data to the server. an musicEffect is bind to this input and processing it.
|
||||
# to be as flexible as possible the client registers with a name(sting), a type(string) and the data as an dict. the effect filters these clients by type. jea?
|
||||
|
||||
# rgbStrips register themselves at the rgbStripContoller
|
||||
# the rgbStripController calls the backend Provider's onChange function
|
||||
# when there are new values for the strip
|
||||
from rgbUtils.rgbStripController import rgbStripController
|
||||
rgbStripController = rgbStripController()
|
||||
rgbStripController.start()
|
||||
|
||||
# the effectController handles the effects and pushes the values to the rgbStripContoller
|
||||
# it also calls the backendProvider's onChange function when there are changes made on the effects
|
||||
from rgbUtils.effectController import effectController
|
||||
effectController = effectController(rgbStripController)
|
||||
|
||||
# register effectControllers onRGBStripRegistered and onRGBStripUnregistered handler on the rgbStripContoller to detect added or removed strips
|
||||
rgbStripController.addOnRGBStripRegisteredHandler(effectController.onRGBStripRegistered)
|
||||
rgbStripController.addOnRGBStripUnRegisteredHandler(effectController.onRGBStripUnRegistered)
|
||||
|
||||
# this is a "Backend Provider" that interacts with the effectController and also the rgbStripContoller (via effectController)
|
||||
# this could be seperated in one websocket server for the frontend and one for the rgbStrips
|
||||
# or an other frontend / rgbStrip backend provider not using websockets. you could integrate alexa, phillips hue like lamps or whatever you like!
|
||||
# but then there must be some autoloading of modules in a folder like the effects for easy installing. //todo :)
|
||||
print("starting websocket:8001")
|
||||
import webserver.WebSocketServer as WebSocketServer
|
||||
webSocketThread = WebSocketServer.ThreadedWebSocketServer(effectController,rgbStripController)
|
||||
while not webSocketThread.stopped:
|
||||
time.sleep(1)
|
||||
|
||||
except Exception as e:
|
||||
print(e,traceback.format_exc())
|
||||
finally:
|
||||
print('shutting down the LED-Server')
|
||||
webSocketThread.stop()
|
||||
effectController.stopAll()
|
||||
if __name__=='__main__':
|
||||
main()
|
Binary file not shown.
293
old/audiovis.py
293
old/audiovis.py
@ -1,293 +0,0 @@
|
||||
#
|
||||
# Audio Visualizer RGB lights, v1.0
|
||||
# Author: Jared Sanson
|
||||
# Created: 11/01/2013
|
||||
#
|
||||
# LED strip will be a blue colour when the room is calm,
|
||||
# and progressively turn to red as the room gets noisy.
|
||||
#
|
||||
# The settings below should work fine,
|
||||
# try adjusting the microphone volume/gain before you touch them!
|
||||
#
|
||||
# Connects to an arduino, which controls the RGB led strip.
|
||||
#
|
||||
# Required libraries:
|
||||
# Python 2.7
|
||||
# SciPy : http://www.scipy.org/
|
||||
# Console : http://effbot.org/downloads/#console
|
||||
# pySerial : http://pyserial.sourceforge.net/
|
||||
# pyAudio : http://people.csail.mit.edu/hubert/pyaudio/
|
||||
#
|
||||
|
||||
########## LIBRARIES ###########################################################
|
||||
|
||||
#import console as Console
|
||||
import scipy.fftpack
|
||||
import pyaudio
|
||||
import time
|
||||
import struct
|
||||
import scipy
|
||||
import math
|
||||
from scipy import pi, signal
|
||||
from scipy.fftpack import fft,rfft,rfftfreq,fftfreq
|
||||
|
||||
import serial
|
||||
import struct
|
||||
import time
|
||||
|
||||
|
||||
########## VISUALIZATION SETTINGS ##############################################
|
||||
|
||||
# Loudness detect:
|
||||
CHANNEL = 1 # frequency channel of the FFT to use (see console output to decide)
|
||||
GAIN = 1.5 # audio gain (multiplier)
|
||||
THRESHOLD = 0.15 # audio trigger threshold
|
||||
|
||||
#
|
||||
ATTACK = 0.004 # amount of rowdz increase with loudness
|
||||
DECAY = 0.003 # amount of rowdz decay
|
||||
|
||||
# Brightness:
|
||||
MODULATION = 0.0 # amount of loudness flickering modulation
|
||||
MIN_BRIGHTNESS = 0.5 # minimum brightness
|
||||
|
||||
# Hue mapping:
|
||||
MIN_HUE = 200 # Aqua
|
||||
MAX_HUE = 0 # Red
|
||||
# Note that the hue mapping is actually a power function,
|
||||
# so it will spend more time towards the MIN_HUE, and only a short time towards the MAX_HUE.
|
||||
|
||||
########## APPLICATION SETTINGS ################################################
|
||||
|
||||
#COM_PORT = 'COM3' # COM port to use, or None to run without an arudino
|
||||
COM_PORT = None
|
||||
|
||||
# Audio capture settings
|
||||
SAMPLE_RATE = 44100
|
||||
BUFFER_SIZE = 2**11 # Changing this will change the frequency response of the algorithm
|
||||
#CUTOFF_FREQ = 20000 # LPF freq (Hz)
|
||||
|
||||
|
||||
########## SUPPORT FUNCTIONS ###################################################
|
||||
|
||||
def tobyte(i):
|
||||
"""
|
||||
Clip values that fall outside an unsigned byte
|
||||
"""
|
||||
i = int(i)
|
||||
if i < 0: i = 0
|
||||
if i > 255: i = 255
|
||||
return i
|
||||
|
||||
def limit(val, vmin, vmax):
|
||||
"""
|
||||
Clip values that fall outside vmin & vmax
|
||||
"""
|
||||
if val < vmin: return vmin
|
||||
if val > vmax: return vmax
|
||||
return val
|
||||
|
||||
def mapval(val, minin, maxin, minout, maxout):
|
||||
"""
|
||||
Linear value mapping between in and out
|
||||
"""
|
||||
norm = (val-minin)/(maxin-minin)
|
||||
return norm*(maxout-minout) + minout
|
||||
|
||||
def thresh(val, threshold):
|
||||
"""
|
||||
A bit hard to describe, but this will return 0
|
||||
when val is below the threshold, and will
|
||||
linearly map val to anything higher than threshold.
|
||||
|
||||
The effect being that above the threshold, louder
|
||||
signals will have more of an effect.
|
||||
"""
|
||||
val -= threshold
|
||||
if val < 0: val = 0
|
||||
val *= (1.0/threshold)
|
||||
return val
|
||||
|
||||
def hsv2rgb(h, s, v):
|
||||
"""
|
||||
Convert H,S,V to R,G,B
|
||||
H: 0.0 to 360.0, S&V: 0.0 to 1.0
|
||||
R,G,B: 0 to 255
|
||||
"""
|
||||
h = float(h)
|
||||
s = float(s)
|
||||
v = float(v)
|
||||
h60 = h / 60.0
|
||||
h60f = math.floor(h60)
|
||||
hi = int(h60f) % 6
|
||||
f = h60 - h60f
|
||||
p = v * (1 - s)
|
||||
q = v * (1 - f * s)
|
||||
t = v * (1 - (1 - f) * s)
|
||||
r, g, b = 0, 0, 0
|
||||
if hi == 0: r, g, b = v, t, p
|
||||
elif hi == 1: r, g, b = q, v, p
|
||||
elif hi == 2: r, g, b = p, v, t
|
||||
elif hi == 3: r, g, b = p, q, v
|
||||
elif hi == 4: r, g, b = t, p, v
|
||||
elif hi == 5: r, g, b = v, p, q
|
||||
r, g, b = int(r * 255), int(g * 255), int(b * 255)
|
||||
return r, g, b
|
||||
|
||||
def get_fft(data):
|
||||
"""
|
||||
Run the sample through a FFT, and normalize
|
||||
"""
|
||||
FFT = fft(data)
|
||||
freqs = fftfreq(BUFFER_SIZE*2, 1.0/SAMPLE_RATE)
|
||||
y = 20*scipy.log10(abs(FFT))/ 100
|
||||
|
||||
y = abs(FFT[0:len(FFT)/2])/1000
|
||||
y = scipy.log(y) - 2
|
||||
return (freqs,y)
|
||||
|
||||
ffts=[]
|
||||
def smoothMemory(ffty,degree=3):
|
||||
"""
|
||||
Average samples. Taken from Python FFT tutorial
|
||||
"""
|
||||
global ffts
|
||||
ffts = ffts+[ffty]
|
||||
if len(ffts) <=degree: return ffty
|
||||
ffts=ffts[1:]
|
||||
return scipy.average(scipy.array(ffts),0)
|
||||
|
||||
|
||||
bar_len = 70
|
||||
def update_bars(x,y):
|
||||
"""
|
||||
Display a bar graph in the console
|
||||
"""
|
||||
for i,_ in enumerate(y):
|
||||
a = int(min(max(y[i],0),1)*bar_len)
|
||||
|
||||
label = str(x[i])[:5]
|
||||
label = ' '*(5-len(label)) + label
|
||||
|
||||
text = label +'[' + ('#'*a) + (' '*(bar_len-a)) + ']' + str(i)
|
||||
print(0, i+3, text)
|
||||
|
||||
|
||||
########## SUPPORT CLASSES #####################################################
|
||||
|
||||
class RGBController(object):
|
||||
"""
|
||||
Communicates with the Arduino
|
||||
"""
|
||||
def __init__(self, port):
|
||||
self.ser = serial.Serial(port)
|
||||
time.sleep(1)
|
||||
|
||||
def update(self, color):
|
||||
#print "Update color to (R:%d G:%d B:%d)" % (color[0], color[1], color[2])
|
||||
r = tobyte(color[0])
|
||||
g = tobyte(color[1])
|
||||
b = tobyte(color[2])
|
||||
packet = struct.pack('cBBB', 'X', r,g,b)
|
||||
#print packet
|
||||
self.ser.write(packet)
|
||||
|
||||
|
||||
########## CODE ################################################################
|
||||
|
||||
TITLE = "Audio Visualizer"
|
||||
INK = 0x1f
|
||||
|
||||
# Set up console
|
||||
#console = Console.getconsole(0)
|
||||
#console.title(TITLE)
|
||||
#console.text(0, 0, chr(0xfe) + ' ' + TITLE + ' ' + chr(0xfe))
|
||||
#console.text(0, 1, chr(0xcd) * 80)
|
||||
|
||||
# Create LPF filter
|
||||
# norm_pass = 2*math.pi*CUTOFF_FREQ/SAMPLE_RATE
|
||||
# norm_stop = 1.5*norm_pass
|
||||
# (N, Wn) = signal.buttord(wp=norm_pass, ws=norm_stop, gpass=2, gstop=30, analog=0)
|
||||
# (b, a) = signal.butter(N, Wn, btype='low', analog=0, output='ba')
|
||||
# b *= 1e3
|
||||
|
||||
|
||||
# Open Audio stream (uses default audio adapter)
|
||||
p = pyaudio.PyAudio()
|
||||
stream = p.open(format=pyaudio.paInt16,channels=1,rate=SAMPLE_RATE,input=True,output=False,frames_per_buffer=BUFFER_SIZE)
|
||||
|
||||
# Open comms port to Arduino
|
||||
if COM_PORT:
|
||||
RGB = RGBController(COM_PORT)
|
||||
|
||||
|
||||
########## GLOBAL VARIABLES ####################################################
|
||||
|
||||
red = 0
|
||||
green = 0
|
||||
blue = 0
|
||||
|
||||
noisiness = 0 # Noisiness level
|
||||
|
||||
########## VISUALIZATION LOOP ##################################################
|
||||
|
||||
while True:
|
||||
## Part 1: Sample Audio ##
|
||||
|
||||
# Get audio sample
|
||||
buf = stream.read(BUFFER_SIZE)
|
||||
data = scipy.array(struct.unpack("%dh"%(BUFFER_SIZE),buf))
|
||||
|
||||
## Part 2: Perform FFT and Filtering ##
|
||||
|
||||
# Filter incoming data
|
||||
#data = signal.lfilter(b,a,data)
|
||||
|
||||
# Generate FFT
|
||||
freqs,y = get_fft(data)
|
||||
|
||||
# Average the samples
|
||||
#y=smoothMemory(y,3)
|
||||
|
||||
# Normalize
|
||||
y = y / 5
|
||||
|
||||
# Average into chunks of N
|
||||
N = 25
|
||||
yy = [scipy.average(y[n:n+N]) for n in range(0, len(y), N)]
|
||||
yy = yy[:len(yy)/2] # Discard half of the samples, as they are mirrored
|
||||
|
||||
|
||||
## Part 3: Algorithm ##
|
||||
|
||||
# Loudness detection
|
||||
loudness = thresh(yy[CHANNEL] * GAIN, THRESHOLD)
|
||||
|
||||
# Noisiness meter
|
||||
noisiness -= DECAY
|
||||
noisiness += loudness * ATTACK
|
||||
noisiness = limit(noisiness, 0.0, 1.0)
|
||||
|
||||
# Brightness modulation
|
||||
modulation = MODULATION * limit(noisiness, 0.0, 1.0)
|
||||
brightness = limit(MIN_BRIGHTNESS + (loudness * modulation), 0.0, 1.0)
|
||||
|
||||
# Hue modulation (power relationship)
|
||||
mapping = (10 ** limit(noisiness, 0.0, 1.0)) / 10.0
|
||||
mapping = mapping * 1.1 - 0.11
|
||||
hue = mapval(mapping, 0.0, 1.0, MIN_HUE, MAX_HUE)
|
||||
|
||||
# Display colour
|
||||
red,green,blue = hsv2rgb(hue,1.0,brightness)
|
||||
if COM_PORT:
|
||||
RGB.update([int(red),int(green),int(blue)])
|
||||
|
||||
# Debug information
|
||||
labels = list(yy)
|
||||
bars = list(yy)
|
||||
labels.extend( ['-', 'loud','noise','map', 'brght', '-', 'hue','red','grn','blue'])
|
||||
bars.extend( [0, loudness, noisiness, mapping, brightness, 0, hue/360.0, red/255.0,green/255.0,blue/255.0])
|
||||
|
||||
update_bars(labels,bars)
|
||||
|
||||
########## #####################################################################
|
@ -1,78 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from os import path
|
||||
|
||||
#RGBStrip("Unter Theke",
|
||||
# wiringpi 24,-> BCM 19 -> GPIO. 24 -> kabel fehlt
|
||||
# wiringpi 4, -> BCM 23 -> GPIO. 4 -> Mosfet LAHMT (rot)
|
||||
# wiringpi 0, -> BCM 17 -> GPIO. 0 -> Mosfet TOT (weiß)
|
||||
#RGBStrip("Über Theke",
|
||||
# wiringpi 3, -> BCM 22 -> GPIO. 3
|
||||
# wiringpi 23,-> BCM 13 -> GPIO. 23
|
||||
# wiringpi 2, -> BCM 27 -> GPIO 2
|
||||
|
||||
#RGBStrip("Fensterbank",
|
||||
# wiringpi 21,-> BCM 5 -> GPIO. 21
|
||||
# wiringpi 25,-> BCM 26 -> GPIO. 25
|
||||
# wiringpi 22,-> BCM 6 -> GPIO. 22
|
||||
|
||||
#use the BCM pin numbers here
|
||||
"""
|
||||
from rgbUtils.RGBStrip import RGBStrip
|
||||
rgbStrips = [
|
||||
#RGBStrip("Test Dahem", 4, 17 , 22),
|
||||
RGBStrip("Unter Theke", 20, 16 , 21),
|
||||
RGBStrip("Über Theke", 22, 13, 27),
|
||||
RGBStrip("Fensterbank", 5, 26, 6)
|
||||
]
|
||||
|
||||
# setup PRi.GPIO
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
# setup PWM for the rgbStrips
|
||||
for RGBStrip in self.getRGBStrips():
|
||||
RGBStrip.init()
|
||||
|
||||
"""
|
||||
"""
|
||||
Use WS2812B Strips:
|
||||
an arduino (uno tested) must be connected via usb while running
|
||||
the sketch in the root folder. Define the Strip as masterstrip and
|
||||
use parts of it as a rgbStrip
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from rgbUtils.WS2812MasterStrip import WS2812MasterStrip
|
||||
from rgbUtils.WS2812Strip import WS2812Strip
|
||||
# LED_COUNT must be the same than in the arduino sketch
|
||||
ws2812master = WS2812MasterStrip('/dev/ttyACM0',150)
|
||||
rgbStrips = [
|
||||
WS2812Strip("LEDS 1-50",1,50,ws2812master),
|
||||
WS2812Strip("LEDS 51-100",51,100,ws2812master),
|
||||
WS2812Strip("LEDS 101-150",101,150,ws2812master),
|
||||
]
|
||||
|
||||
"""
|
||||
def drange(start, stop, step):
|
||||
r = start
|
||||
while r < stop:
|
||||
yield r
|
||||
r += step
|
||||
|
||||
rgbStrips = []
|
||||
for x in drange(1,150,10):
|
||||
rgbStrips.append(WS2812Strip(str(x)+"-"+str(x),x,x,ws2812master))
|
||||
"""
|
||||
|
||||
# int Port to bind. ports < 1024 need sudo access
|
||||
SocketBindPort = 8000
|
||||
|
||||
# Maximum brightness of the RGB Strips Max Value is 100, can be set lower if the strips are too bright.
|
||||
# (What I do not think, RGB Strips are never too bright)
|
||||
# MaxBrightness = 100
|
||||
|
||||
# GPIO Pins that are working with pwm. At the moment A and B models only
|
||||
# todo: check rpi version and add the missing pins if there are more that can be used
|
||||
AllowedGPIOPins = [3, 5, 7, 8, 10, 11, 12, 13, 15, 19, 21, 22, 23, 24, 26]
|
||||
|
||||
BASE_PATH = path.dirname(path.realpath(__file__))
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,240 +0,0 @@
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.EffectParameter import slider, colorpicker
|
||||
from rgbUtils.debug import debug
|
||||
import time
|
||||
|
||||
import sys
|
||||
import numpy
|
||||
from rgbUtils.pyAudioRecorder import pyAudioRecorder
|
||||
from time import perf_counter, sleep
|
||||
from random import randint, shuffle
|
||||
|
||||
class musikEffect(BaseEffect):
|
||||
name = "musikEffect"
|
||||
desc = "LED-Band *sollte* nach musik blinken"
|
||||
|
||||
|
||||
|
||||
# Something that will be used to show descriptions and value options
|
||||
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
|
||||
# if the parameters can be toggeled by a button/checkbox/slider/whatever
|
||||
effectParameters = [
|
||||
# radio(\
|
||||
# "Shuffle LED to Freq Order",\
|
||||
# "Off -> Mapping ",\
|
||||
# [\
|
||||
# [0,255,255,"red"],\
|
||||
# [0,255,255,"green"],\
|
||||
# [0,255,255,"blue"]\
|
||||
# ]\
|
||||
# ),\
|
||||
# slider(\
|
||||
# "Effect Brightnes",\
|
||||
# "Choose a brightness for your LED's",\
|
||||
# [\
|
||||
# [0,100,100,"brightness"],\
|
||||
# ]\
|
||||
# )\
|
||||
]
|
||||
|
||||
def init(self):
|
||||
|
||||
self.fft_random_keys = [0,1,2,3]
|
||||
self.fft_random = [0,0,0,0]
|
||||
|
||||
# used by strobe()
|
||||
self.lastmode = 0
|
||||
|
||||
self.recorderClient = pyAudioRecorder.recorderClient()
|
||||
self.rgbStripController.pyAudioRecorder.registerRecorderClient(self.recorderClient)
|
||||
|
||||
return
|
||||
|
||||
#loop effect as long as not stopped
|
||||
def effect(self):
|
||||
self.plot_audio_and_detect_beats()
|
||||
#self.freqtocolor()
|
||||
#if(time.time() - self.lastTime >= 0.002):
|
||||
#for RGBStrip in self.effectRGBStrips():
|
||||
# r= RGBStrip.red-1
|
||||
# if(r<0):
|
||||
# r=0
|
||||
# g= RGBStrip.green-1
|
||||
# if(g<0):
|
||||
# g=0
|
||||
# b= RGBStrip.blue-1
|
||||
# if(b<0):
|
||||
# b=0
|
||||
# RGBStrip.RGB(r,g,b)
|
||||
#self.lastTime = time.time()
|
||||
sleep(.001)
|
||||
|
||||
def end(self):
|
||||
self.rgbStripController.pyAudioRecorder.unregisterRecorderClient(self.recorderClient)
|
||||
|
||||
def plot_audio_and_detect_beats(self):
|
||||
if not self.rgbStripController.pyAudioRecorder.has_new_audio:
|
||||
return
|
||||
|
||||
# get x and y values from FFT
|
||||
xs, ys = self.rgbStripController.pyAudioRecorder.fft()
|
||||
|
||||
# calculate average for all frequency ranges
|
||||
y_avg = numpy.mean(ys)
|
||||
|
||||
|
||||
|
||||
#low_freq = numpy.mean(ys[20:47])
|
||||
#mid_freq = numpy.mean(ys[88:115])
|
||||
#hig_freq = numpy.mean(ys[156:184])
|
||||
|
||||
low_freq = numpy.mean(ys[0:67])
|
||||
mid_freq = numpy.mean(ys[68:135])
|
||||
hig_freq = numpy.mean(ys[136:204])
|
||||
|
||||
#get the maximum of all freq
|
||||
if len(self.y_max_freq_avg_list) < 250 or y_avg > 10 and numpy.amax([low_freq,mid_freq,hig_freq])/2 > numpy.amin(self.y_max_freq_avg_list):
|
||||
self.y_max_freq_avg_list.append(numpy.amax([low_freq,mid_freq,hig_freq]))
|
||||
|
||||
y_max = numpy.amax(self.y_max_freq_avg_list)
|
||||
|
||||
#y_max = numpy.mean([numpy.amax(ys),y_max])
|
||||
#print(low_freq,mid_freq,hig_freq,y_max)
|
||||
|
||||
for i,item in enumerate([low_freq,mid_freq,hig_freq]):
|
||||
if item is None:
|
||||
item = 0
|
||||
|
||||
low = round(low_freq/(y_max+10)*255)
|
||||
mid = round(mid_freq/(y_max+10)*255)
|
||||
hig = round(hig_freq/(y_max+10)*255)
|
||||
#print(low,mid,hig,y_max, numpy.amax(ys), y_avg)
|
||||
#print("------")
|
||||
|
||||
self.fft_random[self.fft_random_keys[0]] = low
|
||||
self.fft_random[self.fft_random_keys[1]] = mid
|
||||
self.fft_random[self.fft_random_keys[2]] = hig
|
||||
self.fft_random[self.fft_random_keys[3]] = 0
|
||||
|
||||
# calculate low frequency average
|
||||
#low_freq = [ys[i] for i in range(len(xs)) if xs[i] < 1000]
|
||||
low_freq = ys[0:47]
|
||||
low_freq_avg = numpy.mean(low_freq)
|
||||
|
||||
if len(self.low_freq_avg_list) < 250 or low_freq_avg > numpy.amin(self.low_freq_avg_list)/2:
|
||||
self.low_freq_avg_list.append(low_freq_avg)
|
||||
cumulative_avg = numpy.mean(self.low_freq_avg_list)
|
||||
|
||||
bass = low_freq[:int(len(low_freq)/2)]
|
||||
bass_avg = numpy.mean(bass)
|
||||
#print("bass: {:.2f} vs cumulative: {:.2f}".format(bass_avg, cumulative_avg))
|
||||
|
||||
# check if there is a beat
|
||||
# song is pretty uniform across all frequencies
|
||||
if (y_avg > y_avg/5 and (bass_avg > cumulative_avg * 1.8 or (low_freq_avg < y_avg * 1.2 and bass_avg > cumulative_avg))):
|
||||
#self.prev_beat
|
||||
curr_time = perf_counter()
|
||||
|
||||
# print(curr_time - self.prev_beat)
|
||||
if curr_time - self.prev_beat > 60/360*2: # 180 BPM max
|
||||
shuffle(self.fft_random_keys)
|
||||
|
||||
# change the button color
|
||||
#self.beats_idx += 1
|
||||
#self.strobe()
|
||||
#print("beat {}".format(self.beats_idx))
|
||||
#print("bass: {:.2f} vs cumulative: {:.2f}".format(bass_avg, cumulative_avg))
|
||||
|
||||
#print(self.fft_random)
|
||||
# change the button text
|
||||
bpm = int(60 / (curr_time - self.prev_beat))
|
||||
if len(self.bpm_list) < 4:
|
||||
if bpm > 60:
|
||||
self.bpm_list.append(bpm)
|
||||
else:
|
||||
bpm_avg = int(numpy.mean(self.bpm_list))
|
||||
if abs(bpm_avg - bpm) < 35:
|
||||
self.bpm_list.append(bpm)
|
||||
print("bpm: {:d}".format(bpm_avg))
|
||||
|
||||
# reset the timer
|
||||
self.prev_beat = curr_time
|
||||
if y_avg > 10:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(
|
||||
self.fft_random[0],
|
||||
self.fft_random[1],
|
||||
self.fft_random[2]
|
||||
)
|
||||
|
||||
# shorten the cumulative list to account for changes in dynamics
|
||||
if len(self.low_freq_avg_list) > 500:
|
||||
self.low_freq_avg_list = self.low_freq_avg_list[250:]
|
||||
#print("REFRESH!!")
|
||||
|
||||
# shorten the cumulative list to account for changes in dynamics
|
||||
if len(self.y_max_freq_avg_list ) > 500:
|
||||
self.y_max_freq_avg_list = self.y_max_freq_avg_list[250:]
|
||||
print("--REFRESH y_max_freq_avg_list")
|
||||
|
||||
# keep two 8-counts of BPMs so we can maybe catch tempo changes
|
||||
if len(self.bpm_list) > 24:
|
||||
self.bpm_list = self.bpm_list[8:]
|
||||
|
||||
# reset song data if the song has stopped
|
||||
if y_avg < 10:
|
||||
self.bpm_list = []
|
||||
self.low_freq_avg_list = []
|
||||
print("new song")
|
||||
self.off()
|
||||
|
||||
self.rgbStripController.pyAudioRecorder.newAudio = False
|
||||
# print(self.bpm_list)
|
||||
|
||||
def strobe(self):
|
||||
x = randint(0,5)
|
||||
while x is self.lastmode:
|
||||
x = randint(0,5)
|
||||
|
||||
self.lastmode = x
|
||||
r = 255#randint(0,255)
|
||||
g = 255#randint(0,255)
|
||||
b = 255#randint(0,255)
|
||||
if x is 0:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(r,g,0)
|
||||
if x is 1:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,g,b)
|
||||
if x is 2:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(r,0,b)
|
||||
if x is 3:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(r,0,0)
|
||||
if x is 4:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,g,0)
|
||||
if x is 5:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,0,b)
|
||||
if x is 6:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(r,g,b)
|
||||
|
||||
def off(self):
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,0,0)
|
||||
|
||||
def left_rotate(self,arr):
|
||||
if not arr:
|
||||
return arr
|
||||
|
||||
left_most_element = arr[0]
|
||||
length = len(arr)
|
||||
|
||||
for i in range(length - 1):
|
||||
arr[i], arr[i + 1] = arr[i + 1], arr[i]
|
||||
|
||||
arr[length - 1] = left_most_element
|
||||
return arr
|
@ -1,23 +0,0 @@
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.debug import debug
|
||||
|
||||
import time
|
||||
|
||||
class offEffect(BaseEffect):
|
||||
name = "offEffect"
|
||||
desc = "LED-Band *sollte* nicht an sein"
|
||||
|
||||
def effect(self):
|
||||
time.sleep(1)
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onRGBStripAdded(self,rgbStrip):
|
||||
rgbStrip.RGB(0,0,0,)
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onEffectParameterValuesUpdated(self):
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,0,0)
|
||||
return
|
@ -1,67 +0,0 @@
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.EffectParameter import slider, colorpicker
|
||||
from rgbUtils.debug import debug
|
||||
import time
|
||||
|
||||
class onEffect(BaseEffect):
|
||||
name = "onEffect"
|
||||
desc = "LED-Band *sollte* an sein"
|
||||
|
||||
# Something that will be used to show descriptions and value options
|
||||
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
|
||||
# if the parameters can be toggeled by a button/checkbox/slider/whatever
|
||||
effectParameters = [
|
||||
colorpicker(\
|
||||
"Effect Color",\
|
||||
"Choose a color for your LED's",\
|
||||
[\
|
||||
[0,255,255,"red"],\
|
||||
[0,255,255,"green"],\
|
||||
[0,255,255,"blue"]\
|
||||
]\
|
||||
),\
|
||||
slider(\
|
||||
"Effect Brightnes",\
|
||||
"Choose a brightness for your LED's",\
|
||||
[\
|
||||
[0,100,100,"brightness"],\
|
||||
]\
|
||||
)\
|
||||
]
|
||||
|
||||
def init(self):
|
||||
return
|
||||
|
||||
#loop effect as long as not stopped
|
||||
def effect(self):
|
||||
time.sleep(1)
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onRGBStripAdded(self,rgbStrip):
|
||||
rgbStrip.RGB(\
|
||||
# colorpicker red currentvalue
|
||||
self.effectParameterValues[0][0],\
|
||||
# colorpicker green currentvalue
|
||||
self.effectParameterValues[0][1],\
|
||||
# colorpicker blue currentvalue
|
||||
self.effectParameterValues[0][2],\
|
||||
# slider brightness currentvalue
|
||||
self.effectParameterValues[1][0]\
|
||||
)
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a params are updated
|
||||
def onEffectParameterValuesUpdated(self):
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
#print(self.effectParameterValues)
|
||||
RGBStrip.RGB(\
|
||||
# colorpicker red currentvalue
|
||||
self.effectParameterValues[0][0],\
|
||||
# colorpicker green currentvalue
|
||||
self.effectParameterValues[0][1],\
|
||||
# colorpicker blue currentvalue
|
||||
self.effectParameterValues[0][2],\
|
||||
# slider brightness currentvalue
|
||||
self.effectParameterValues[1][0]\
|
||||
)
|
@ -1,67 +0,0 @@
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.debug import debug
|
||||
import time
|
||||
|
||||
class rainbowEffect(BaseEffect):
|
||||
name = "rainbowEffect"
|
||||
desc = "LED-Band *sollte* rainbowEffect sein"
|
||||
|
||||
def init(self):
|
||||
self.i=0
|
||||
self.speed = 1
|
||||
self.helligkeit = 100
|
||||
|
||||
#loop effect as long as not stopped
|
||||
def effect(self):
|
||||
debug(self)
|
||||
if self.i < 3*255*self.speed:
|
||||
c = self.wheel_color(self.i,self.speed)
|
||||
#print("r: "+ str(round(c[0]/100*helligkeit,2))+" g: "+str(round(c[1]/100*helligkeit,2))+" b: "+str(round(c[2]/100*helligkeit,2)))
|
||||
for rgbStrip in self.effectRGBStrips():
|
||||
#print(c[0],c[1],c[2])
|
||||
rgbStrip.RGB(c[0],c[1],c[2],self.helligkeit)
|
||||
time.sleep(0.05)
|
||||
self.i =self.i +1
|
||||
else:
|
||||
self.i=0
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onRGBStripAdded(self,rgbStrip):
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onEffectParameterValuesUpdated(self):
|
||||
return
|
||||
|
||||
def wheel_color(self,position,speed = 5):
|
||||
"""Get color from wheel value (0 - 765)"""
|
||||
if position < 0:
|
||||
position = 0
|
||||
if position > 765*speed:
|
||||
position = 765*speed
|
||||
|
||||
if position < (255*speed):
|
||||
r = (255*speed) - position % (255*speed)
|
||||
g = position % (255*speed)
|
||||
b = 0
|
||||
elif position < (510*speed):
|
||||
g = (255*speed) - position % (255*speed)
|
||||
b = position % (255*speed)
|
||||
r = 0
|
||||
else:
|
||||
b = (255*speed) - position % (255*speed)
|
||||
r = position % (255*speed)
|
||||
g = 0
|
||||
|
||||
return [r/speed, g/speed, b/speed]
|
||||
|
||||
# def wheel_color_2(self,r=255,g=0,b=0):
|
||||
# if r<255:
|
||||
# r=r+1
|
||||
# elif g<255:
|
||||
# g=g+1
|
||||
# elif r=255:
|
||||
|
||||
# elif b<255:
|
||||
# b=b+1
|
||||
|
@ -1,42 +0,0 @@
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.debug import debug
|
||||
from random import randint
|
||||
import time
|
||||
|
||||
class strobeEffect(BaseEffect):
|
||||
name = "strobeEffect"
|
||||
desc = "*Strobe*"
|
||||
|
||||
def init(self):
|
||||
self.state = True
|
||||
|
||||
#loop effect as long as not stopped
|
||||
def effect(self):
|
||||
y = -1
|
||||
x = -1
|
||||
if self.state:
|
||||
while x is y:
|
||||
x = randint(0,2)
|
||||
if x is 0:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(255,255,0)
|
||||
if x is 1:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,255,255)
|
||||
if x is 2:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(255,0,255)
|
||||
self.state = False
|
||||
else:
|
||||
for RGBStrip in self.effectRGBStrips():
|
||||
RGBStrip.RGB(0,0,0)
|
||||
self.state = True
|
||||
time.sleep(0.0015)
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onRGBStripAdded(self,rgbStrip):
|
||||
return
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onEffectParameterValuesUpdated(self):
|
||||
return
|
@ -1,10 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import sys
|
||||
import time
|
||||
import pyaudio
|
||||
|
||||
p=pyaudio.PyAudio() # start the PyAudio class
|
||||
for i in range(p.get_device_count()):
|
||||
devinfo = p.get_device_info_by_index(i)
|
||||
print(i,devinfo["name"])
|
BIN
old/loader.pyc
BIN
old/loader.pyc
Binary file not shown.
@ -1,91 +0,0 @@
|
||||
import time
|
||||
import threading
|
||||
import copy
|
||||
from rgbUtils.debug import debug
|
||||
|
||||
class BaseEffect(threading.Thread):
|
||||
|
||||
# The Name and the Description of the Effect,
|
||||
# should be overwritten by the inheritancing Effect
|
||||
name = "Undefined"
|
||||
desc = "No Description"
|
||||
|
||||
# Something that will be used to show descriptions and value options
|
||||
# of the parameters the effect will accept, in a way, that eg the webclient can decide,
|
||||
# if the parameters can be toggeled by a button/checkbox/slider/whatever
|
||||
effectParameters = []
|
||||
|
||||
stop = False
|
||||
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.effectRGBStripList = []
|
||||
|
||||
# when a strip is added or removed or the options change, the thread will not restart,
|
||||
# the changes are pushed to the thread at livetime. so avoid log running loops without
|
||||
# accessing getRGBStrips and getEffectParams. It could happen, that a new effect for example already uses
|
||||
# a rgbStip while the loop of the old effect is running and has not got the changes.
|
||||
def run(self):
|
||||
self.effectParameterValues = []
|
||||
for effectParameterIndex, effectParameter in enumerate(self.effectParameters):
|
||||
self.effectParameterValues.append([])
|
||||
for option in effectParameter.options:
|
||||
self.effectParameterValues[effectParameterIndex].append(option[2])
|
||||
|
||||
print(self.effectParameterValues)
|
||||
self.init()
|
||||
while not self.stop:
|
||||
# run the effect in endless while
|
||||
self.effect()
|
||||
self.end()
|
||||
|
||||
# Init is called bevor the loop, use setEffectParams for init values
|
||||
# and access them in the effect with getEffectParams
|
||||
def init(self):
|
||||
return
|
||||
|
||||
# see run(): never save effectRGBStrips() as a variable and access it as often as possible
|
||||
# to avoid two effects accessing the rgbStrip
|
||||
def effect(self):
|
||||
while 1:
|
||||
debug("ET "+self.name+" effect() function needs to be replaced in inheritancing Effect")
|
||||
|
||||
# called when the effect is stopped
|
||||
def end(self):
|
||||
return
|
||||
|
||||
# when called the effect loop will stop and the thread can be terminated
|
||||
def stopEffect(self):
|
||||
self.stop = True
|
||||
|
||||
# the effect itself will know its own strips. i don't know if it would be better if the effectController self
|
||||
# should have this list, but then i must do something like nested arrays, naah.
|
||||
def addRGBStrip(self,rgbStrip):
|
||||
self.effectRGBStripList.append(rgbStrip)
|
||||
self.onRGBStripAdded(rgbStrip)
|
||||
|
||||
# remove a strip, if the effect has no more strips, the effect thread guardian will kill it
|
||||
def removeRGBStrip(self,rgbStrip):
|
||||
self.effectRGBStripList.remove(rgbStrip)
|
||||
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onRGBStripAdded(self,rgbStrip):
|
||||
return
|
||||
# for overriding by the effect, when a strip is added
|
||||
def onEffectParameterValuesUpdated(self):
|
||||
return
|
||||
|
||||
# returns a list of the RGBStrips used by this effect
|
||||
def effectRGBStrips(self):
|
||||
return self.effectRGBStripList
|
||||
|
||||
def addEffectParameter(self,effectParameter):
|
||||
self.effectParameters.append(effectParameter)
|
||||
|
||||
# set Params as descriped in getParamsDescription()
|
||||
def updateEffectParameterValues(self,effectParameterIndex, effectParameterValues):
|
||||
print("updateEffectParameterValues",effectParameterIndex,effectParameterValues)
|
||||
for effectParameterValue in effectParameterValues:
|
||||
if self.effectParameters[int(effectParameterIndex)].testValue(int(effectParameterValue),int(effectParameterValues[effectParameterValue])):
|
||||
self.effectParameterValues[int(effectParameterIndex)][int(effectParameterValue)] = int(effectParameterValues[effectParameterValue])
|
||||
self.onEffectParameterValuesUpdated()
|
@ -1,42 +0,0 @@
|
||||
import threading
|
||||
|
||||
class effectParameter(object):
|
||||
# The Name and the Description of the EffectParameter,
|
||||
# should be overwritten by the inheritancing EffectParameter
|
||||
name="Undefined"
|
||||
desc = "No Description"
|
||||
|
||||
# In the order you expect the options to be set
|
||||
# [
|
||||
# [min/off,max/on,current,"description"],
|
||||
# [min/off,max/on,current,"description"],
|
||||
# [min/off,max/on,current,"description"],
|
||||
# ]
|
||||
options = []
|
||||
|
||||
def __init__(self,name,desc,initOptions = []):
|
||||
self.name = name
|
||||
self.desc = desc
|
||||
self.options = initOptions
|
||||
|
||||
# check if the given values are plausible
|
||||
def testValue(self,index,value):
|
||||
if value >= self.options[index][0] \
|
||||
and value <= self.options[index][1]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class colorpicker(effectParameter):
|
||||
name="UndefinedColorpicker"
|
||||
desc="No Description"
|
||||
type="colorpicker"
|
||||
|
||||
# check if the given values are plausible
|
||||
def testValue(self,index,value):
|
||||
return True
|
||||
|
||||
class slider(effectParameter):
|
||||
name="UndefinedSlider"
|
||||
desc="No Description"
|
||||
type="slider"
|
@ -1,98 +0,0 @@
|
||||
try:
|
||||
import RPi.GPIO as GPIO
|
||||
except ImportError:
|
||||
import rgbUtils.fakeGPIO as GPIO
|
||||
from rgbUtils.debug import debug
|
||||
class RGBStrip:
|
||||
STRIP_NAME = None
|
||||
|
||||
issetup = False
|
||||
|
||||
effectClassInstance = None
|
||||
|
||||
# GPIO PWM Frequenz
|
||||
hertz = 100
|
||||
|
||||
RED_PIN = None
|
||||
GREEN_PIN = None
|
||||
BLUE_PIN = None
|
||||
|
||||
RED_PWM = None
|
||||
GREEN_PWM = None
|
||||
BLUE_PWM = None
|
||||
|
||||
|
||||
def __init__(self,STRIP_NAME,RED_PIN,GREEN_PIN,BLUE_PIN):
|
||||
self.STRIP_NAME = STRIP_NAME
|
||||
self.RED_PIN = RED_PIN
|
||||
self.GREEN_PIN = GREEN_PIN
|
||||
self.BLUE_PIN = BLUE_PIN
|
||||
|
||||
def init(self):
|
||||
if not self.issetup:
|
||||
debug("setting up")
|
||||
# setup RED
|
||||
GPIO.setup(self.RED_PIN, GPIO.OUT)
|
||||
self.RED_PWM = GPIO.PWM(self.RED_PIN, self.hertz)
|
||||
self.RED_PWM.start(0)
|
||||
# setup GREEN
|
||||
GPIO.setup(self.GREEN_PIN, GPIO.OUT)
|
||||
self.GREEN_PWM = GPIO.PWM(self.GREEN_PIN, self.hertz)
|
||||
self.GREEN_PWM.start(0)
|
||||
# setup BLUE
|
||||
GPIO.setup(self.BLUE_PIN, GPIO.OUT)
|
||||
self.BLUE_PWM = GPIO.PWM(self.BLUE_PIN, self.hertz)
|
||||
self.BLUE_PWM.start(0)
|
||||
|
||||
self.issetup = True
|
||||
|
||||
def RGB(self,red,green,blue,brightness = 100):
|
||||
|
||||
if(red < 0):
|
||||
red = 0
|
||||
if(red > 255):
|
||||
red = 255
|
||||
|
||||
if(green < 0):
|
||||
green = 0
|
||||
if(green > 255):
|
||||
green = 255
|
||||
|
||||
if(blue < 0):
|
||||
blue = 0
|
||||
if(blue > 255):
|
||||
blue = 255
|
||||
|
||||
if(brightness < 0):
|
||||
brightness = 0
|
||||
if(brightness > 100):
|
||||
brightness = 100
|
||||
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.RED_PWM.ChangeDutyCycle(round((red/255*100)/100*brightness,2))
|
||||
self.GREEN_PWM.ChangeDutyCycle(round((green/255*100)/100*brightness,2))
|
||||
self.BLUE_PWM.ChangeDutyCycle(round((blue/255*100)/100*brightness,2))
|
||||
|
||||
def stop(self):
|
||||
self.RED_PWM.ChangeDutyCycle(0)
|
||||
self.GREEN_PWM.ChangeDutyCycle(0)
|
||||
self.BLUE_PWM.ChangeDutyCycle(0)
|
||||
self.RED_PWM.stop()
|
||||
self.GREEN_PWM.stop()
|
||||
self.BLUE_PWM.stop()
|
||||
|
||||
|
||||
|
||||
# I have to be sure that a rgbStip is only used by one Effect at once, so i save the current running Effect Class Object
|
||||
# in the rgbStip object.
|
||||
def setEffectClassInstance(self,effectClass):
|
||||
debug("RGBStrip "+ self.STRIP_NAME + " Effect is now " + str(effectClass))
|
||||
self.effectClassInstance = effectClass
|
||||
|
||||
def getEffectClassInstance(self):
|
||||
return self.effectClassInstance
|
||||
|
||||
|
||||
|
@ -1,95 +0,0 @@
|
||||
from rgbUtils.debug import debug
|
||||
import uuid
|
||||
|
||||
class RGBStrip:
|
||||
# name = the name off the the strip, defined by the client connecting to the server
|
||||
# uid = unique id, if the strip sends one, use this (later maybe, or never, whatever)
|
||||
# lenght = the lenght off the strip, for future use of eg WS2812b strips, will be 1 by default
|
||||
def __init__(self,name,onValuesUpdateHandler,lenght=1):
|
||||
# UID should be updateable later, or not?
|
||||
# when updating, be sure it does not exist
|
||||
self.STRIP_UID = str(uuid.uuid4())
|
||||
self.STRIP_NAME = name
|
||||
self.STRIP_LEGHT = lenght
|
||||
|
||||
self.onValuesUpdateHandler = onValuesUpdateHandler
|
||||
|
||||
self.red = [0]*self.STRIP_LEGHT
|
||||
self.green = [0]*self.STRIP_LEGHT
|
||||
self.blue = [0]*self.STRIP_LEGHT
|
||||
|
||||
def RGB(self,red,green,blue,brightness = 100):
|
||||
|
||||
if(red < 0):
|
||||
red = 0
|
||||
if(red > 255):
|
||||
red = 255
|
||||
|
||||
if(green < 0):
|
||||
green = 0
|
||||
if(green > 255):
|
||||
green = 255
|
||||
|
||||
if(blue < 0):
|
||||
blue = 0
|
||||
if(blue > 255):
|
||||
blue = 255
|
||||
|
||||
if(brightness < 0):
|
||||
brightness = 0
|
||||
if(brightness > 100):
|
||||
brightness = 100
|
||||
|
||||
for x in range(self.STRIP_LEGHT):
|
||||
self.red[x] = int(red/100*brightness)
|
||||
self.green[x] = int(green/100*brightness)
|
||||
self.blue[x] = int(blue/100*brightness)
|
||||
|
||||
self.onValuesUpdateHandler(self)
|
||||
|
||||
def WS2812b(self,id,red,green,blue,brightness=100):
|
||||
if id < 0 and id > self.STRIP_LEGHT:
|
||||
print(self.STRIP_NAME," is max ",self.STRIP_LEGHT," Pixels long!")
|
||||
return
|
||||
else:
|
||||
if(red < 0):
|
||||
red = 0
|
||||
if(red > 255):
|
||||
red = 255
|
||||
|
||||
if(green < 0):
|
||||
green = 0
|
||||
if(green > 255):
|
||||
green = 255
|
||||
|
||||
if(blue < 0):
|
||||
blue = 0
|
||||
if(blue > 255):
|
||||
blue = 255
|
||||
|
||||
if(brightness < 0):
|
||||
brightness = 0
|
||||
if(brightness > 100):
|
||||
brightness = 100
|
||||
|
||||
self.red[id] = int(red/100*brightness)
|
||||
self.green[id] = int(green/100*brightness)
|
||||
self.blue[id] = int(blue/100*brightness)
|
||||
|
||||
self.onValuesUpdateHandler(self)
|
||||
|
||||
|
||||
def off(self):
|
||||
for x in range(self.STRIP_LEGHT):
|
||||
self.red[x] = 0
|
||||
self.green[x] = 0
|
||||
self.blue[x] = 0
|
||||
|
||||
self.onValuesUpdateHandler(self)
|
||||
|
||||
def getData(self):
|
||||
self.hasNewData = False
|
||||
return [self.red,self.green,self.blue]
|
||||
|
||||
|
||||
|
@ -1,46 +0,0 @@
|
||||
# The Master Strip that can be used as multiple RGBStrips or later as one for Special Effects
|
||||
# see https://github.com/mdaffin/PyNeoPixel for arduino ino
|
||||
|
||||
import struct
|
||||
import serial
|
||||
import time
|
||||
|
||||
|
||||
class WS2812MasterStrip:
|
||||
|
||||
def __init__(self,port,LED_COUNT):
|
||||
|
||||
#serial connection
|
||||
self.port = port
|
||||
self.ser = serial.Serial(self.port, 115200, timeout=1)
|
||||
self.command_count = 0
|
||||
|
||||
self.LED_COUNT = LED_COUNT
|
||||
|
||||
self.lock = False
|
||||
|
||||
self.setPixelColorRange(1,LED_COUNT, 0, 0, 0)
|
||||
|
||||
def setPixelColorRange(self, pixelstart, pixelstop, red, green, blue):
|
||||
# locking while sending serial data, because multiple threads
|
||||
# could try to send data at the same time
|
||||
while self.lock:
|
||||
#time.sleep(0.001)
|
||||
return
|
||||
self.lock = True
|
||||
|
||||
for pixel in [pixelstart,pixelstop]:
|
||||
if pixelstart > self.LED_COUNT:
|
||||
print("WS2812MasterStrip@"+self.port+" Strip is only "+self.LED_COUNT+" pixels long")
|
||||
return
|
||||
pixelstart = pixelstart - 1
|
||||
pixelstop = pixelstop - 1
|
||||
message = struct.pack('>BBBHHBBB', ord(':'), self.command_count, ord('r'), pixelstart, pixelstop, red, green, blue)
|
||||
self.command_count += 1
|
||||
if self.command_count >=255:
|
||||
self.command_count = 0
|
||||
#print(message)
|
||||
self.ser.write(message)
|
||||
response = self.ser.readline()
|
||||
self.lock = False
|
||||
#print(response)
|
@ -1,61 +0,0 @@
|
||||
from rgbUtils.debug import debug
|
||||
from rgbUtils.RGBStrip import RGBStrip
|
||||
|
||||
# The WS2812Strip must have the same behavior as the 12v rgb strip,
|
||||
# plus some extras for these type of strips only.
|
||||
# A WS1812 Strip can be initialised as multiple RGB Strips by defining
|
||||
# the start and the end led's. lets's see how that goes
|
||||
class WS2812Strip(RGBStrip):
|
||||
STRIP_NAME = None
|
||||
|
||||
master = None
|
||||
FIRST_LED = None
|
||||
LAST_LED = None
|
||||
|
||||
def __init__(self,STRIP_NAME,FIRST_LED,LAST_LED,WS2812B_MASTER_STRIP):
|
||||
self.STRIP_NAME = STRIP_NAME
|
||||
self.master = WS2812B_MASTER_STRIP
|
||||
self.FIRST_LED = FIRST_LED
|
||||
self.LAST_LED = LAST_LED
|
||||
|
||||
# init the WS2812 part. since the master sets all pixel to 0 in init,
|
||||
# we have nothing to do here.
|
||||
def init(self):
|
||||
if not self.issetup:
|
||||
debug("setting up")
|
||||
self.issetup = True
|
||||
|
||||
def RGB(self,red,green,blue,brightness = 100):
|
||||
|
||||
if(red < 0):
|
||||
red = 0
|
||||
if(red > 255):
|
||||
red = 255
|
||||
|
||||
if(green < 0):
|
||||
green = 0
|
||||
if(green > 255):
|
||||
green = 255
|
||||
|
||||
if(blue < 0):
|
||||
blue = 0
|
||||
if(blue > 255):
|
||||
blue = 255
|
||||
green = 255
|
||||
|
||||
if(brightness < 0):
|
||||
brightness = 0
|
||||
if(brightness > 255):
|
||||
brightness = 100
|
||||
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.master.setPixelColorRange(self.FIRST_LED,self.LAST_LED, int(round(red/100*brightness)), int(round(green/100*brightness)), int(round(blue/100*brightness)))
|
||||
|
||||
|
||||
def stop(self):
|
||||
self.master.setPixelColorRange(self.FIRST_LED,self.LAST_LED, 0, 0,0)
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
def debug(string):
|
||||
return
|
||||
print(string)
|
@ -1,174 +0,0 @@
|
||||
# import offEffect
|
||||
from effects.offEffect import offEffect
|
||||
|
||||
from rgbUtils.debug import debug
|
||||
|
||||
from rgbUtils.BaseEffect import BaseEffect
|
||||
from rgbUtils.RGBStrip import RGBStrip
|
||||
|
||||
import time
|
||||
import threading
|
||||
import os
|
||||
import sys
|
||||
|
||||
#
|
||||
# handles all the effects:
|
||||
# - start/stop effects
|
||||
# - changes parameters of specific effects
|
||||
# - moves the rgbStrips to the effects
|
||||
# - runs a guardian that detects dead effectThreads and moves Strips to offEffect
|
||||
#
|
||||
class effectController:
|
||||
|
||||
# list of current running effects
|
||||
effectThreads = []
|
||||
|
||||
offEffectThreadObject = None
|
||||
|
||||
# maybe i will seperate this later
|
||||
onControllerChangeHandler = []
|
||||
|
||||
def __init__(self,rgbStripController):
|
||||
self.rgbStripController = rgbStripController
|
||||
# load the effects
|
||||
self.effectsList = self.getEffectsListFromDir()
|
||||
# start the offEffect by default
|
||||
self.offEffectThreadObject = self.startEffect(offEffect,[])
|
||||
# - a bit of failover handling, remove dead threads from effectThread array
|
||||
# - move strips without an effect to the offEffect
|
||||
self.effectGuardian = self.effectGuardian(self)
|
||||
self.effectGuardian.start()
|
||||
|
||||
# starts a effect by given class, rgbStrips and params ([[index,[param,param,param]],[index,[param,param,param]]])
|
||||
def startEffect(self, effectClass: BaseEffect, rgbStrips: list, params: list = []):
|
||||
newEffect = effectClass()
|
||||
newEffect.start()
|
||||
self.updateEffectParameters(newEffect, params)
|
||||
self.effectThreads.append(newEffect)
|
||||
|
||||
for rgbStrip in rgbStrips:
|
||||
self.moveRGBStripToEffectThread(rgbStrip, newEffect)
|
||||
|
||||
# if the effectThread has no strips, we stop it and remove it.
|
||||
if len(newEffect.effectRGBStrips()) == 0:
|
||||
newEffect.stopEffect()
|
||||
self.effectThreads.remove(newEffect)
|
||||
|
||||
self.noticeControllerChange()
|
||||
return newEffect
|
||||
|
||||
# returns all effectClasses but offEffect, since offEffect will never be killed
|
||||
# and should not be running twice
|
||||
def getEffects(self):
|
||||
# alle außer offEffect
|
||||
return self.effectsList
|
||||
|
||||
# returns all running effectThreads
|
||||
def getEffectThreads(self):
|
||||
return self.effectThreads
|
||||
|
||||
# returns a list of the RGBStrips used by this effect
|
||||
def getEffectRGBStrips(self, effectThreadObject: BaseEffect):
|
||||
return effectThreadObject.effectRGBStrips()
|
||||
|
||||
# move a rgbStip to a running effectThread
|
||||
def moveRGBStripToEffectThread(self, rgbStrip: RGBStrip, effectThreadObject: BaseEffect):
|
||||
# cycle throught all effects and
|
||||
# remove Strip from effect if added
|
||||
for et in self.effectThreads:
|
||||
if rgbStrip in et.effectRGBStrips():
|
||||
et.removeRGBStrip(rgbStrip)
|
||||
if effectThreadObject.isAlive():
|
||||
effectThreadObject.addRGBStrip(rgbStrip)
|
||||
# check if any effectThread has no more rgbStrips and if so, stop it
|
||||
|
||||
# if the effectThread has no more strips, we stop it and remove it.
|
||||
for x, effectThread in enumerate(self.effectThreads):
|
||||
if len(effectThread.effectRGBStrips()) == 0 and x is not 0:
|
||||
effectThread.stopEffect()
|
||||
self.effectThreads.remove(effectThread)
|
||||
self.noticeControllerChange()
|
||||
|
||||
# updates parameter of a running effectThread
|
||||
def updateEffectParameters(self, effectThreadObject: BaseEffect, effectParameters):
|
||||
for effectParameter in effectParameters:
|
||||
effectThreadObject.updateEffectParameterValues(
|
||||
effectParameter[0], effectParameter[1])
|
||||
self.noticeControllerChange()
|
||||
|
||||
# stops all effectThreads and set the rgbStrips to off
|
||||
def stopAll(self):
|
||||
debug("effectController stopAll()")
|
||||
for effectThread in self.effectThreads:
|
||||
effectThread.stopEffect()
|
||||
debug("effectController killed "+str(effectThread))
|
||||
|
||||
self.effectGuardian.stop()
|
||||
|
||||
time.sleep(0.5)
|
||||
# GPIO.cleanup()
|
||||
|
||||
# inform the controllerChangeHandler to update the client
|
||||
def noticeControllerChange(self):
|
||||
for controllerChangeHandler in self.onControllerChangeHandler:
|
||||
controllerChangeHandler()
|
||||
|
||||
# add onControllerChangeHandler
|
||||
def addOnControllerChangeHandler(self, hander):
|
||||
print("addOnControllerChangeHandler", str(hander))
|
||||
self.onControllerChangeHandler.append(hander)
|
||||
# send data to this client
|
||||
hander()
|
||||
|
||||
# remove onControllerChangeHandler
|
||||
def removeOnControllerChangeHandler(self, hander):
|
||||
print("removeOnControllerChangeHandler", str(hander))
|
||||
self.onControllerChangeHandler.remove(hander)
|
||||
|
||||
# automaticly loads all modules from effects subdir and adds them to the list of effects if they have the BaseEffect as subclass
|
||||
def getEffectsListFromDir(self):
|
||||
effectsList = []
|
||||
for raw_module in os.listdir(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.pardir),"effects"))):
|
||||
|
||||
if raw_module == '__init__.py' or raw_module == 'offEffect.py' or raw_module[-3:] != '.py':
|
||||
continue
|
||||
effectModule = __import__("effects."+raw_module[:-3], fromlist=[raw_module[:-3]])
|
||||
effectClass = getattr(effectModule, raw_module[:-3])
|
||||
if issubclass(effectClass,BaseEffect):
|
||||
effectsList.append(effectClass)
|
||||
print("Loaded effects: ",effectsList)
|
||||
return effectsList
|
||||
|
||||
def onRGBStripRegistered(self,rgbStrip):
|
||||
self.offEffectThreadObject.addRGBStrip(rgbStrip)
|
||||
self.noticeControllerChange()
|
||||
|
||||
def onRGBStripUnRegistered(self,rgbStrip):
|
||||
# cycle throught all effects and
|
||||
# remove Strip from effect if added
|
||||
for et in self.effectThreads:
|
||||
if rgbStrip in et.effectRGBStrips():
|
||||
et.removeRGBStrip(rgbStrip)
|
||||
self.noticeControllerChange()
|
||||
|
||||
class effectGuardian(threading.Thread):
|
||||
def __init__(self, effectController):
|
||||
threading.Thread.__init__(self)
|
||||
self.effectController = effectController
|
||||
self.stopped = False
|
||||
|
||||
def run(self):
|
||||
while not self.stopped:
|
||||
for effectThread in self.effectController.effectThreads:
|
||||
# if Thread was killed by something else, we remove it from the list
|
||||
if not effectThread.isAlive():
|
||||
for rgbStrip in effectThread.effectRGBStrips():
|
||||
self.effectController.moveRGBStripToEffectThread(rgbStrip,self.effectController.offEffectThreadObject)
|
||||
self.effectController.effectThreads.remove(effectThread)
|
||||
print("effectController:effectGuardian removed dead Thread " +
|
||||
str(effectThread) + ". There must be an error in code!")
|
||||
self.effectController.noticeControllerChange()
|
||||
time.sleep(1)
|
||||
|
||||
def stop(self):
|
||||
self.stopped = True
|
@ -1,49 +0,0 @@
|
||||
"""
|
||||
Convert the effectController function outputs to json format
|
||||
"""
|
||||
|
||||
def responseHandler(effectController,rgbStripController,data):
|
||||
if "startEffect" in data:
|
||||
enabledRGBStrips = []
|
||||
for rgbStrip in rgbStripController.getRGBStrips():
|
||||
for rgbStripJsonArray in data['startEffect']['rgbStrips']:
|
||||
if rgbStrip.STRIP_UID in rgbStripJsonArray[0] and rgbStripJsonArray[1]:
|
||||
enabledRGBStrips.append(rgbStrip)
|
||||
|
||||
effectController.startEffect(effectController.getEffects()[data['startEffect']['effect']],enabledRGBStrips,data['startEffect']['params'])
|
||||
if "moveRGBStripToEffectThread" in data:
|
||||
for rgbStrip in rgbStripController.getRGBStrips():
|
||||
if rgbStrip.STRIP_UID in data['moveRGBStripToEffectThread']['rgbStrip']:
|
||||
effectController.moveRGBStripToEffectThread( \
|
||||
rgbStrip, \
|
||||
effectController.getEffectThreads()[data['moveRGBStripToEffectThread']['effectThread']] \
|
||||
)
|
||||
if "effectThreadChangeEffectParam" in data:
|
||||
effectController.updateEffectParameters(\
|
||||
effectController.getEffectThreads()[data['effectThreadChangeEffectParam']['effectThread']], \
|
||||
data['effectThreadChangeEffectParam']['params']
|
||||
)
|
||||
return 'ok'
|
||||
|
||||
# return json of all configured effects (except offEffect) with their paramDescriptions
|
||||
def getEffects(effectController):
|
||||
result = {}
|
||||
for x, effect in enumerate(effectController.getEffects()):
|
||||
effectParams = {}
|
||||
for y, effectParam in enumerate(effect.effectParameters):
|
||||
effectParams[y] = {'index': y,'type': effectParam.type, 'name': effectParam.name, 'desc': effectParam.desc, 'options': effectParam.options}
|
||||
result[x] = {'index': x, 'name': effect.name, 'desc': effect.desc, 'effectParams': effectParams}
|
||||
return result
|
||||
|
||||
# return json of all running effectThreads with their active rgbStrips and params
|
||||
def getEffectThreads(effectController):
|
||||
result = {}
|
||||
for x, effectThread in enumerate(effectController.getEffectThreads()):
|
||||
effectRGBStrips = {}
|
||||
for effectRGBStrip in effectController.getEffectRGBStrips(effectThread):
|
||||
effectRGBStrips[effectRGBStrip.STRIP_UID] = {'index': effectRGBStrip.STRIP_UID, 'name': effectRGBStrip.STRIP_NAME}
|
||||
effectParams = {}
|
||||
for z, effectParam in enumerate(effectThread.effectParameters):
|
||||
effectParams[z] = {'index': z,'type': effectParam.type, 'name': effectParam.name, 'desc': effectParam.desc, 'options': effectParam.options, 'values': effectThread.effectParameterValues[z]}
|
||||
result[x] = {'index': x, 'name': effectThread.name, 'desc': effectThread.desc,'activeRGBStips': effectRGBStrips, 'dump': str(effectThread), 'effectParams': effectParams}
|
||||
return result
|
@ -1,113 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Fake RPi.GPIO package
|
||||
'''
|
||||
#______________________________________________________________________
|
||||
# imports
|
||||
|
||||
#______________________________________________________________________
|
||||
# globals
|
||||
BCM = 'BCM'
|
||||
BOARD = 'BOARD'
|
||||
|
||||
OUT = 'OUT'
|
||||
IN = 'IN'
|
||||
|
||||
LOW = 'LOW'
|
||||
HIGH = 'HIGH'
|
||||
|
||||
FALLING = 'FALLING'
|
||||
RISING = 'RISING'
|
||||
|
||||
PUD_UP = 'PUD_UP'
|
||||
PUD_DOWN = 'PUD_DOWN'
|
||||
|
||||
RPI_INFO = {'INFO': 'Fake GPIO, ¬¬', 'P1_REVISION': 'Fake GPIO, ¬¬'}
|
||||
|
||||
VERSION = '0.2.0a0'
|
||||
|
||||
#______________________________________________________________________
|
||||
# VERBOSE
|
||||
VERBOSE = False
|
||||
|
||||
#______________________________________________________________________
|
||||
# functions wrapper/ base fucntion
|
||||
def print_data(func):
|
||||
def verbose(*args, **kwargs):
|
||||
if VERBOSE:
|
||||
print(func.__name__, args, kwargs)
|
||||
return verbose
|
||||
|
||||
#______________________________________________________________________
|
||||
# PWM class
|
||||
class PWM(object):
|
||||
|
||||
@print_data
|
||||
def __init__(self, channel, frequency):
|
||||
self.channel = channel
|
||||
self.frequency = frequency
|
||||
self.dc = 0
|
||||
|
||||
@print_data
|
||||
def start(self, dc):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def ChangeFrequency(self, freq):
|
||||
self.frequency = freq
|
||||
|
||||
@print_data
|
||||
def ChangeDutyCycle(self, dc):
|
||||
self.dc = dc
|
||||
|
||||
@print_data
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
#______________________________________________________________________
|
||||
# functions
|
||||
|
||||
@print_data
|
||||
def setmode(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def setup(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def output(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def input(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def cleanup(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def wait_for_edge(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def event_detected(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def add_event_detect(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def add_event_callback(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def remove_event_detect(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@print_data
|
||||
def setwarnings(*args, **kwargs):
|
||||
pass
|
@ -1,140 +0,0 @@
|
||||
#
|
||||
# The idea is to have only one thread accessing the audio input source instead
|
||||
# of every music enabled thread itself. also, different fuctions calculating
|
||||
# frequencys and so on shoud run in own threads to the leds get more updates
|
||||
#
|
||||
# in history one thread was calculating bpm, freqence average and max values in one thread
|
||||
# before updating the leds, what the pi was a bit slow for and you cloud count every update
|
||||
# of the leds
|
||||
|
||||
# i think most of it is from https://github.com/shunfu/python-beat-detector/
|
||||
|
||||
|
||||
import numpy
|
||||
import scipy
|
||||
import pyaudio
|
||||
import threading
|
||||
|
||||
import time
|
||||
|
||||
|
||||
class pyAudioRecorder:
|
||||
"""Simple, cross-platform class to record from the default input device."""
|
||||
|
||||
def __init__(self):
|
||||
self.RATE = 44100
|
||||
self.BUFFERSIZE = 2**12
|
||||
self.secToRecord = .1
|
||||
self.kill_threads = False
|
||||
self.has_new_audio = False
|
||||
self.setup()
|
||||
|
||||
# since the server only can handly one input (for now) this thread will calculate
|
||||
# some basic things for the musicEffectsThreads, so they can update the leds more often.
|
||||
# it is always posible to catch the fft() function and do your own thing in your musikEffect.
|
||||
|
||||
# calculate bpm, this is the same for all clientThreads
|
||||
self.beats_idx = 0
|
||||
|
||||
self.bpm_list = []
|
||||
self.prev_beat = time.perf_counter()
|
||||
self.low_freq_avg_list = []
|
||||
|
||||
self.lastTime = time.time()
|
||||
|
||||
|
||||
self.recorderClients = []
|
||||
|
||||
def setup(self):
|
||||
self.buffers_to_record = int(
|
||||
self.RATE * self.secToRecord / self.BUFFERSIZE)
|
||||
if self.buffers_to_record == 0:
|
||||
self.buffers_to_record = 1
|
||||
self.samples_to_record = int(self.BUFFERSIZE * self.buffers_to_record)
|
||||
self.chunks_to_record = int(self.samples_to_record / self.BUFFERSIZE)
|
||||
self.sec_per_point = 1. / self.RATE
|
||||
|
||||
self.p = pyaudio.PyAudio()
|
||||
# start the PyAudio class
|
||||
for i in range(self.p.get_device_count()):
|
||||
devinfo = self.p.get_device_info_by_index(i)
|
||||
print(i, devinfo["name"])
|
||||
# make sure the default input device is broadcasting the speaker output
|
||||
# there are a few ways to do this
|
||||
# e.g., stereo mix, VB audio cable for windows, soundflower for mac
|
||||
self.in_stream = self.p.open(format=pyaudio.paInt16,
|
||||
channels=1,
|
||||
rate=self.RATE,
|
||||
input=True,
|
||||
frames_per_buffer=self.BUFFERSIZE)
|
||||
print("Using default input device: {:s}".format(
|
||||
self.p.get_default_input_device_info()['name']))
|
||||
|
||||
self.audio = numpy.empty(
|
||||
(self.chunks_to_record * self.BUFFERSIZE), dtype=numpy.int16)
|
||||
|
||||
def close(self):
|
||||
print("pyAudioRecorder closed")
|
||||
self.kill_threads = True
|
||||
self.p.close(self.in_stream)
|
||||
|
||||
### RECORDING AUDIO ###
|
||||
|
||||
def get_audio(self):
|
||||
"""get a single buffer size worth of audio."""
|
||||
audio_string = self.in_stream.read(self.BUFFERSIZE)
|
||||
return numpy.fromstring(audio_string, dtype=numpy.int16)
|
||||
|
||||
def record(self):
|
||||
while not self.kill_threads:
|
||||
for i in range(self.chunks_to_record):
|
||||
self.audio[i*self.BUFFERSIZE:(i+1)
|
||||
* self.BUFFERSIZE] = self.get_audio()
|
||||
self.has_new_audio = True
|
||||
|
||||
def start(self):
|
||||
print("pyAudioRecorder started")
|
||||
self.t = threading.Thread(target=self.record)
|
||||
self.t.start()
|
||||
|
||||
### MATH ###
|
||||
|
||||
def downsample(self, data, mult):
|
||||
"""Given 1D data, return the binned average."""
|
||||
overhang = len(data) % mult
|
||||
if overhang:
|
||||
data = data[:-overhang]
|
||||
data = numpy.reshape(data, (len(data) / mult, mult))
|
||||
data = numpy.average(data, 1)
|
||||
return data
|
||||
|
||||
def fft(self, data=None, trim_by=10, log_scale=False, div_by=100):
|
||||
if not data:
|
||||
data = self.audio.flatten()
|
||||
left, right = numpy.split(numpy.abs(numpy.fft.fft(data)), 2)
|
||||
ys = numpy.add(left, right[::-1])
|
||||
if log_scale:
|
||||
ys = numpy.multiply(20, numpy.log10(ys))
|
||||
xs = numpy.arange(self.BUFFERSIZE/2, dtype=float)
|
||||
if trim_by:
|
||||
i = int((self.BUFFERSIZE/2) / trim_by)
|
||||
ys = ys[:i]
|
||||
xs = xs[:i] * self.RATE / self.BUFFERSIZE
|
||||
if div_by:
|
||||
ys = ys / float(div_by)
|
||||
return xs, ys
|
||||
|
||||
### multithreading things ###
|
||||
|
||||
def registerRecorderClient(self,recorderClient):
|
||||
self.recorderClients.append(recorderClient)
|
||||
|
||||
def unregisterRecorderClient(self,recorderClient):
|
||||
self.recorderClients.remove(recorderClient)
|
||||
|
||||
class recorderClient(threading.Thread):
|
||||
def __init__():
|
||||
# toggle to true on beat, false when client got the value
|
||||
self.onBeat = False
|
||||
# when registering the client i want to be able to define how long the avg list should be
|
||||
self.y_max_freq_avg_list = []
|
@ -1,54 +0,0 @@
|
||||
from rgbUtils.RGBStrip import RGBStrip
|
||||
import time
|
||||
import threading
|
||||
import json
|
||||
class rgbStripController(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
self.rgbStrips = []
|
||||
self.onRGBStripRegisteredHandler = []
|
||||
self.onRGBStripUnRegisteredHandler = []
|
||||
|
||||
def registerRGBStrip(self,rgbStripName,onValuesUpdateHandler):
|
||||
# maybe we can use an unique id if the strip reconnects later, eg push the uid
|
||||
# to the client on first connect and if he reconnects he sould send it back again.
|
||||
# the wmos could use the mac adress, if there is a python script it can save the uid
|
||||
# in a file or so.
|
||||
strip = RGBStrip(rgbStripName,onValuesUpdateHandler)
|
||||
self.rgbStrips.append(strip)
|
||||
self.noticeRGBStripRegisteredHandler(strip)
|
||||
return strip
|
||||
|
||||
def unregisterRGBStrip(self,strip):
|
||||
self.rgbStrips.remove(strip)
|
||||
self.noticeRGBStripUnRegisteredHandler(strip)
|
||||
|
||||
# returns all registered rgbStips
|
||||
def getRGBStrips(self):
|
||||
return self.rgbStrips
|
||||
|
||||
# inform all onRGBStripRegisteredHandler about the new RGBStrip
|
||||
def noticeRGBStripRegisteredHandler(self,rgbStrip):
|
||||
for hander in self.onRGBStripRegisteredHandler:
|
||||
hander(rgbStrip)
|
||||
|
||||
# add onRGBStripRegisteredHandler
|
||||
def addOnRGBStripRegisteredHandler(self, function):
|
||||
self.onRGBStripRegisteredHandler.append(function)
|
||||
|
||||
# remove onRGBStripRegisteredHandler
|
||||
def removeOnRGBStripRegisteredHandler(self, function):
|
||||
self.onRGBStripRegisteredHandler.remove(function)
|
||||
|
||||
# inform all onRGBStripUnRegisteredHandder about the removed RGBStrip
|
||||
def noticeRGBStripUnRegisteredHandler(self,rgbStrip):
|
||||
for hander in self.onRGBStripUnRegisteredHandler:
|
||||
hander(rgbStrip)
|
||||
|
||||
# add onRGBStripUnRegisteredHandler
|
||||
def addOnRGBStripUnRegisteredHandler(self, function):
|
||||
self.onRGBStripUnRegisteredHandler.append(function)
|
||||
|
||||
# remove onRGBStripUnRegisteredHandler
|
||||
def removeOnRGBStripUnRegisteredHandler(self, function):
|
||||
self.onRGBStripUnRegisteredHandler.remove(function)
|
@ -1,16 +0,0 @@
|
||||
def getRGBData(rgbStrip):
|
||||
result = {}
|
||||
data = rgbStrip.getData()
|
||||
red = data[0]
|
||||
green = data[1]
|
||||
blue = data[2]
|
||||
for x in range(len(red)):
|
||||
result[x] = {'red': red[x], 'green': green[x], 'blue': blue[x]}
|
||||
return result
|
||||
|
||||
# return json of all configured rgbStrips
|
||||
def getRGBStrips(rgbStripController):
|
||||
result = {}
|
||||
for rgbStrip in rgbStripController.getRGBStrips():
|
||||
result[rgbStrip.STRIP_UID] = {'index': rgbStrip.STRIP_UID, 'name': rgbStrip.STRIP_NAME}
|
||||
return result
|
File diff suppressed because it is too large
Load Diff
31
old/test.sh
31
old/test.sh
@ -1,31 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Unter Theke - 1 Streifen
|
||||
# Kabel Sw Grau Blau Rot
|
||||
# LEDband Masse Rot# Blau Gruen
|
||||
# GPIO 15 11 16
|
||||
# BCM 8 26 10
|
||||
#
|
||||
# Ueber Theke 3 Streifen
|
||||
# Kabel sw Rot Weiss Gelb
|
||||
# LEDband Masse Rot Blau Gruen#(LAngsam an aus)
|
||||
# GPIO 7 1 2
|
||||
# BCM 7 12 13
|
||||
#
|
||||
# Fensterbank - 2 Streifen
|
||||
# Kabel Sw Gelb Weiss Rot
|
||||
# LEDband Masse Rot Blau Gruen
|
||||
# GPIO 8 10 0
|
||||
# BCM 3 24 11
|
||||
|
||||
function e {
|
||||
read -n1 -r -p "Press for $2 on" key
|
||||
gpio mode $1 out
|
||||
gpio write $1 1
|
||||
read -n1 -r -p "Press any key to turn off..." key
|
||||
gpio write $1 0
|
||||
read -n1 -r -p "Press any key to move to next..." key
|
||||
}
|
||||
|
||||
e 7 "UT R"
|
||||
e 1 "UT B"
|
||||
e 2 "UT G"
|
60
old/test2.py
60
old/test2.py
@ -1,60 +0,0 @@
|
||||
import pyaudio
|
||||
import numpy
|
||||
import wave
|
||||
import subprocess
|
||||
#import matplotlib.pyplot as plt
|
||||
|
||||
numpy.set_printoptions(suppress=True) # don't use scientific notation
|
||||
|
||||
CHUNK = 32 # number of data points to read at a time
|
||||
RATE = 44100 # time resolution of the recording device (Hz)
|
||||
|
||||
class SimpleBeatDetection:
|
||||
"""
|
||||
Simple beat detection algorithm from
|
||||
http://archive.gamedev.net/archive/reference/programming/features/beatdetection/index.html
|
||||
"""
|
||||
def __init__(self, history = 43):
|
||||
self.local_energy = numpy.zeros(history) # a simple ring buffer
|
||||
self.local_energy_index = 0 # the index of the oldest element
|
||||
|
||||
def detect_beat(self, signal):
|
||||
|
||||
samples = signal.astype(numpy.int) # make room for squares
|
||||
# optimized sum of squares, i.e faster version of (samples**2).sum()
|
||||
instant_energy = numpy.dot(samples, samples) / float(0xffffffff) # normalize
|
||||
|
||||
local_energy_average = self.local_energy.mean()
|
||||
local_energy_variance = self.local_energy.var()
|
||||
|
||||
beat_sensibility = (-0.0025714 * local_energy_variance) + 1.15142857
|
||||
beat = instant_energy > beat_sensibility * local_energy_average
|
||||
|
||||
self.local_energy[self.local_energy_index] = instant_energy
|
||||
self.local_energy_index -= 1
|
||||
if self.local_energy_index < 0:
|
||||
self.local_energy_index = len(self.local_energy) - 1
|
||||
|
||||
return beat
|
||||
|
||||
sb = SimpleBeatDetection()
|
||||
|
||||
p=pyaudio.PyAudio() # start the PyAudio class
|
||||
# for i in range(p.get_device_count()):
|
||||
# devinfo = p.get_device_info_by_index(i)
|
||||
# print(i,devinfo["name"])
|
||||
|
||||
|
||||
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,
|
||||
frames_per_buffer=CHUNK) #uses default input device
|
||||
|
||||
while True:
|
||||
data = stream.read(CHUNK)
|
||||
signal = numpy.frombuffer(data, numpy.int16)
|
||||
if(sb.detect_beat(signal)):
|
||||
i+1
|
||||
print(i,"Beat!")
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
p.terminate()
|
@ -1,84 +0,0 @@
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
import rgbUtils.RGBStipContollerJsonConverter as rgbCJson
|
||||
from pathlib import Path
|
||||
from mimetypes import guess_type
|
||||
from os import curdir, sep
|
||||
import json
|
||||
|
||||
from rgbUtils.debug import debug
|
||||
|
||||
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
rgbC = None
|
||||
|
||||
def __init__(self, rgbC, *args, **kwargs):
|
||||
self.rgbC = rgbC
|
||||
# BaseHTTPRequestHandler calls do_GET **inside** __init__ !!!
|
||||
# So we have to call super().__init__ after setting attributes.
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def do_GET(self):
|
||||
try:
|
||||
if "/api/" in self.path:
|
||||
# set response header application/json when calling the api
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "application/json")
|
||||
self.end_headers()
|
||||
|
||||
if "/getEffects" in self.path:
|
||||
self.wfile.write(json.dumps({'result': rgbCJson.getEffects(self.rgbC)}).encode(encoding='utf_8'))
|
||||
|
||||
if "/getRGBStrips" in self.path:
|
||||
self.wfile.write(json.dumps({'result': rgbCJson.getRGBStrips(self.rgbC)}).encode(encoding='utf_8'))
|
||||
|
||||
if "/getEffectThreads" in self.path:
|
||||
self.wfile.write(json.dumps({'result': rgbCJson.getEffectThreads(self.rgbC)}).encode(encoding='utf_8'))
|
||||
|
||||
else:
|
||||
#Get files as requested from htdocs, set mimetype
|
||||
request = curdir + sep + "htdocs" + self.path
|
||||
debug(request)
|
||||
|
||||
if Path(request).is_dir():
|
||||
debug("isdir: "+request)
|
||||
if not request[-1:] == "/":
|
||||
debug("no /: "+request)
|
||||
request += "/"
|
||||
request += "index.html"
|
||||
debug("fi request: "+request)
|
||||
|
||||
mimetype = guess_type(request)[0]
|
||||
f = open(request, 'rb')
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", mimetype)
|
||||
self.end_headers()
|
||||
self.wfile.write(f.read())
|
||||
f.close()
|
||||
except IOError:
|
||||
self.send_error(404,'File Not Found: %s' % self.path)
|
||||
|
||||
def do_POST(self):
|
||||
try:
|
||||
if "/api/" in self.path:
|
||||
self.send_response(200)
|
||||
data = json.loads(self.rfile.read(int(self.headers['Content-Length'])).decode('utf-8'))
|
||||
self.end_headers()
|
||||
print(data)
|
||||
if "/startEffect" in self.path:
|
||||
enabledRGBStrips = []
|
||||
for rgbStripObject in data['rgbStrips']:
|
||||
if rgbStripObject[1]:
|
||||
enabledRGBStrips.append(self.rgbC.getRGBStrips()[int(rgbStripObject[0])])
|
||||
|
||||
self.rgbC.startEffect(self.rgbC.getEffects()[data['effect']],enabledRGBStrips,data['params'])
|
||||
if "/moveRGBStripToEffectThread" in self.path:
|
||||
print(data)
|
||||
self.rgbC.moveRGBStripToEffectThread(self.rgbC.getRGBStrips()[data['rgbStrip']],self.rgbC.getEffectThreads()[data['effectThread']])
|
||||
if "/updateEffectParams" in self.path:
|
||||
result = {}
|
||||
print(data)
|
||||
self.wfile.write("OK".encode(encoding='utf_8'))
|
||||
except IOError:
|
||||
self.send_error(404,'File Not Found: %s' % self.path)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
@ -1,17 +0,0 @@
|
||||
# HTTPServer Things
|
||||
from webserver.HTTPRequestHandler import HTTPRequestHandler
|
||||
from threading import Thread
|
||||
from http.server import HTTPServer
|
||||
from functools import partial
|
||||
import config
|
||||
|
||||
class ThreadedHTTPServer(Thread):
|
||||
def __init__(self,rgbC):
|
||||
Thread.__init__(self)
|
||||
self.rgbC = rgbC
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
httpd = HTTPServer(("", config.SocketBindPort),partial(HTTPRequestHandler, self.rgbC))
|
||||
httpd.serve_forever()
|
@ -1,115 +0,0 @@
|
||||
import json
|
||||
|
||||
from rgbUtils import effectControllerJsonHandler
|
||||
from rgbUtils import rgbStripControllerJsonHandler
|
||||
from webserver.SimpleWebSocketServer import WebSocket
|
||||
|
||||
import traceback
|
||||
import logging
|
||||
|
||||
|
||||
CLIENT_TYPE_CONTROLLER = 0
|
||||
CLIENT_TYPE_STRIPE = 1
|
||||
CLIENT_TYPE_RECORDER = 2
|
||||
|
||||
|
||||
#class WebSocketError(Exception):
|
||||
# pass
|
||||
|
||||
|
||||
class HTTPWebSocketsHandler(WebSocket):
|
||||
|
||||
def __init__(self, effectController, rgbStripController, *args, **kwargs):
|
||||
self.effectController = effectController
|
||||
self.rgbStripController = rgbStripController
|
||||
self.client_type = CLIENT_TYPE_CONTROLLER
|
||||
self.rgbStrip = None
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def handleMessage(self):
|
||||
try:
|
||||
print(self.address, self.data)
|
||||
data = json.loads(self.data)
|
||||
# Client Registration on the Websocket Server
|
||||
# maybe it would be better to use a websocket server thread for each client type,
|
||||
# can be done in future if there is too much latency
|
||||
if "register_client_type" in data:
|
||||
# the controler type, add handler on RGBStripContoller and send the current state of the controller
|
||||
if int(data['register_client_type']) is CLIENT_TYPE_CONTROLLER:
|
||||
self.client_type = CLIENT_TYPE_CONTROLLER
|
||||
# add effectController onControllerChangeHandler to get changes in the effectController eg start/stop effects, parameter updates, moved strips
|
||||
# register rgbStripController onRGBStripRegistered/UnRegistered handler to get noticed about new rgbStrips is not necessary
|
||||
# since we will get noticed from the effectController when it added the rgbStrip to the offEffect
|
||||
self.effectController.addOnControllerChangeHandler(self.onChange)
|
||||
# register new Stripes
|
||||
elif int(data['register_client_type']) is CLIENT_TYPE_STRIPE and "client_name" in data:
|
||||
self.client_type = CLIENT_TYPE_STRIPE
|
||||
# registers the strip with websocket object and name. the onRGBStripValueUpdate(rgbStrip) is called by
|
||||
# by the rgbStrip when an effectThread updates it
|
||||
# the self.rgbStrip variable is used to unregister the strip only
|
||||
self.rgbStrip = self.rgbStripController.registerRGBStrip(data["client_name"],self.onRGBStripValueUpdate)
|
||||
# register new Audio Recorders
|
||||
elif int(data['register_client_type']) is CLIENT_TYPE_RECORDER:
|
||||
self.client_type = CLIENT_TYPE_RECORDER
|
||||
|
||||
# controller responses are handled by the effectControllerJsonHandler
|
||||
if self.client_type is CLIENT_TYPE_CONTROLLER:
|
||||
response = effectControllerJsonHandler.responseHandler(self.effectController, self.rgbStripController, data)
|
||||
self.sendMessage(
|
||||
json.dumps({
|
||||
'response': response
|
||||
})
|
||||
)
|
||||
return
|
||||
# the stripe should usualy not send any data, i do not why it should...
|
||||
elif self.client_type is CLIENT_TYPE_STRIPE:
|
||||
return
|
||||
# audio recorder responses are handled by the effectControllerJsonHandler
|
||||
elif self.client_type is CLIENT_TYPE_RECORDER:
|
||||
return
|
||||
except Exception as e:
|
||||
print(e, traceback.format_exc())
|
||||
|
||||
# notice about connects in terminal, the client has to register itself, see handleMessage
|
||||
def handleConnected(self):
|
||||
print(self.address, 'connected')
|
||||
|
||||
# unregister the onChangeHandler
|
||||
# for now this function is not called when a client times out,
|
||||
# so they don't get unregistered. i mean there is no function that
|
||||
# is called when a client times out.
|
||||
def handleClose(self):
|
||||
if self.client_type is CLIENT_TYPE_CONTROLLER:
|
||||
self.effectController.addOnControllerChangeHandler(self.onChange)
|
||||
elif self.client_type is CLIENT_TYPE_STRIPE:
|
||||
self.rgbStripController.unregisterRGBStrip(self.rgbStrip)
|
||||
elif self.client_type is CLIENT_TYPE_RECORDER:
|
||||
pass
|
||||
print(self.address, 'closed')
|
||||
|
||||
# called when there are changes that should be pushed to the client.
|
||||
# - the effectController: start / stop effects, move strip to effect, changing effect params
|
||||
# - the rgbStripController: add/removing strips
|
||||
# -> CLIENT_TYPE_CONTROLLER
|
||||
def onChange(self):
|
||||
if self.client_type is CLIENT_TYPE_CONTROLLER:
|
||||
self.sendMessage(
|
||||
json.dumps({
|
||||
'effects': effectControllerJsonHandler.getEffects(self.effectController),
|
||||
'rgbStrips': rgbStripControllerJsonHandler.getRGBStrips(self.rgbStripController),
|
||||
'effectThreads': effectControllerJsonHandler.getEffectThreads(self.effectController)
|
||||
})
|
||||
)
|
||||
return
|
||||
elif self.client_type is CLIENT_TYPE_STRIPE:
|
||||
return
|
||||
elif self.client_type is CLIENT_TYPE_RECORDER:
|
||||
return
|
||||
|
||||
# when a rgbStrip value is changed, send json data to client
|
||||
def onRGBStripValueUpdate(self,rgbStrip):
|
||||
self.sendMessage(
|
||||
json.dumps({
|
||||
'data': rgbStripControllerJsonHandler.getRGBData(rgbStrip)
|
||||
})
|
||||
)
|
@ -1,732 +0,0 @@
|
||||
'''
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013 Dave P.
|
||||
https://github.com/dpallot/simple-websocket-server
|
||||
'''
|
||||
import sys
|
||||
VER = sys.version_info[0]
|
||||
import socketserver
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from io import StringIO, BytesIO
|
||||
|
||||
import hashlib
|
||||
import base64
|
||||
import socket
|
||||
import struct
|
||||
import ssl
|
||||
import errno
|
||||
import codecs
|
||||
from collections import deque
|
||||
from select import select
|
||||
|
||||
import traceback
|
||||
import time
|
||||
|
||||
__all__ = ['WebSocket',
|
||||
'SimpleWebSocketServer',
|
||||
'SimpleSSLWebSocketServer']
|
||||
|
||||
def _check_unicode(val):
|
||||
if VER >= 3:
|
||||
return isinstance(val, str)
|
||||
else:
|
||||
return isinstance(val, unicode)
|
||||
|
||||
class HTTPRequest(BaseHTTPRequestHandler):
|
||||
def __init__(self, request_text):
|
||||
if VER >= 3:
|
||||
self.rfile = BytesIO(request_text)
|
||||
else:
|
||||
self.rfile = StringIO(request_text)
|
||||
self.raw_requestline = self.rfile.readline()
|
||||
self.error_code = self.error_message = None
|
||||
self.parse_request()
|
||||
|
||||
_VALID_STATUS_CODES = [1000, 1001, 1002, 1003, 1007, 1008,
|
||||
1009, 1010, 1011, 3000, 3999, 4000, 4999]
|
||||
|
||||
HANDSHAKE_STR = (
|
||||
"HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Upgrade: WebSocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n"
|
||||
)
|
||||
|
||||
GUID_STR = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
||||
|
||||
STREAM = 0x0
|
||||
TEXT = 0x1
|
||||
BINARY = 0x2
|
||||
CLOSE = 0x8
|
||||
PING = 0x9
|
||||
PONG = 0xA
|
||||
|
||||
HEADERB1 = 1
|
||||
HEADERB2 = 3
|
||||
LENGTHSHORT = 4
|
||||
LENGTHLONG = 5
|
||||
MASK = 6
|
||||
PAYLOAD = 7
|
||||
|
||||
MAXHEADER = 65536
|
||||
MAXPAYLOAD = 33554432
|
||||
|
||||
class WebSocket(object):
|
||||
|
||||
def __init__(self, server, sock, address):
|
||||
self.server = server
|
||||
self.client = sock
|
||||
self.address = address
|
||||
|
||||
self.handshaked = False
|
||||
self.headerbuffer = bytearray()
|
||||
self.headertoread = 2048
|
||||
|
||||
self.fin = 0
|
||||
self.data = bytearray()
|
||||
self.opcode = 0
|
||||
self.hasmask = 0
|
||||
self.maskarray = None
|
||||
self.length = 0
|
||||
self.lengtharray = None
|
||||
self.index = 0
|
||||
self.request = None
|
||||
self.usingssl = False
|
||||
self.lastping = 0
|
||||
|
||||
self.frag_start = False
|
||||
self.frag_type = BINARY
|
||||
self.frag_buffer = None
|
||||
self.frag_decoder = codecs.getincrementaldecoder('utf-8')(errors='strict')
|
||||
self.closed = False
|
||||
self.sendq = deque()
|
||||
|
||||
self.state = HEADERB1
|
||||
|
||||
# restrict the size of header and payload for security reasons
|
||||
self.maxheader = MAXHEADER
|
||||
self.maxpayload = MAXPAYLOAD
|
||||
|
||||
def handleMessage(self):
|
||||
"""
|
||||
Called when websocket frame is received.
|
||||
To access the frame data call self.data.
|
||||
|
||||
If the frame is Text then self.data is a unicode object.
|
||||
If the frame is Binary then self.data is a bytearray object.
|
||||
"""
|
||||
pass
|
||||
|
||||
def handleConnected(self):
|
||||
"""
|
||||
Called when a websocket client connects to the server.
|
||||
"""
|
||||
pass
|
||||
|
||||
def handleClose(self):
|
||||
"""
|
||||
Called when a websocket server gets a Close frame from a client.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _handlePacket(self):
|
||||
if self.opcode == CLOSE:
|
||||
pass
|
||||
elif self.opcode == STREAM:
|
||||
pass
|
||||
elif self.opcode == TEXT:
|
||||
pass
|
||||
elif self.opcode == BINARY:
|
||||
pass
|
||||
elif self.opcode == PONG or self.opcode == PING:
|
||||
self.lastping = time.time()
|
||||
if len(self.data) > 125:
|
||||
print('control frame length can not be > 125')
|
||||
raise Exception('control frame length can not be > 125')
|
||||
else:
|
||||
# unknown or reserved opcode so just close
|
||||
print('unknown opcode')
|
||||
raise Exception('unknown opcode')
|
||||
|
||||
if self.opcode == CLOSE:
|
||||
status = 1000
|
||||
reason = u''
|
||||
length = len(self.data)
|
||||
|
||||
if length == 0:
|
||||
pass
|
||||
elif length >= 2:
|
||||
status = struct.unpack_from('!H', self.data[:2])[0]
|
||||
reason = self.data[2:]
|
||||
|
||||
if status not in _VALID_STATUS_CODES:
|
||||
status = 1002
|
||||
|
||||
if len(reason) > 0:
|
||||
try:
|
||||
reason = reason.decode('utf8', errors='strict')
|
||||
except:
|
||||
status = 1002
|
||||
else:
|
||||
status = 1002
|
||||
|
||||
self.close(status, reason)
|
||||
return
|
||||
|
||||
elif self.fin == 0:
|
||||
if self.opcode != STREAM:
|
||||
if self.opcode == PING or self.opcode == PONG:
|
||||
print('control messages can not be fragmented')
|
||||
raise Exception('control messages can not be fragmented')
|
||||
|
||||
self.frag_type = self.opcode
|
||||
self.frag_start = True
|
||||
self.frag_decoder.reset()
|
||||
|
||||
if self.frag_type == TEXT:
|
||||
self.frag_buffer = []
|
||||
utf_str = self.frag_decoder.decode(self.data, final = False)
|
||||
if utf_str:
|
||||
self.frag_buffer.append(utf_str)
|
||||
else:
|
||||
self.frag_buffer = bytearray()
|
||||
self.frag_buffer.extend(self.data)
|
||||
|
||||
else:
|
||||
if self.frag_start is False:
|
||||
print('fragmentation protocol error')
|
||||
raise Exception('fragmentation protocol error')
|
||||
|
||||
if self.frag_type == TEXT:
|
||||
utf_str = self.frag_decoder.decode(self.data, final = False)
|
||||
if utf_str:
|
||||
self.frag_buffer.append(utf_str)
|
||||
else:
|
||||
self.frag_buffer.extend(self.data)
|
||||
|
||||
else:
|
||||
if self.opcode == STREAM:
|
||||
if self.frag_start is False:
|
||||
print('fragmentation protocol error')
|
||||
raise Exception('fragmentation protocol error')
|
||||
|
||||
if self.frag_type == TEXT:
|
||||
utf_str = self.frag_decoder.decode(self.data, final = True)
|
||||
self.frag_buffer.append(utf_str)
|
||||
self.data = u''.join(self.frag_buffer)
|
||||
else:
|
||||
self.frag_buffer.extend(self.data)
|
||||
self.data = self.frag_buffer
|
||||
|
||||
self.handleMessage()
|
||||
|
||||
self.frag_decoder.reset()
|
||||
self.frag_type = BINARY
|
||||
self.frag_start = False
|
||||
self.frag_buffer = None
|
||||
|
||||
elif self.opcode == PING:
|
||||
self._sendMessage(False, PONG, self.data)
|
||||
|
||||
elif self.opcode == PONG:
|
||||
pass
|
||||
|
||||
else:
|
||||
if self.frag_start is True:
|
||||
print('fragmentation protocol error')
|
||||
raise Exception('fragmentation protocol error')
|
||||
|
||||
if self.opcode == TEXT:
|
||||
try:
|
||||
self.data = self.data.decode('utf8', errors='strict')
|
||||
except Exception as exp:
|
||||
print('invalid utf-8 payload')
|
||||
raise Exception('invalid utf-8 payload')
|
||||
|
||||
self.handleMessage()
|
||||
|
||||
|
||||
def _handleData(self):
|
||||
# do the HTTP header and handshake
|
||||
if self.handshaked is False:
|
||||
|
||||
data = self.client.recv(self.headertoread)
|
||||
if not data:
|
||||
print('remote socket closed')
|
||||
raise Exception('remote socket closed')
|
||||
|
||||
else:
|
||||
# accumulate
|
||||
self.headerbuffer.extend(data)
|
||||
|
||||
if len(self.headerbuffer) >= self.maxheader:
|
||||
print('header exceeded allowable size')
|
||||
raise Exception('header exceeded allowable size')
|
||||
|
||||
# indicates end of HTTP header
|
||||
if b'\r\n\r\n' in self.headerbuffer:
|
||||
self.request = HTTPRequest(self.headerbuffer)
|
||||
|
||||
# handshake rfc 6455
|
||||
try:
|
||||
key = self.request.headers['Sec-WebSocket-Key']
|
||||
k = key.encode('ascii') + GUID_STR.encode('ascii')
|
||||
k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii')
|
||||
hStr = HANDSHAKE_STR % {'acceptstr': k_s}
|
||||
self.sendq.append((BINARY, hStr.encode('ascii')))
|
||||
self.handshaked = True
|
||||
self.handleConnected()
|
||||
except Exception as e:
|
||||
print(e,traceback.format_exc())
|
||||
print('handshake failed: %s', str(e))
|
||||
raise Exception('handshake failed: %s', str(e))
|
||||
|
||||
# else do normal data
|
||||
else:
|
||||
data = self.client.recv(16384)
|
||||
if not data:
|
||||
print("remote socket closed")
|
||||
raise Exception("remote socket closed")
|
||||
|
||||
if VER >= 3:
|
||||
for d in data:
|
||||
self._parseMessage(d)
|
||||
else:
|
||||
for d in data:
|
||||
self._parseMessage(ord(d))
|
||||
|
||||
def close(self, status = 1000, reason = u''):
|
||||
"""
|
||||
Send Close frame to the client. The underlying socket is only closed
|
||||
when the client acknowledges the Close frame.
|
||||
|
||||
status is the closing identifier.
|
||||
reason is the reason for the close.
|
||||
"""
|
||||
try:
|
||||
if self.closed is False:
|
||||
close_msg = bytearray()
|
||||
close_msg.extend(struct.pack("!H", status))
|
||||
if _check_unicode(reason):
|
||||
close_msg.extend(reason.encode('utf-8'))
|
||||
else:
|
||||
close_msg.extend(reason)
|
||||
|
||||
self._sendMessage(False, CLOSE, close_msg)
|
||||
|
||||
finally:
|
||||
self.closed = True
|
||||
|
||||
|
||||
def _sendBuffer(self, buff, send_all = False):
|
||||
size = len(buff)
|
||||
tosend = size
|
||||
already_sent = 0
|
||||
|
||||
while tosend > 0:
|
||||
try:
|
||||
# i should be able to send a bytearray
|
||||
sent = self.client.send(buff[already_sent:])
|
||||
if sent == 0:
|
||||
raise RuntimeError('socket connection broken')
|
||||
|
||||
already_sent += sent
|
||||
tosend -= sent
|
||||
|
||||
except socket.error as e:
|
||||
print(e,traceback.format_exc())
|
||||
# if we have full buffers then wait for them to drain and try again
|
||||
if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]:
|
||||
if send_all:
|
||||
continue
|
||||
return buff[already_sent:]
|
||||
else:
|
||||
print(e,traceback.format_exc())
|
||||
raise e
|
||||
|
||||
return None
|
||||
|
||||
def sendFragmentStart(self, data):
|
||||
"""
|
||||
Send the start of a data fragment stream to a websocket client.
|
||||
Subsequent data should be sent using sendFragment().
|
||||
A fragment stream is completed when sendFragmentEnd() is called.
|
||||
|
||||
If data is a unicode object then the frame is sent as Text.
|
||||
If the data is a bytearray object then the frame is sent as Binary.
|
||||
"""
|
||||
opcode = BINARY
|
||||
if _check_unicode(data):
|
||||
opcode = TEXT
|
||||
self._sendMessage(True, opcode, data)
|
||||
|
||||
def sendFragment(self, data):
|
||||
"""
|
||||
see sendFragmentStart()
|
||||
|
||||
If data is a unicode object then the frame is sent as Text.
|
||||
If the data is a bytearray object then the frame is sent as Binary.
|
||||
"""
|
||||
self._sendMessage(True, STREAM, data)
|
||||
|
||||
def sendFragmentEnd(self, data):
|
||||
"""
|
||||
see sendFragmentEnd()
|
||||
|
||||
If data is a unicode object then the frame is sent as Text.
|
||||
If the data is a bytearray object then the frame is sent as Binary.
|
||||
"""
|
||||
self._sendMessage(False, STREAM, data)
|
||||
|
||||
def sendMessage(self, data):
|
||||
"""
|
||||
Send websocket data frame to the client.
|
||||
|
||||
If data is a unicode object then the frame is sent as Text.
|
||||
If the data is a bytearray object then the frame is sent as Binary.
|
||||
"""
|
||||
opcode = BINARY
|
||||
if _check_unicode(data):
|
||||
opcode = TEXT
|
||||
self._sendMessage(False, opcode, data)
|
||||
|
||||
|
||||
def _sendMessage(self, fin, opcode, data):
|
||||
|
||||
payload = bytearray()
|
||||
|
||||
b1 = 0
|
||||
b2 = 0
|
||||
if fin is False:
|
||||
b1 |= 0x80
|
||||
b1 |= opcode
|
||||
|
||||
if _check_unicode(data):
|
||||
data = data.encode('utf-8')
|
||||
|
||||
length = len(data)
|
||||
payload.append(b1)
|
||||
|
||||
if length <= 125:
|
||||
b2 |= length
|
||||
payload.append(b2)
|
||||
|
||||
elif length >= 126 and length <= 65535:
|
||||
b2 |= 126
|
||||
payload.append(b2)
|
||||
payload.extend(struct.pack("!H", length))
|
||||
|
||||
else:
|
||||
b2 |= 127
|
||||
payload.append(b2)
|
||||
payload.extend(struct.pack("!Q", length))
|
||||
|
||||
if length > 0:
|
||||
payload.extend(data)
|
||||
|
||||
self.sendq.append((opcode, payload))
|
||||
|
||||
|
||||
def _parseMessage(self, byte):
|
||||
# read in the header
|
||||
if self.state == HEADERB1:
|
||||
|
||||
self.fin = byte & 0x80
|
||||
self.opcode = byte & 0x0F
|
||||
self.state = HEADERB2
|
||||
|
||||
self.index = 0
|
||||
self.length = 0
|
||||
self.lengtharray = bytearray()
|
||||
self.data = bytearray()
|
||||
|
||||
rsv = byte & 0x70
|
||||
if rsv != 0:
|
||||
print('RSV bit must be 0')
|
||||
raise Exception('RSV bit must be 0')
|
||||
|
||||
elif self.state == HEADERB2:
|
||||
mask = byte & 0x80
|
||||
length = byte & 0x7F
|
||||
|
||||
if self.opcode == PING and length > 125:
|
||||
print('ping packet is too large')
|
||||
raise Exception('ping packet is too large')
|
||||
|
||||
if mask == 128:
|
||||
self.hasmask = True
|
||||
else:
|
||||
self.hasmask = False
|
||||
|
||||
if length <= 125:
|
||||
self.length = length
|
||||
|
||||
# if we have a mask we must read it
|
||||
if self.hasmask is True:
|
||||
self.maskarray = bytearray()
|
||||
self.state = MASK
|
||||
else:
|
||||
# if there is no mask and no payload we are done
|
||||
if self.length <= 0:
|
||||
try:
|
||||
self._handlePacket()
|
||||
finally:
|
||||
self.state = HEADERB1
|
||||
self.data = bytearray()
|
||||
|
||||
# we have no mask and some payload
|
||||
else:
|
||||
#self.index = 0
|
||||
self.data = bytearray()
|
||||
self.state = PAYLOAD
|
||||
|
||||
elif length == 126:
|
||||
self.lengtharray = bytearray()
|
||||
self.state = LENGTHSHORT
|
||||
|
||||
elif length == 127:
|
||||
self.lengtharray = bytearray()
|
||||
self.state = LENGTHLONG
|
||||
|
||||
|
||||
elif self.state == LENGTHSHORT:
|
||||
self.lengtharray.append(byte)
|
||||
|
||||
if len(self.lengtharray) > 2:
|
||||
print('short length exceeded allowable size')
|
||||
raise Exception('short length exceeded allowable size')
|
||||
|
||||
if len(self.lengtharray) == 2:
|
||||
self.length = struct.unpack_from('!H', self.lengtharray)[0]
|
||||
|
||||
if self.hasmask is True:
|
||||
self.maskarray = bytearray()
|
||||
self.state = MASK
|
||||
else:
|
||||
# if there is no mask and no payload we are done
|
||||
if self.length <= 0:
|
||||
try:
|
||||
self._handlePacket()
|
||||
finally:
|
||||
self.state = HEADERB1
|
||||
self.data = bytearray()
|
||||
|
||||
# we have no mask and some payload
|
||||
else:
|
||||
#self.index = 0
|
||||
self.data = bytearray()
|
||||
self.state = PAYLOAD
|
||||
|
||||
elif self.state == LENGTHLONG:
|
||||
|
||||
self.lengtharray.append(byte)
|
||||
|
||||
if len(self.lengtharray) > 8:
|
||||
print('long length exceeded allowable size')
|
||||
raise Exception('long length exceeded allowable size')
|
||||
|
||||
if len(self.lengtharray) == 8:
|
||||
self.length = struct.unpack_from('!Q', self.lengtharray)[0]
|
||||
|
||||
if self.hasmask is True:
|
||||
self.maskarray = bytearray()
|
||||
self.state = MASK
|
||||
else:
|
||||
# if there is no mask and no payload we are done
|
||||
if self.length <= 0:
|
||||
try:
|
||||
self._handlePacket()
|
||||
finally:
|
||||
self.state = HEADERB1
|
||||
self.data = bytearray()
|
||||
|
||||
# we have no mask and some payload
|
||||
else:
|
||||
#self.index = 0
|
||||
self.data = bytearray()
|
||||
self.state = PAYLOAD
|
||||
|
||||
# MASK STATE
|
||||
elif self.state == MASK:
|
||||
self.maskarray.append(byte)
|
||||
|
||||
if len(self.maskarray) > 4:
|
||||
print('mask exceeded allowable size')
|
||||
raise Exception('mask exceeded allowable size')
|
||||
|
||||
if len(self.maskarray) == 4:
|
||||
# if there is no mask and no payload we are done
|
||||
if self.length <= 0:
|
||||
try:
|
||||
self._handlePacket()
|
||||
finally:
|
||||
self.state = HEADERB1
|
||||
self.data = bytearray()
|
||||
|
||||
# we have no mask and some payload
|
||||
else:
|
||||
#self.index = 0
|
||||
self.data = bytearray()
|
||||
self.state = PAYLOAD
|
||||
|
||||
# PAYLOAD STATE
|
||||
elif self.state == PAYLOAD:
|
||||
if self.hasmask is True:
|
||||
self.data.append( byte ^ self.maskarray[self.index % 4] )
|
||||
else:
|
||||
self.data.append( byte )
|
||||
|
||||
# if length exceeds allowable size then we except and remove the connection
|
||||
if len(self.data) >= self.maxpayload:
|
||||
print('payload exceeded allowable size')
|
||||
raise Exception('payload exceeded allowable size')
|
||||
|
||||
# check if we have processed length bytes; if so we are done
|
||||
if (self.index+1) == self.length:
|
||||
try:
|
||||
self._handlePacket()
|
||||
finally:
|
||||
#self.index = 0
|
||||
self.state = HEADERB1
|
||||
self.data = bytearray()
|
||||
else:
|
||||
self.index += 1
|
||||
|
||||
|
||||
class SimpleWebSocketServer(object):
|
||||
def __init__(self, host, port, websocketclass, selectInterval = 0.1):
|
||||
self.websocketclass = websocketclass
|
||||
self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.serversocket.settimeout(5)
|
||||
self.serversocket.bind((host, port))
|
||||
self.serversocket.listen(5)
|
||||
self.selectInterval = selectInterval
|
||||
self.connections = {}
|
||||
self.listeners = [self.serversocket]
|
||||
|
||||
def _decorateSocket(self, sock):
|
||||
return sock
|
||||
|
||||
def _constructWebSocket(self, sock, address):
|
||||
return self.websocketclass(self, sock, address)
|
||||
|
||||
def close(self):
|
||||
self.serversocket.close()
|
||||
|
||||
for desc, conn in self.connections.items():
|
||||
conn.close()
|
||||
self._handleClose(conn)
|
||||
|
||||
def _handleClose(self, client):
|
||||
client.client.close()
|
||||
# only call handleClose when we have a successful websocket connection
|
||||
if client.handshaked:
|
||||
#try:
|
||||
client.handleClose()
|
||||
#except:
|
||||
# print("timeout?")
|
||||
# pass
|
||||
|
||||
def serveonce(self):
|
||||
writers = []
|
||||
for fileno in self.listeners:
|
||||
if fileno == self.serversocket:
|
||||
continue
|
||||
client = self.connections[fileno]
|
||||
if client.sendq:
|
||||
writers.append(fileno)
|
||||
|
||||
if self.selectInterval:
|
||||
rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval)
|
||||
else:
|
||||
rList, wList, xList = select(self.listeners, writers, self.listeners)
|
||||
|
||||
for ready in wList:
|
||||
client = self.connections[ready]
|
||||
try:
|
||||
while client.sendq:
|
||||
opcode, payload = client.sendq.popleft()
|
||||
remaining = client._sendBuffer(payload)
|
||||
if remaining is not None:
|
||||
client.sendq.appendleft((opcode, remaining))
|
||||
break
|
||||
else:
|
||||
if opcode == CLOSE:
|
||||
print('received client close')
|
||||
raise Exception('received client close')
|
||||
|
||||
except Exception as n:
|
||||
print(n,traceback.format_exc())
|
||||
self._handleClose(client)
|
||||
del self.connections[ready]
|
||||
self.listeners.remove(ready)
|
||||
|
||||
for ready in rList:
|
||||
if ready == self.serversocket:
|
||||
sock = None
|
||||
try:
|
||||
sock, address = self.serversocket.accept()
|
||||
newsock = self._decorateSocket(sock)
|
||||
newsock.setblocking(0)
|
||||
fileno = newsock.fileno()
|
||||
self.connections[fileno] = self._constructWebSocket(newsock, address)
|
||||
self.listeners.append(fileno)
|
||||
except Exception as n:
|
||||
print(n,traceback.format_exc())
|
||||
if sock is not None:
|
||||
sock.close()
|
||||
else:
|
||||
if ready not in self.connections:
|
||||
continue
|
||||
client = self.connections[ready]
|
||||
try:
|
||||
client._handleData()
|
||||
except Exception as n:
|
||||
print(n,traceback.format_exc())
|
||||
self._handleClose(client)
|
||||
del self.connections[ready]
|
||||
self.listeners.remove(ready)
|
||||
|
||||
for failed in xList:
|
||||
if failed == self.serversocket:
|
||||
self.close()
|
||||
print('server socket failed')
|
||||
raise Exception('server socket failed')
|
||||
else:
|
||||
if failed not in self.connections:
|
||||
continue
|
||||
client = self.connections[failed]
|
||||
self._handleClose(client)
|
||||
del self.connections[failed]
|
||||
self.listeners.remove(failed)
|
||||
|
||||
def serveforever(self):
|
||||
while True:
|
||||
self.serveonce()
|
||||
|
||||
class SimpleSSLWebSocketServer(SimpleWebSocketServer):
|
||||
|
||||
def __init__(self, host, port, websocketclass, certfile,
|
||||
keyfile, version = ssl.PROTOCOL_TLSv1, selectInterval = 0.1):
|
||||
|
||||
SimpleWebSocketServer.__init__(self, host, port,
|
||||
websocketclass, selectInterval)
|
||||
|
||||
self.context = ssl.SSLContext(version)
|
||||
self.context.load_cert_chain(certfile, keyfile)
|
||||
|
||||
def close(self):
|
||||
super(SimpleSSLWebSocketServer, self).close()
|
||||
|
||||
def _decorateSocket(self, sock):
|
||||
sslsock = self.context.wrap_socket(sock, server_side=True)
|
||||
return sslsock
|
||||
|
||||
def _constructWebSocket(self, sock, address):
|
||||
ws = self.websocketclass(self, sock, address)
|
||||
ws.usingssl = True
|
||||
return ws
|
||||
|
||||
def serveforever(self):
|
||||
super(SimpleSSLWebSocketServer, self).serveforever()
|
@ -1,22 +0,0 @@
|
||||
from webserver.SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
|
||||
from webserver.HTTPWebSocketsHandler import HTTPWebSocketsHandler
|
||||
from threading import Thread
|
||||
from functools import partial
|
||||
|
||||
class ThreadedWebSocketServer(Thread):
|
||||
def __init__(self,effectController,rgbStripController):
|
||||
Thread.__init__(self)
|
||||
self.effectController = effectController
|
||||
self.rgbStripController = rgbStripController
|
||||
self.daemon = True
|
||||
self.stopped = False
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
server = SimpleWebSocketServer('', 8001, partial(HTTPWebSocketsHandler,self.effectController, self.rgbStripController))
|
||||
while not self.stopped:
|
||||
server.serveonce()
|
||||
print("ThreadedWebSocketServer stopped")
|
||||
|
||||
def stop(self):
|
||||
self.stopped = True
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,147 +0,0 @@
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
#define PIN 5
|
||||
#define LED_COUNT 150
|
||||
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
/*
|
||||
\r Start of command
|
||||
\n End of command
|
||||
|
||||
s show
|
||||
c setPixelColor pixelH pixelL red green blue
|
||||
b setBrightness brightness
|
||||
g getPixelColor pixelH pixelL
|
||||
n numPixels
|
||||
*/
|
||||
|
||||
enum Commands {
|
||||
Show = 's',
|
||||
SetColor = 'c',
|
||||
SetColorRange = 'r',
|
||||
SetBrightness = 'b',
|
||||
GetColor = 'g',
|
||||
NumberPixels = 'n'
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
strip.begin();
|
||||
strip.show(); // Initialize all pixels to 'off'
|
||||
Serial.println("Ok");
|
||||
}
|
||||
|
||||
bool read(char &character, long timeout = 1000) {
|
||||
long start = millis();
|
||||
while (!Serial.available()) {
|
||||
if (millis() - start > timeout) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
character = Serial.read();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setColor() {
|
||||
char character;
|
||||
uint16_t pixel;
|
||||
uint8_t color[3];
|
||||
|
||||
if (!read(character)) { return false; }
|
||||
pixel = (uint16_t) character << 8;
|
||||
if (!read(character)) { return false; }
|
||||
pixel += (uint8_t)character;
|
||||
if (!read(character)) { return false; }
|
||||
color[0] = character;
|
||||
if (!read(character)) { return false; }
|
||||
color[1] = character;
|
||||
if (!read(character)) { return false; }
|
||||
color[2] = character;
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[0]);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[1]);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[2]);
|
||||
//Serial.print(" ");
|
||||
|
||||
strip.setPixelColor(pixel, color[0], color[1], color[2]);
|
||||
strip.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setColorRange() {
|
||||
char character;
|
||||
uint16_t pixelstart;
|
||||
uint16_t pixelstop;
|
||||
uint8_t color[3];
|
||||
|
||||
if (!read(character)) { return false; }
|
||||
pixelstart = (uint16_t) character << 8;
|
||||
if (!read(character)) { return false; }
|
||||
pixelstart += (uint8_t)character;
|
||||
if (!read(character)) { return false; }
|
||||
pixelstop = (uint16_t) character << 8;
|
||||
if (!read(character)) { return false; }
|
||||
pixelstop += (uint8_t)character;
|
||||
if (!read(character)) { return false; }
|
||||
color[0] = character;
|
||||
if (!read(character)) { return false; }
|
||||
color[1] = character;
|
||||
if (!read(character)) { return false; }
|
||||
color[2] = character;
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[0]);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[1]);
|
||||
//Serial.print(" ");
|
||||
//Serial.print(color[2]);
|
||||
//Serial.print(" ");
|
||||
|
||||
for (int i=pixelstart; i <= pixelstop; i++){
|
||||
strip.setPixelColor(i, color[0], color[1], color[2]);
|
||||
}
|
||||
strip.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
char character;
|
||||
if (!read(character) || character != ':') { return; }
|
||||
if (!read(character)) { return; }
|
||||
|
||||
uint8_t command_index = (uint8_t)character;
|
||||
Serial.print(command_index);
|
||||
|
||||
if (!read(character)) { return; }
|
||||
|
||||
switch(character) {
|
||||
case Show:
|
||||
strip.show();
|
||||
Serial.println("Ok");
|
||||
break;
|
||||
case SetColor:
|
||||
if (setColor()) {
|
||||
Serial.println("Ok");
|
||||
} else {
|
||||
Serial.println("Err");
|
||||
}
|
||||
break;
|
||||
case SetColorRange:
|
||||
if (setColorRange()) {
|
||||
Serial.println("Ok");
|
||||
} else {
|
||||
Serial.println("Err");
|
||||
}
|
||||
break;
|
||||
case SetBrightness:
|
||||
break;
|
||||
case GetColor:
|
||||
break;
|
||||
case NumberPixels:
|
||||
//Serial.println(strip.numPixels());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user