diff --git a/old/.directory b/old/.directory deleted file mode 100644 index 2f51748..0000000 --- a/old/.directory +++ /dev/null @@ -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 diff --git a/old/.idea/LED-Server.iml b/old/.idea/LED-Server.iml deleted file mode 100644 index b3dc937..0000000 --- a/old/.idea/LED-Server.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/old/.idea/deployment.xml b/old/.idea/deployment.xml deleted file mode 100644 index bb5a95e..0000000 --- a/old/.idea/deployment.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/old/.idea/misc.xml b/old/.idea/misc.xml deleted file mode 100644 index e5e1b0d..0000000 --- a/old/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/old/.idea/modules.xml b/old/.idea/modules.xml deleted file mode 100644 index 675fa8d..0000000 --- a/old/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/old/.idea/workspace.xml b/old/.idea/workspace.xml deleted file mode 100644 index 6e9ddac..0000000 --- a/old/.idea/workspace.xml +++ /dev/null @@ -1,685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1502053329033 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file://$PROJECT_DIR$/test.py - 1 - - - file://$PROJECT_DIR$/__main__.py - 31 - - - file://$PROJECT_DIR$/__main__.py - 27 - - - file://$PROJECT_DIR$/__main__.py - 24 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/old/LEDServer.py b/old/LEDServer.py deleted file mode 100644 index 4a3d2f5..0000000 --- a/old/LEDServer.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/old/LEDServer.pyc b/old/LEDServer.pyc deleted file mode 100644 index 13d6426..0000000 Binary files a/old/LEDServer.pyc and /dev/null differ diff --git a/old/__init__.py b/old/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/old/audiovis.py b/old/audiovis.py deleted file mode 100644 index ded04f9..0000000 --- a/old/audiovis.py +++ /dev/null @@ -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) - -########## ##################################################################### \ No newline at end of file diff --git a/old/config.py b/old/config.py deleted file mode 100644 index 4938113..0000000 --- a/old/config.py +++ /dev/null @@ -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__)) diff --git a/old/effects/__pycache__/musikEffect.cpython-36.pyc b/old/effects/__pycache__/musikEffect.cpython-36.pyc deleted file mode 100644 index f1ad2e5..0000000 Binary files a/old/effects/__pycache__/musikEffect.cpython-36.pyc and /dev/null differ diff --git a/old/effects/__pycache__/musikEffect.cpython-37.pyc b/old/effects/__pycache__/musikEffect.cpython-37.pyc deleted file mode 100644 index 60c3ce4..0000000 Binary files a/old/effects/__pycache__/musikEffect.cpython-37.pyc and /dev/null differ diff --git a/old/effects/__pycache__/offEffect.cpython-36.pyc b/old/effects/__pycache__/offEffect.cpython-36.pyc deleted file mode 100644 index b507827..0000000 Binary files a/old/effects/__pycache__/offEffect.cpython-36.pyc and /dev/null differ diff --git a/old/effects/__pycache__/offEffect.cpython-37.pyc b/old/effects/__pycache__/offEffect.cpython-37.pyc deleted file mode 100644 index 504f67a..0000000 Binary files a/old/effects/__pycache__/offEffect.cpython-37.pyc and /dev/null differ diff --git a/old/effects/__pycache__/onEffect.cpython-36.pyc b/old/effects/__pycache__/onEffect.cpython-36.pyc deleted file mode 100644 index 897f51c..0000000 Binary files a/old/effects/__pycache__/onEffect.cpython-36.pyc and /dev/null differ diff --git a/old/effects/__pycache__/rainbowEffect.cpython-36.pyc b/old/effects/__pycache__/rainbowEffect.cpython-36.pyc deleted file mode 100644 index acf373d..0000000 Binary files a/old/effects/__pycache__/rainbowEffect.cpython-36.pyc and /dev/null differ diff --git a/old/effects/__pycache__/rainbowEffect.cpython-37.pyc b/old/effects/__pycache__/rainbowEffect.cpython-37.pyc deleted file mode 100644 index 548e971..0000000 Binary files a/old/effects/__pycache__/rainbowEffect.cpython-37.pyc and /dev/null differ diff --git a/old/effects/__pycache__/strobeEffect.cpython-36.pyc b/old/effects/__pycache__/strobeEffect.cpython-36.pyc deleted file mode 100644 index d7f398f..0000000 Binary files a/old/effects/__pycache__/strobeEffect.cpython-36.pyc and /dev/null differ diff --git a/old/effects/musikEffect.py b/old/effects/musikEffect.py deleted file mode 100644 index ef3f515..0000000 --- a/old/effects/musikEffect.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/effects/offEffect.py b/old/effects/offEffect.py deleted file mode 100644 index 9ea5234..0000000 --- a/old/effects/offEffect.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/effects/onEffect.py b/old/effects/onEffect.py deleted file mode 100644 index a2b776f..0000000 --- a/old/effects/onEffect.py +++ /dev/null @@ -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]\ - ) \ No newline at end of file diff --git a/old/effects/rainbowEffect.py b/old/effects/rainbowEffect.py deleted file mode 100644 index ec9b2e8..0000000 --- a/old/effects/rainbowEffect.py +++ /dev/null @@ -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 - \ No newline at end of file diff --git a/old/effects/strobeEffect.py b/old/effects/strobeEffect.py deleted file mode 100644 index c2c0b51..0000000 --- a/old/effects/strobeEffect.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/listSoundCards.py b/old/listSoundCards.py deleted file mode 100644 index ee26909..0000000 --- a/old/listSoundCards.py +++ /dev/null @@ -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"]) \ No newline at end of file diff --git a/old/loader.pyc b/old/loader.pyc deleted file mode 100644 index dfd6979..0000000 Binary files a/old/loader.pyc and /dev/null differ diff --git a/old/rgbUtils/BaseEffect.py b/old/rgbUtils/BaseEffect.py deleted file mode 100644 index 9a3d33a..0000000 --- a/old/rgbUtils/BaseEffect.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/old/rgbUtils/EffectParameter.py b/old/rgbUtils/EffectParameter.py deleted file mode 100644 index 45b117b..0000000 --- a/old/rgbUtils/EffectParameter.py +++ /dev/null @@ -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" \ No newline at end of file diff --git a/old/rgbUtils/RGBStrip.1.py b/old/rgbUtils/RGBStrip.1.py deleted file mode 100644 index 7c3c241..0000000 --- a/old/rgbUtils/RGBStrip.1.py +++ /dev/null @@ -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 - - - diff --git a/old/rgbUtils/RGBStrip.py b/old/rgbUtils/RGBStrip.py deleted file mode 100644 index fa99ace..0000000 --- a/old/rgbUtils/RGBStrip.py +++ /dev/null @@ -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] - - - diff --git a/old/rgbUtils/WS2812MasterStrip.py b/old/rgbUtils/WS2812MasterStrip.py deleted file mode 100644 index 17a0e49..0000000 --- a/old/rgbUtils/WS2812MasterStrip.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/old/rgbUtils/WS2812Strip.py b/old/rgbUtils/WS2812Strip.py deleted file mode 100644 index 2d97332..0000000 --- a/old/rgbUtils/WS2812Strip.py +++ /dev/null @@ -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) - - - diff --git a/old/rgbUtils/__pycache__/BaseEffect.cpython-36.pyc b/old/rgbUtils/__pycache__/BaseEffect.cpython-36.pyc deleted file mode 100644 index 500c642..0000000 Binary files a/old/rgbUtils/__pycache__/BaseEffect.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/BaseEffect.cpython-37.pyc b/old/rgbUtils/__pycache__/BaseEffect.cpython-37.pyc deleted file mode 100644 index 38a6133..0000000 Binary files a/old/rgbUtils/__pycache__/BaseEffect.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/EffectParameter.cpython-36.pyc b/old/rgbUtils/__pycache__/EffectParameter.cpython-36.pyc deleted file mode 100644 index 8529055..0000000 Binary files a/old/rgbUtils/__pycache__/EffectParameter.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/EffectParameter.cpython-37.pyc b/old/rgbUtils/__pycache__/EffectParameter.cpython-37.pyc deleted file mode 100644 index 2882949..0000000 Binary files a/old/rgbUtils/__pycache__/EffectParameter.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/RGBStrip.cpython-36.pyc b/old/rgbUtils/__pycache__/RGBStrip.cpython-36.pyc deleted file mode 100644 index a37ead6..0000000 Binary files a/old/rgbUtils/__pycache__/RGBStrip.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/RGBStrip.cpython-37.pyc b/old/rgbUtils/__pycache__/RGBStrip.cpython-37.pyc deleted file mode 100644 index f62cecc..0000000 Binary files a/old/rgbUtils/__pycache__/RGBStrip.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/debug.cpython-36.pyc b/old/rgbUtils/__pycache__/debug.cpython-36.pyc deleted file mode 100644 index cc2d919..0000000 Binary files a/old/rgbUtils/__pycache__/debug.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/debug.cpython-37.pyc b/old/rgbUtils/__pycache__/debug.cpython-37.pyc deleted file mode 100644 index 2d97256..0000000 Binary files a/old/rgbUtils/__pycache__/debug.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/effectController.cpython-36.pyc b/old/rgbUtils/__pycache__/effectController.cpython-36.pyc deleted file mode 100644 index 97638d5..0000000 Binary files a/old/rgbUtils/__pycache__/effectController.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/effectController.cpython-37.pyc b/old/rgbUtils/__pycache__/effectController.cpython-37.pyc deleted file mode 100644 index 10359fd..0000000 Binary files a/old/rgbUtils/__pycache__/effectController.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/effectControllerJsonHandler.cpython-36.pyc b/old/rgbUtils/__pycache__/effectControllerJsonHandler.cpython-36.pyc deleted file mode 100644 index b010392..0000000 Binary files a/old/rgbUtils/__pycache__/effectControllerJsonHandler.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-36.pyc b/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-36.pyc deleted file mode 100644 index cdab29a..0000000 Binary files a/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-37.pyc b/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-37.pyc deleted file mode 100644 index 11a3629..0000000 Binary files a/old/rgbUtils/__pycache__/pyAudioRecorder.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/rgbStripController.cpython-36.pyc b/old/rgbUtils/__pycache__/rgbStripController.cpython-36.pyc deleted file mode 100644 index 2cf2900..0000000 Binary files a/old/rgbUtils/__pycache__/rgbStripController.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/rgbStripController.cpython-37.pyc b/old/rgbUtils/__pycache__/rgbStripController.cpython-37.pyc deleted file mode 100644 index 0e48fd5..0000000 Binary files a/old/rgbUtils/__pycache__/rgbStripController.cpython-37.pyc and /dev/null differ diff --git a/old/rgbUtils/__pycache__/rgbStripControllerJsonHandler.cpython-36.pyc b/old/rgbUtils/__pycache__/rgbStripControllerJsonHandler.cpython-36.pyc deleted file mode 100644 index 8469d41..0000000 Binary files a/old/rgbUtils/__pycache__/rgbStripControllerJsonHandler.cpython-36.pyc and /dev/null differ diff --git a/old/rgbUtils/debug.py b/old/rgbUtils/debug.py deleted file mode 100644 index 534eecb..0000000 --- a/old/rgbUtils/debug.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -def debug(string): - return - print(string) \ No newline at end of file diff --git a/old/rgbUtils/effectController.py b/old/rgbUtils/effectController.py deleted file mode 100644 index d0ae8b1..0000000 --- a/old/rgbUtils/effectController.py +++ /dev/null @@ -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 diff --git a/old/rgbUtils/effectControllerJsonHandler.py b/old/rgbUtils/effectControllerJsonHandler.py deleted file mode 100644 index d44326b..0000000 --- a/old/rgbUtils/effectControllerJsonHandler.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/rgbUtils/fakeGPIO.py b/old/rgbUtils/fakeGPIO.py deleted file mode 100644 index a1e4b76..0000000 --- a/old/rgbUtils/fakeGPIO.py +++ /dev/null @@ -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 diff --git a/old/rgbUtils/pyAudioRecorder.py b/old/rgbUtils/pyAudioRecorder.py deleted file mode 100644 index dfe7e43..0000000 --- a/old/rgbUtils/pyAudioRecorder.py +++ /dev/null @@ -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 = [] diff --git a/old/rgbUtils/rgbStripController.py b/old/rgbUtils/rgbStripController.py deleted file mode 100644 index 4c1b7be..0000000 --- a/old/rgbUtils/rgbStripController.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/old/rgbUtils/rgbStripControllerJsonHandler.py b/old/rgbUtils/rgbStripControllerJsonHandler.py deleted file mode 100644 index 26b3918..0000000 --- a/old/rgbUtils/rgbStripControllerJsonHandler.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/rgbUtils/virtGPIO.py b/old/rgbUtils/virtGPIO.py deleted file mode 100644 index 4bc42ac..0000000 --- a/old/rgbUtils/virtGPIO.py +++ /dev/null @@ -1,1057 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# virtGPIO.py V0.9.7 - -""" -"Virtual GPIO" uses an arduino as a GPIO device to a Raspberry Pi or PC. -This system uses USB serial (or rPi's UART) to control (and power??) the arduino. -This file is the PC end of "virtual-gpio", ie the python library module that your own python code imports. -This code is compatible with python 2.7 and python 3.3. -Includes functionality of "import RPi.GPIO" and "import smbus" and "import spidev" - -""" - -# PC instructions (Linux or Windows or Mac): -# You require python 2.7 or 3.3 installed, and "pyserial". -# The arduino simply stays connected to PC by USB cable. -# On Windows, you may need to experiment with COM port numbers assigned to Arduino. - -# Raspberry Pi instructions: -# You require "pyserial" installed on the rPi. -# You may choose: (1) USB cable between, or (2) TTL wires from rPi uart pins to arduino uart pins. -# Here is how to configure for using the rPi's inbuilt uart: -# (sudo) edit /boot/cmdline.txt to remove the two phrases "console=ttyAMA0,115200 kgdboc=ttyAMA0,115200" -# (sudo) edit /etc/inittab to comment out the line containing "/dev/ttyAMA0" (the last line?) -# (sudo) edit /boot/config.txt by adding a new line "init_uart_clock=16000000" -# Reboot the rPi. -# Now, (1) uart is free and available for virtGPIO (rx -> tx and tx -> rx), -# (2) and it can go at baudrate speeds way over the usual 115200, -# Configured as above, the rPi's own GPIO-uart works quite well with virtGPIO arduino at 500000 baud. -# But see WARNING below on interfacing tx and rx wires. - -# Probably you can power the arduino from rPi's 5V supply, even using UART connection. -# But any substantial current requirement (eg servos beyond one small test one) needs provision of proper supply. - -# WARNING: rPI UART 3.3V TX and RX LINES MUST NOT CONNECT DIRECTLY TO 5V RX and TX OF ARDUINO ... -# ... You must use some form of voltage level shifting to 5V arduino, or use a 3.3V version arduino. - -# ADDITIONALLY ... -# Want to load the arduino sketch via this same rPi uart line? Refer to notes at top of "VirtGPIO.ino" - - - -if __name__ == '__main__': - print ("virtGPIO.py is an importable module for PC or Raspberry Pi:") - print ("... import virtGPIO as GPIO") - print ("virtGPIO.py talks by USB-serial with ARDUINO-ftdi loaded with VirtGPIO.ino") - print ("") - exit() - - -import time -try: - import serial -except: - print("Virtual-GPIO ERROR: pyserial seems not installed on your python?") - exit() -import sys -import glob -import os - - -def hardResetARD(): - Serial.setDTR(False) - time.sleep(0.3) - Serial.setDTR(True) - time.sleep(3) # and wait for it - -def softResetARD(): - # reset Arduino in software. (AVR registers may not be initialised to full reset) - _SerialWrite("0-"); - time.sleep(2.1) - - -def _i8(x): - # x is either an int8 or a single character string - # Used for processing _SerialRead characters from either str (python2) or bytes (python3) - # return is always int8 - if type(x) == type(""): - return ord(x) - return x - -def _SerialWrite(s): - # accepts List (of int8), or string (to int7), free choice, or mixed. Avoid strings with chrs over 0x7f - if type(s) == type(""): # type str - if sys.version_info.major == 2: # python2 - Serial.write(s) # py2 accepts strings (with int8) directly - else: # python3 - Serial.write(s.encode('UTF-8')) # -> bytes. But only to 7-bit int - else: # type list - if sys.version_info.major == 2: - Serial.write(''.join(chr(e) for e in s)) # -> str incl int8 - else: - Serial.write(bytes(s)) # -> bytes with int8 - - -def _SerialRead(count=1): - r = Serial.read(count) - # python2 returns type str of int8 strr[x] -> "?" - # python3 returns type bytes of int8 bb[x] -> int8 - # receiving routines to handle the difference! [_i8() function useful] - return r - - -def _serial_ports(): - # - if sys.platform.startswith('win'): - ports = ['COM' + str(i + 1) for i in range(256)] - elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): - # this is to exclude your current terminal "/dev/tty" - ports = glob.glob('/dev/tty[A-Za-z]*') - elif sys.platform.startswith('darwin'): - ports = glob.glob('/dev/tty.*') - else: - raise EnvironmentError('Unsupported platform') - result = [] - for port in ports: - try: - s = serial.Serial(port) - s.close() - result.append(port) - except (OSError, serial.SerialException): - pass - return result - -def set_baudrate(self, baud): - try: - self.setBaudrate(baud) - except AttributeError: - self.baudrate = baud - -Serial = None -verboseSetup = False -STDTIMEOUT = 0.8 - -# Following are DEFAULT portnames and baudrates that are attempted for virtGPIO. -# Optional file serialConfig.py can override these defaults. -baudlist = [500000, 115200, 250000] -portlist = ['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2', '/dev/ttyACM0', 'COM1', "COM3", "COM8", "COM9"] -# (these lists may be edited. 500000 baud recommended, list it first.) -# (I'm not a Mac person. So of course, I haven't tested a Mac. -# Try "ls /dev/tty.*" in terminal to help find your Mac serial port name.) -# Alternatively (BETTER!), use optional file "serialConfig.py" to override the baud and port settings above. - -try: - from serialConfig import * -except: - pass - -if portlist == "SMART": - portlist = _serial_ports() - if verboseSetup: - print ("SMART Serial Port Seek:"), - print (portlist) -elif verboseSetup: - print ("Ports to test:") - print (portlist) - - -for k in range(len(portlist)): - try: - Serial = serial.Serial(portlist[k], 9600, timeout=STDTIMEOUT, dsrdtr=False) - break; - except: - pass - -if type(Serial) == type(None): - print ("Failed to initialise Serial Port.") - print ("Tried %s." % portlist) - print ("Check your port name??") - exit() - - -if verboseSetup: - print ("Device found at %s " % Serial.port) - - -if not Serial.port == "/dev/ttyAMA0": - # NOT for Raspberry Pi UART port: it has no DTR line - if verboseSetup: - print ("Attempting hard reset of arduino ...") - hardResetARD() - -# Now, we know that the serial port exists. It COULD be another device, not our arduino ! -# Try certain baudrates to talk with arduino ... -if verboseSetup: - print ("Baudrates to test:") - print (baudlist) - -for k in range(len(baudlist)): - try: - if verboseSetup: - print ("Trying baudrate"), - print (baudlist[k]) - set_baudrate(Serial,baudlist[k]) # Try each baudrate in turn from our list - except: - print ("Device at %s can not operate at baudrate %d" % (Serial.port,baudlist[k])) - print ("Change options in 'serialConfig.py'") - exit() - time.sleep(0.1) - if verboseSetup: - print ("Try Ping @"), - print (Serial.baudrate) - _SerialWrite("=") # The sync() call used as a "ping" - ping = _SerialRead() # Fetch one reply character - if len(ping)>0: - if _i8(ping[0]) == ord("="): # Does this look like correct response? - break; - if k==(len(baudlist)-1): # tried & failed on all options - print ("Arduino not in contact. Tried baudrates"), - print (baudlist) - exit() -if verboseSetup: - print ("Found Arduino @ baudrate %d " % Serial.baudrate) - -if Serial.port == "/dev/ttyAMA0": # Raspberry Pi GPIO uart? - # on rPi UART mode we needed to establish serial contact before reset: this reset is a software command. - if verboseSetup: - print ("Soft reset of arduino ...") - softResetARD() - -if verboseSetup: - print ("Successful Setup") - print ("") - -# END OF SETUP - - - -# All below is API for user functions - - - - - - - - - - - - - - - -###################################################################### - - -HIGH = 1 -LOW = 0 - -A0 = 14 # the analog pins -A1 = 15 -A2 = 16 -A3 = 17 -A4 = 18 -A5 = 19 -A6 = 20 -A7 = 21 - -OUT = 1 -IN = 0 - - -# RPI.GPIO constants for compatibility: -PUD_UP = 22 -PUD_DOWN = 21 -PUD_OFF = 20 -BCM = 11 -BOARD = 10 -VERSION = "0.9.7" -RPI_REVISION = 0 - -def setmode(mode): - # Compatibility for rpi code GPIO.setmode(GPIO.BOARD/BCM) - pass - -def cleanup(): - GPIO.softReset() - -def setwarnings(mode): - # Not used. Compatibility for rpi code GPIO.setwarnings(false) - pass - - -def setup(dpin, mode, pull_up_down=0): - # Cast it into arduino numbers - INPUT_PULLUP = 2 - if pull_up_down == PUD_UP: - mode = INPUT_PULLUP - if pull_up_down == PUD_DOWN: - print ("Virtual-GPIO (arduino) has no pulldown. Continuing ...") - _SerialWrite("s" + chr(dpin) + chr(mode)); -def pinMode(dpin, mode): # arduino style - setup(dpin, mode) - -def output(dpin, hilo): - _SerialWrite("w" + chr(dpin) + chr(hilo)) - _SerialRead() # sync only -def digitalWrite(dpin, hilo): # arduino style - output(dpin, hilo) - -def input(dpin): - _SerialWrite("r" + chr(dpin)) - return _serialread1int8(0xff) -def digitalRead(dpin): # arduino style - input(dpin) - -def digitalPreciseRead(pin): - # Uses analog comparator on to compare the pin's ANALOG volts against 1.1V chip reference. - # ONLY for pins d7 and A0-A7 - AVR.bitClear(AVR.ADCSRA, 7) # disable ADC - AVR.write8(AVR.ACSR, 0x40); # set internal ref 1.1 for comparator - if pin == 7: - AVR.write8(AVR.ADCSRB, 0) # set d7 as input - elif (pin>= A0 and pin <= A7): - AVR.write8(AVR.ADCSRB, (pin-14) + 0x40) # set adc mux address 0-7 as input - else: - AVR.bitSet(AVR.ADCSRA, 7) # re-enable ADC - return 0xf4 # == f4 bad pin - r = ((~AVR.read8(AVR.ACSR)) >> 5) & 1 # comparator output bit - AVR.bitSet(AVR.ADCSRA, 7) # re-enable ADC - return r - - -def digitalReadAll(): - return (AVR.read8(AVR.PIND) & 0xf6) + ((AVR.read8(AVR.PINB)&0x3f)<<8) - # d2 to d7, and d8 to d13 - -def pwmWrite(dpin, dcycle): - _SerialWrite("p" + chr(dpin) + chr(dcycle)) # 8bit write - # p3 p11 Timer2, p9 p10 Timer1, p5 p6 Timer0 - # This is the regular analogWrite of the arduino - - -def analogRead(apin): # regular arduino style analog read - # HOWEVER, use the A0 A1 numbering (ie 14-21, not 0-7) - if apin<=7: - apin += 14 - _SerialWrite("a" + chr(apin)) - return _serialread2int16(0xfffa) - -def analogReadAll(): - _SerialWrite("A") - buf2 = _SerialRead(16) - # pyserial's serial.read() returns STRING or BYTES (of 16 CHARs) - # but we want LIST of 8 x 16-bit integers as our return format - L = len(buf2) - if L<16: # timeout? - buf3 = [0] * 8 # empty dummy of the correct length/format - else: - buf3 = [] - for k in range(8): - buf3.append(_i8(buf2[k*2]) + 256*_i8(buf2[1+k*2])) - return buf3 - -def pulseOut(dpin, mode, usec): # pulse to 255 uSec - _SerialWrite("U") - _SerialWrite([dpin, mode&1, usec]) - - -def pulseIn(pin, hilo, timeout1, timeout2): # pulsein - # int timeouts: To start 20 - 5000 usec, length 100uSec - 25000uSec 8 bit - _SerialWrite("I" + chr(pin) + chr(hilo)) - _SerialWrite([timeout1//20, timeout2//100]) - # 16-bit integer return in uSec - return _serialread2int16(0xfff2) - # Note return error codes could be FFE3 (pin conflict), FFFF (not idle), - # FFFE (not started on time), FFFA (fail to finish in time) - # These come from pulse_In function or case 'I' section in VirtGPIO.ino - - -def analogHiSpeed(): - # This moves ADC clock from divider 128 to divider 16 - # Not very useful for single analog reads, but some speedup for analogReadAll() - AVR.bitClear(AVR.ADCSRA, AVR.ADPS0); - AVR.bitClear(AVR.ADCSRA, AVR.ADPS1); - AVR.bitSet(AVR.ADCSRA, AVR.ADPS2); - -def setActivityLed(pin): - _SerialWrite ("_" + chr(pin)) - # The Activity Pin defaults as d13. It flashes ON while arduino is processing one incoming serial packet. - # Can be anytime reassigned to be a different pin, or to 0 which means disabled. - # Other need for pin13 needs ActivityPin to have been reassigned first. (Altho SPI will "kick" it off anyway) - - -############################################### - -class _AVR_: # class not intended to be instantiated by an outside script - ADCSRA = 0x7a - ADPS0 = 0 - ADPS1 = 1 - ADPS2 = 2 - TCNT1 = 0x84 # (0x84 lsB 0x85 msB) - TCCR1A = 0x80 - TCCR1B = 0x81 - CS10 = 1 - CS11 = 2 - CS12 = 4 - PINB = 0x23 # direct register addresses of digital inputs - PINC = 0x26 - PIND = 0x29 - PORTB = 0x25 - PORTC = 0x28 - PORTD = 0x2b - DDRB = 0x24 - DDRC = 0x27 - DDRD = 0x2a - ACSR = 0x50 - ADCSRA = 0x7a - ADCSRB = 0x7B - - # add to this list from 328 manual as needed - - def __init__(self): - pass - - - def read8(self, register): - _SerialWrite("#") - _SerialWrite([register]) - return _serialread1int8(0) - - def write8(self, register, data8): - _SerialWrite("*") - _SerialWrite([register, data8]) - - - def read16(self, register, errcode=0): - _SerialWrite("@") - _SerialWrite([register]) - return _serialread2int16(errcode) - - def write16(self, register, data16): - _SerialWrite("&") - _SerialWrite([register, data16&0xff, data16>>8]) - - - def bitSet(self, register, bit): - _SerialWrite("[") - _SerialWrite([register&0xff, bit]) - - def bitClear(self, register, bit): - _SerialWrite("]") - _SerialWrite([register&0xff, bit]); - -AVR = _AVR_() -# We pre-define the AVR object HERE. Outside script can now use this AVR object this way. - -############################################### - - - -class Servo: - # Using any servos disables PWM on pins 9-10 (uses Timer1) - - def __init__(self, pin): # pin 3 - 10 - setup(pin, OUT) # fix V0.9.7 - self.pin = pin - pass - - def write(self, value): - _SerialWrite("V" + chr(self.pin)) # 2-10 - _SerialWrite([value]) # 0-180 - - def stop(self): - _SerialWrite("v" + chr(self.pin)) - - -############################################### - - - -class SpiDev: - # minimal emulation of rPi-style spidev - # Note arduino pin 10 is conventionally used as the CSN/SS* output pin. It ought be preferred as first CE. - # This code supports any number of devices on SPI bus, - # Some of the comments below imply RF24L01 2.4GHz transceiver is attached to SPI ... - # ... however the SPI should be generic enough anyway. - - max_speed_hz = 0 # not currently implemented - - def __init__(self): - self.mode = 0 # default - return - - def mode(self, mode): - self.mode = mode&3 - - def max_speed_hz(self, speed): - pass - - def open(self, bus, device): - # bus is for RPI syntax compatibility only - # Also, where RPI uses 0 or 1 for device (CE0, CE1), virtGPIO uses actual chip enable pin - self.cePin = device - _SerialWrite("S" + chr(self.cePin)); # take SPI control of pins 11-13, plus CE-pin - - - # RPI compatible: - # import spidev spidev module. Contains SpiDev class. - # (On virtGPIO, (virt)GPIO module contains SpiDev class) - # mySPI = spidev.SpiDev() Create SpiDev object - # mySPI.open(bus, device) bus 0 (Model B) or bus 0 / 1 (Model B+) device = 0 or 1 (CE0 CE1) - # mySPI.mode = 2 SPI mode 0 to 3 - # mySPI.xfer2([listofTXint8]) Returns RX list of int8 - - - - def xfer2(self, buf): - # buf arrives as a list of 8-bit integers, - # max len 127, but this is unrealistic as the serial buffer is only 127. Suggest use <80 - # buf includes first byte = cmd byte, plus the payload - RF24 - # At the arduino, the CE* select is automatically asserted (low) around this block. - L = len(buf) - # set it as STRING of CHARS for serial.write: - #print "X" + chr(self.cePin) + chr(self.mode) + chr(L) + ''.join(chr(e) for e in buf) - _SerialWrite("X" + chr(self.cePin) + chr(self.mode) + chr(L)) - _SerialWrite(buf) - buf2 = _SerialRead(L) - # pyserial's serial.read() returns STRING or BYTES (of CHARs) - # but we want LIST of 8-bit integers as our return format - L2 = len(buf2) - if L2 60: - buf1 = buf[0:60] # save leading 60 - buf = buf[60:] # dump leading 60 - L -= 60 # and counter drops by 60 - # process precisely 60 with TO_BE_CONTIN flag - _SerialWrite("x" + chr(self.cePin) + chr(0x10 + self.mode) + chr(60)) - _SerialWrite(buf1) - _SerialRead() # wait on some reply ( for syncing) - - # Now we have 1 to 60 in last block - _SerialWrite("x" + chr(self.cePin) + chr(self.mode) + chr(L)) - _SerialWrite(buf) - _SerialRead() # wait on a reply - return - - def fill(self, count16, data16): - # Repetitive write of 1 or 2 bytes. NOT a RPI function! - # Useful for TFT clear screen operations on virt-gpio (for speed) - _SerialWrite("g" + chr(self.cePin) + chr(self.mode)) - _SerialWrite([count16&0xff, count16>>8, data16&0xff, data16>>8]) - _SerialRead() # just for sync-ing - - def close(self): - print ("SPI CLOSE not supported") - -############################################### - -class SerialTx: - # up to five TTL (5V) "COM ports", transmit only, bit-banged (no interrupts or timers) - # unbuffered, 2400 baud, blocking (exc port 0) until sent. - # All ports are at same baudrate, compiled at arduino. - # (Can recompile to 75 300 2400 9600 19200 38400 57600.) - # PORT 0 IS DIFFERENT: output at arduino is buffered and transmitted by loop() when idle. - # Ports 1 to 4 are direct transmit. - # Port 0 was used for internal sketch diagnostic. Using it here will over-ride diag use. - - # To send binary data, submit it as a character string. - - def __init__(self, port, pin): # port 0-4, pin any digital-out capable pin - self.port = port - _SerialWrite([0xc0, port, pin]) - - def Print(self, x): # single parameter - if not (type(x) == type ("123")): - x = str(x) # Whatever format, coerce it into string - _SerialWrite([0xc1, self.port, len(x)]) - _SerialWrite(x) - return _serialread1int8(0) - - def PrintLN(self, x): - x = str(x) + "\n" - return self.Print(x) - - def Write(self, x): - self.Print(chr(x)) - - -################################################### - -class SerialRx: - # pin 8 only - def __init__(self, baud): - _SerialWrite([0xd0, 3]) - - def available(self): - _SerialWrite([0xd1]) - # returns a count - return _serialread1int8(0) - - def read(self, count): - _SerialWrite([0xd2, count]) - buf2 = _SerialRead(count) - # pyserial's serial.read() returns STRING or BYTES (of CHARs) - # but we want LIST of 8-bit integers as our return format - L2 = len(buf2) - if L2 32: - print ("I2C limit at arduino is 32 chars !!") - L = len(txbuf) - _SerialWrite("W" + chr(L) + chr(port)) - _SerialWrite(txbuf); - _SerialRead() # just for syncing v0.9.5 - - - def read(self, port, count): - # returns list, with result code then []*count - _SerialWrite("c") - _SerialWrite([count, port]) - buf2 = _SerialRead(count) - count2 = len(buf2) - buf3 = [0] * (count+1) # empty dummy of the correct length/format - if count2>8]) - self.id = id&1 - self.SPR = stepsPerRev - - def setSpeedRPM(self, speedRPM): # integer speed in RPM (positive number) - _SerialWrite([0xb2, self.id, speedRPM&0xff, speedRPM>>8]) - self.speedRPM = abs(speedRPM) - - def step(self, steps, wait=True): # steps negative for reverse rotation +-32000 - self.steps = abs(steps) - steps = cInt16(steps) - _SerialWrite([0xb3, self.id, steps&0xff, steps>>8] ) - if wait: - self.waitToFinish() - - def stepsLeft(self): - _SerialWrite([0xb4, self.id] ) - return _serialread2int16(0) - - def waitToFinish(self): - wtime = ((1.3 * self.steps) // self.speedRPM) * 60 // self.SPR - t1 = time.time() - r=0 - while (time.time() - t1) < wtime: - if self.stepsLeft() == 0: - r=1 - break - return r # optional return code 0=timeout 1=normal finish - - - -############################################### - -class Intcounter: # two counters using INT0 and INT1 - # These counters operate only on pins d2/d3. (This is a 328 chip hardware constraint.) - # if QUAD encoder selected, d2 pairs with d4, d3 pairs with d5 - - RISING = 0x03 # AVR code - FALLING = 0x02 # AVR code - CHANGE = 0x01 # AVR code - QUAD = 0x05 # change + 0x04 - - def __init__(self, pin, mode): # pin 2 or 3, mode as above - if pin==2 or pin == 3: - _SerialWrite("2" + chr(pin) + chr(mode)) - - - def read(self, andZero=False): # optional counter clear, read as time-matched pair. - _SerialWrite("," + chr(andZero &1)) - c0 = _serialread2int16(0xffff) - c1 = _serialread2int16(0xffff) - return [c0, c1] - - - -############################################### - -class HWcounter: # true (one-only) 16bit MCU hardware counter: no interrupts. - # This counter operates only on pin d5. (This is a 328 chip hardware constraint.) - # This function kills any other timer1 operation (or PWM on pins 9, 10) - - - def __init__(self): - AVR.write8(AVR.TCCR1A, 0) # reset timer/counter control register A - AVR.write8(AVR.TCCR1B, AVR.CS10+AVR.CS11+AVR.CS12) # Counter on external pin, rising edge - self.zero() - # once initialised, the counter always is active - - def zero(self): # CLEAR the counter to 0x0000 - AVR.write16(AVR.TCNT1, 0) - - def read(self): - return AVR.read16(AVR.TCNT1, 0xffff) - - - -############################################### - - -class InfraRedRx: - # Uses Timer2, so PWM on p3, p11 disabled - - def __init__(self, pin): - self.devicenum = 0 # ID of hand remote - _SerialWrite("F" + chr(pin & 0x0f)) - - def read(self): # fetch IR code from remote - _SerialWrite("f"); - ir = _serialread4int32(0xffffffff) - self.devicenum = ir & 0xFFFF - return (ir >>16)&0xff - - def device(self): # read remote device number of latest read - return self.devicenum - # only valid immediately after a read - - -############################################### - -class PWMplus: - # only pins 9 &/or 10. Uses Timer1 - - def __init__(self): - _SerialWrite ([0x81]) - self.pinBusy = [0,0] - - def setPeriod(self, usec): # usec from 1 to 1,000,000 - _SerialWrite ([0x82, usec & 0x0000ff, (usec & 0x0FF00)>>8, usec//65536] ) - - def initPin(self, pin, duty): # pin = 9 or 10 only. duty 0 to 1023 - if pin < 9 or pin > 10: - return - if self.pinBusy[pin-9]: - self.changeDuty(pin, duty) - return - self.pinBusy[pin-9] = 1 - _SerialWrite ([0x83, pin, duty & 0x00ff, duty >>8]) - - def changeDuty(self,pin,duty): - _SerialWrite ([0x84, pin, duty & 0x00ff, duty >>8]) - - - def releasePin(self,pin): - if pin < 9 or pin > 10: - return - _SerialWrite ([0x85, pin] ) - self.pinBusy[pin-9] = 0 - - def stop(self): - _SerialWrite ([0x86, 0]) - - def restart(self): - _SerialWrite ([0x86, 1]) - - def tone(self, pin, freq): - self.setPeriod(1000000 // freq) - self.initPin(pin, 511) - - def noTone(self, pin): - self.releasePin(pin) - -############################################### - - -# DIAGNOSTIC/DEBUG STUFF: - -class Trace: #developer use. - def __init__(self): - pass - def Start(self): - _SerialWrite("^") - - def Stop(self): - _SerialWrite("<") - - def Print(self): - _SerialWrite(">") - # Will not print if Serial0 (ie COM port 0) is not initialised - -def mopup(): - # Testing only - #time.sleep(.003) - #print "Mop up: " , - while(Serial.inWaiting()): # anything to mopup??? - r=_SerialRead() - print (" {%x}" % ( _i8(r))), - - -############################################### - - -def sync(timeout = 0.25, printping = False): # 0.5 - 1.0 mSec when no catchup needed - # Use in user code after several non-reporting commands, so that sender can not - # get too many serial characters ahead of slave unit. - # Only likely calls that MIGHT need this are multiple AVR.write, Servo.write, SerialTX.write - # Note GPIO.output and I2C.write should be immune, with inbuilt sync function. - - # Also useable as a visible "ping" - _SerialWrite("=") - Serial.timeout = timeout - r=_serialread1int8(0xf6) - Serial.timeout = STDTIMEOUT - if printping: - # Diagnostic use - print ("Ping response %s %x" % (chr(r),r) ) # should report "=" chr - return r - -def readFreePins(): - # Diagnostic tool - _SerialWrite ("q") - print ("") - print (" GP pins AAAAAAAA111100000000TR") - print (" 1=free 76543210321098765432rd") - print (bin(0x80300000 | _serialread4int32(0))) - # top bit: just to align the display. Bits for A6 A7 added for display. They remain always avbl. - - -def VccRead(): - _SerialWrite("+") - return _serialread2int16(0)/1000.0 - - -def printCompileDate(): - # Diagnostic tool - _SerialWrite('t') - time.sleep(.05) - print ("") - print ("Compile/Load Date: " ), - datstr="" - while(Serial.inWaiting()): - datstr += chr(_i8(_SerialRead()[0])) - print (datstr) - -def getVersion(): - _SerialWrite('T') - return _serialread1int8(0) - - -def clearResetFlag(): # at slave - _SerialWrite("i") - -def resetFlagIsOn(): # optional test whether slave has since suffered a reset - return (readFlags() & 1) - -def readFlags(): - # Flag bits (confirm at VirtGPIO.ino): - # enum {F_reset=0, F_spi, F_svo, F_ir, F_i2c, F_intctr, F_pwm, - # F_stepr, F_actled, F_nospi, F_TxCom, F_RxCom, F_badchar=15}; - _SerialWrite("n"); - return _serialread2int16(0xff) - -def restart_program(): - #Restarts the current program. - python = sys.executable - os.execl(python, python, * sys.argv) - -def checkPinsFree(pinslist): - # returns false if ANY of the pins is reserved - _SerialWrite ("q") - a = _serialread4int32(0) - for k in range(len(pinslist)): - if not (a & (1<3 : - return _i8(a[0]) + (_i8(a[1])<<8) + (_i8(a[2]) << 16) + (_i8(a[3]) << 24) - else: - return errorflag32 - -def _serialread2int16(errorflag16): - # read 2 byte and format as a python integer - # if read fail, return known error flag - a = _SerialRead(2) - if len(a) >1 : - return _i8(a[0]) + (_i8(a[1])<<8) - else: - return errorflag16 - -def _serialread1int8(errorflag8): - # read 1 bytes and format as python integer - a = _SerialRead() - if len(a) : - return _i8(a[0]) - else: - return (errorflag8 & 0xff) - - -from ctypes import * -def cByte(i): - return c_ubyte(i).value -def cInt16(i): - return c_ushort(i).value -def cInt32(i): - return c_uint(i).value -def cInt32FromFloat(f): - return cInt32(int(f)) -def str1FromByte(i): - return chr(cByte(i)) - - -# Still flagged for possible change: -# 1. HWcounter enhance to more than 16 bits - eg see "Arduino Internals" ebook -# 2. arduino end - more robust serial timeouts -# 3. Clean python docstrings - - -# Changes made V0.9 -> v0.9.5 : -# Added serialConfig.py for port settings -# Sonar removed from virtGPIO core, out to simple example script -# SPI devices get individual control of mode -# i2c - option to disable arduino's internal pullups -# SPI.xfer2() out to 80 chars, and added unlimited SPI.writebytes() -# Improved RPI syntax compatibility -# Now Python 2.7 / Python 3.3 compatible - -""" - * Copyright (c) 2014 Brian Lavery http://virtgpio.blavery.com - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * -""" - - diff --git a/old/test.py b/old/test.py deleted file mode 100644 index e69de29..0000000 diff --git a/old/test.sh b/old/test.sh deleted file mode 100644 index 247526e..0000000 --- a/old/test.sh +++ /dev/null @@ -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" \ No newline at end of file diff --git a/old/test2.py b/old/test2.py deleted file mode 100644 index 5ed4700..0000000 --- a/old/test2.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/old/webserver/HTTPRequestHandler.py b/old/webserver/HTTPRequestHandler.py deleted file mode 100644 index d544242..0000000 --- a/old/webserver/HTTPRequestHandler.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/webserver/HTTPServer.py b/old/webserver/HTTPServer.py deleted file mode 100644 index 8661031..0000000 --- a/old/webserver/HTTPServer.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/old/webserver/HTTPWebSocketsHandler.py b/old/webserver/HTTPWebSocketsHandler.py deleted file mode 100644 index 48f6247..0000000 --- a/old/webserver/HTTPWebSocketsHandler.py +++ /dev/null @@ -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) - }) - ) diff --git a/old/webserver/SimpleWebSocketServer.py b/old/webserver/SimpleWebSocketServer.py deleted file mode 100644 index 66726c8..0000000 --- a/old/webserver/SimpleWebSocketServer.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/old/webserver/WebSocketServer.py b/old/webserver/WebSocketServer.py deleted file mode 100644 index 9eab79e..0000000 --- a/old/webserver/WebSocketServer.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/old/webserver/__pycache__/HTTPWebSocketsHandler.cpython-36.pyc b/old/webserver/__pycache__/HTTPWebSocketsHandler.cpython-36.pyc deleted file mode 100644 index abd176c..0000000 Binary files a/old/webserver/__pycache__/HTTPWebSocketsHandler.cpython-36.pyc and /dev/null differ diff --git a/old/webserver/__pycache__/SimpleWebSocketServer.cpython-36.pyc b/old/webserver/__pycache__/SimpleWebSocketServer.cpython-36.pyc deleted file mode 100644 index 170571f..0000000 Binary files a/old/webserver/__pycache__/SimpleWebSocketServer.cpython-36.pyc and /dev/null differ diff --git a/old/webserver/__pycache__/WebSocketServer.cpython-36.pyc b/old/webserver/__pycache__/WebSocketServer.cpython-36.pyc deleted file mode 100644 index 4af0635..0000000 Binary files a/old/webserver/__pycache__/WebSocketServer.cpython-36.pyc and /dev/null differ diff --git a/old/ws2812b sketch/ws2812b_sketch.ino b/old/ws2812b sketch/ws2812b_sketch.ino deleted file mode 100644 index 5768db1..0000000 --- a/old/ws2812b sketch/ws2812b_sketch.ino +++ /dev/null @@ -1,147 +0,0 @@ -#include - -#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; - } - } -}