reorganize

This commit is contained in:
simon 2019-04-27 16:00:12 +02:00
parent 72482d0162
commit b8efa3badb
68 changed files with 0 additions and 4857 deletions

View File

@ -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

View File

@ -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>

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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>

View File

@ -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.

View File

View File

@ -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)
########## #####################################################################

View File

@ -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__))

View File

@ -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

View File

@ -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

View File

@ -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]\
)

View File

@ -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

View File

@ -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

View File

@ -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"])

Binary file not shown.

View File

@ -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()

View File

@ -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"

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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)

View File

@ -1,6 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def debug(string):
return
print(string)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 = []

View File

@ -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)

View File

@ -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

View File

View File

@ -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"

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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)
})
)

View File

@ -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()

View File

@ -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

View File

@ -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;
}
}
}