diff --git a/.gitignore b/.gitignore index 5f4535c..484b769 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,10 @@ *.userosscache *.sln.docstates +node_modules +clients/controller-html/old +clients/strip-wemosd1-websocket/settings.example.h + .directory # User-specific files (MonoDevelop/Xamarin Studio) diff --git a/app/rgbUtils/__init__.py b/app/rgbUtils/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/clients/controller-html/Dockerfile b/clients/controller-html/Dockerfile new file mode 100644 index 0000000..337f9aa --- /dev/null +++ b/clients/controller-html/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx:stable-alpine + +RUN apk add --update nodejs nodejs-npm + +COPY . /usr/share/nginx/html + +RUN cd /usr/share/nginx/html && npm install diff --git a/htdocs/favicon.ico b/clients/controller-html/favicon.ico similarity index 100% rename from htdocs/favicon.ico rename to clients/controller-html/favicon.ico diff --git a/htdocs/htmlstrip.html b/clients/controller-html/htmlstrip.html similarity index 92% rename from htdocs/htmlstrip.html rename to clients/controller-html/htmlstrip.html index 8e83771..cb3484f 100644 --- a/htdocs/htmlstrip.html +++ b/clients/controller-html/htmlstrip.html @@ -3,13 +3,14 @@ + {{data}}
{{value}}
- - + + - - + + + - - - + + + + - - - - + + + + - - - - - - - - - diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 6bad103..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -numpy -scipy diff --git a/run-autopep8-docker.sh b/run-autopep8-docker.sh new file mode 100755 index 0000000..32810d8 --- /dev/null +++ b/run-autopep8-docker.sh @@ -0,0 +1,12 @@ +#!/bin/sh +docker run \ + --rm \ + -i \ + --network=host \ + -v "$HOME":"$HOME":ro \ + -u $(id -u) \ + -w "$PWD" \ + unibeautify/autopep8 \ + $@ + +exit $? \ No newline at end of file diff --git a/run-pylint-docker.sh b/run-pylint-docker.sh new file mode 100755 index 0000000..5aab4f7 --- /dev/null +++ b/run-pylint-docker.sh @@ -0,0 +1,12 @@ +#!/bin/sh +docker run \ + --rm \ + -i \ + --network=host \ + -v "$HOME":"$HOME":ro \ + -u $(id -u) \ + -w "$PWD" \ + clburlison/pylint:py3-alpine \ + pylint $@ + +exit $? \ No newline at end of file diff --git a/run-python-docker.sh b/run-python-docker.sh new file mode 100755 index 0000000..8b49bae --- /dev/null +++ b/run-python-docker.sh @@ -0,0 +1,12 @@ +#!/bin/sh +docker run \ + --rm \ + -i \ + --network=host \ + -v "$HOME":"$HOME":ro \ + -u $(id -u) \ + -w "$PWD" \ + $USER/ledserver:latest \ + python3.7 $@ + +exit $? \ No newline at end of file diff --git a/app/BackendProvider/Helper/SimpleWebSocketServer.py b/server/BackendProvider/Helper/SimpleWebSocketServer.py similarity index 100% rename from app/BackendProvider/Helper/SimpleWebSocketServer.py rename to server/BackendProvider/Helper/SimpleWebSocketServer.py diff --git a/app/BackendProvider/Helper/__init__.py b/server/BackendProvider/Helper/__init__.py similarity index 100% rename from app/BackendProvider/Helper/__init__.py rename to server/BackendProvider/Helper/__init__.py diff --git a/app/BackendProvider/WebSocketServer.py b/server/BackendProvider/WebSocketServer.py similarity index 100% rename from app/BackendProvider/WebSocketServer.py rename to server/BackendProvider/WebSocketServer.py diff --git a/app/BackendProvider/WemosStripUDPServer.py b/server/BackendProvider/WemosStripUDPServer.py similarity index 71% rename from app/BackendProvider/WemosStripUDPServer.py rename to server/BackendProvider/WemosStripUDPServer.py index 6d8c6a0..6d69045 100644 --- a/app/BackendProvider/WemosStripUDPServer.py +++ b/server/BackendProvider/WemosStripUDPServer.py @@ -6,8 +6,9 @@ from time import sleep, time import json import struct + class ThreadedUDPServer(threading.Thread): - def __init__(self,effectController,rgbStripController): + def __init__(self, effectController, rgbStripController): threading.Thread.__init__(self) self.effectController = effectController self.rgbStripController = rgbStripController @@ -17,7 +18,7 @@ class ThreadedUDPServer(threading.Thread): self.udpClientGuardian = self.UDPClientGuardian() self.udpClientGuardian.start() UDPClients - + def run(self): self.server = socketserver.UDPServer(('', 8002), UDPStripHandler) self.server.effectController = self.effectController @@ -28,8 +29,8 @@ class ThreadedUDPServer(threading.Thread): def stop(self): self.udpClientGuardian.stop() self.server.shutdown() - - # check last pings from clients, responds with pong and remove clients + + # check last pings from clients, responds with pong and remove clients # when there is no answer after 2 seconds class UDPClientGuardian(threading.Thread): def __init__(self): @@ -54,16 +55,19 @@ CLIENT_TYPE_RECORDER = 2 UDPClients = {} + class UDPStripHandler(socketserver.BaseRequestHandler): def handle(self): - #print(self.client_address) + # print(self.client_address) if self.client_address not in UDPClients: - UDPClients[self.client_address] = UDPClient(self.client_address,self.server.effectController,self.server.rgbStripController) + UDPClients[self.client_address] = UDPClient( + self.client_address, self.server.effectController, self.server.rgbStripController) UDPClients[self.client_address].handle(self.request) - + + class UDPClient(): - def __init__(self,client_address,effectController,rgbStripController): + def __init__(self, client_address, effectController, rgbStripController): self.client_type = None self.rgbStrip = None self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -73,7 +77,7 @@ class UDPClient(): self.sendToClientLock = False self.lastping = time() - def handle(self,request): + def handle(self, request): clientdata = request[0].decode() self.socket = request[1] @@ -83,29 +87,33 @@ class UDPClient(): try: data = clientdata.split(':') - #print(data) - #r:1:srg strip name + # print(data) + # r:1:srg strip name if data[0] == "r" and int(data[1]) == CLIENT_TYPE_STRIPE and data[2] != None: - 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[2],self.onRGBStripValueUpdate) - #s:ping + 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[2], self.onRGBStripValueUpdate) + # s:ping if data[0] == "s" and data[1] == "ping": # if we got a ping and the client has no client type defined, send status unregistered, so the client knows that he has to register if self.client_type is None and self.socket is not None: self.sendToClient('s:unregistered') self.lastping = time() + if data[0] == "u" and self.client_type == CLIENT_TYPE_STRIPE: + led = int(data[1]) + self.sendToClient('d:'+str(led)+':'+str(self.rgbStrip.red[led])+':'+str( + self.rgbStrip.green[led])+':'+str(self.rgbStrip.blue[led])+'') except Exception as e: print(e, traceback.format_exc()) - - # 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_STRIPE: self.rgbStripController.unregisterRGBStrip(self.rgbStrip) @@ -113,11 +121,12 @@ class UDPClient(): # when a rgbStrip value is changed, send not json data but a formated string to client # d:[id off the LED, always 0 on RGB strips]:[red value 0-255]:[green value 0-255]:[blue value 0-255] - def onRGBStripValueUpdate(self,rgbStrip,led = 0): - self.sendToClient('d:'+str(led)+':'+str(rgbStrip.red[led])+':'+str(rgbStrip.green[led])+':'+str(rgbStrip.blue[led])+'') - + def onRGBStripValueUpdate(self, rgbStrip, led=0): + return # we send the update as requested, to prevent flooding the module + #self.sendToClient('d:'+str(led)+':'+str(rgbStrip.red[led])+':'+str( + # rgbStrip.green[led])+':'+str(rgbStrip.blue[led])+'') - def sendToClient(self,message): + def sendToClient(self, message): while self.sendToClientLock is True: sleep(1) self.sendToClientLock = True @@ -125,4 +134,4 @@ class UDPClient(): self.socket.sendto( message.encode(), self.client_address ) - self.sendToClientLock = False \ No newline at end of file + self.sendToClientLock = False diff --git a/app/BackendProvider/__init__.py b/server/BackendProvider/__init__.py similarity index 100% rename from app/BackendProvider/__init__.py rename to server/BackendProvider/__init__.py diff --git a/Dockerfile b/server/Dockerfile similarity index 58% rename from Dockerfile rename to server/Dockerfile index f74597d..0ff5bf0 100644 --- a/Dockerfile +++ b/server/Dockerfile @@ -4,12 +4,8 @@ RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /et RUN apk add --update --no-cache ca-certificates gcc g++ curl openblas-dev@community RUN ln -s /usr/include/locale.h /usr/include/xlocale.h -WORKDIR /usr/src/app +WORKDIR /usr/src/LEDServer +RUN pip3 install --no-cache-dir numpy scipy -COPY requirements.txt ./ -RUN pip3 install --no-cache-dir -r requirements.txt - -#COPY . . - -#CMD [ "ls", "/usr/src/app/" ] -#CMD [ "python3.7", "/usr/src/app/LEDServer.py" ] +COPY . /usr/src/LEDServer +CMD python3.7 -u /usr/src/LEDServer/LEDServer.py \ No newline at end of file diff --git a/app/LEDServer.py b/server/LEDServer.py old mode 100644 new mode 100755 similarity index 82% rename from app/LEDServer.py rename to server/LEDServer.py index 38b8342..611a4ea --- a/app/LEDServer.py +++ b/server/LEDServer.py @@ -1,9 +1,10 @@ #!/usr/bin/python - import os import sys import time import traceback + + def main(): try: @@ -13,23 +14,25 @@ def main(): # 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? + # 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 + # 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) + 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 @@ -37,22 +40,26 @@ def main(): # but then there must be some autoloading of modules in a folder like the effects for easy installing. //todo :) print("starting websocket:8001") import BackendProvider.WebSocketServer as WebSocketServer - webSocketThread = WebSocketServer.ThreadedWebSocketServer(effectController,rgbStripController) - + webSocketThread = WebSocketServer.ThreadedWebSocketServer( + effectController, rgbStripController) + print("starting UDPServer:8002") import BackendProvider.WemosStripUDPServer as UPDSocketServer - udpSocketThread = UPDSocketServer.ThreadedUDPServer(effectController,rgbStripController) + udpSocketThread = UPDSocketServer.ThreadedUDPServer( + effectController, rgbStripController) while running: time.sleep(1) except Exception as e: running = False - print(e,traceback.format_exc()) + print(e, traceback.format_exc()) finally: print('shutting down the LED-Server') webSocketThread.stop() udpSocketThread.stop() effectController.stopAll() -if __name__=='__main__': - main() \ No newline at end of file + + +if __name__ == '__main__': + main() diff --git a/app/config.py b/server/config.py similarity index 100% rename from app/config.py rename to server/config.py diff --git a/app/__init__.py b/server/effects/__init__.py similarity index 100% rename from app/__init__.py rename to server/effects/__init__.py diff --git a/app/effects/musikEffect.py b/server/effects/musikEffect.py.out similarity index 100% rename from app/effects/musikEffect.py rename to server/effects/musikEffect.py.out diff --git a/app/effects/offEffect.py b/server/effects/offEffect.py similarity index 100% rename from app/effects/offEffect.py rename to server/effects/offEffect.py diff --git a/app/effects/onEffect.py b/server/effects/onEffect.py similarity index 100% rename from app/effects/onEffect.py rename to server/effects/onEffect.py diff --git a/app/effects/rainbowEffect.py b/server/effects/rainbowEffect.py similarity index 100% rename from app/effects/rainbowEffect.py rename to server/effects/rainbowEffect.py diff --git a/app/effects/strobeEffect.py b/server/effects/strobeEffect.py similarity index 100% rename from app/effects/strobeEffect.py rename to server/effects/strobeEffect.py diff --git a/app/rgbUtils/BaseEffect.py b/server/rgbUtils/BaseEffect.py similarity index 100% rename from app/rgbUtils/BaseEffect.py rename to server/rgbUtils/BaseEffect.py diff --git a/app/rgbUtils/EffectParameter.py b/server/rgbUtils/EffectParameter.py similarity index 100% rename from app/rgbUtils/EffectParameter.py rename to server/rgbUtils/EffectParameter.py diff --git a/app/rgbUtils/RGBStrip.py b/server/rgbUtils/RGBStrip.py similarity index 100% rename from app/rgbUtils/RGBStrip.py rename to server/rgbUtils/RGBStrip.py diff --git a/app/effects/__init__.py b/server/rgbUtils/__init__.py similarity index 100% rename from app/effects/__init__.py rename to server/rgbUtils/__init__.py diff --git a/app/rgbUtils/debug.py b/server/rgbUtils/debug.py similarity index 100% rename from app/rgbUtils/debug.py rename to server/rgbUtils/debug.py diff --git a/app/rgbUtils/effectController.py b/server/rgbUtils/effectController.py similarity index 100% rename from app/rgbUtils/effectController.py rename to server/rgbUtils/effectController.py diff --git a/app/rgbUtils/effectControllerJsonHelper.py b/server/rgbUtils/effectControllerJsonHelper.py similarity index 100% rename from app/rgbUtils/effectControllerJsonHelper.py rename to server/rgbUtils/effectControllerJsonHelper.py diff --git a/app/rgbUtils/pyAudioRecorder.py b/server/rgbUtils/pyAudioRecorder.py similarity index 100% rename from app/rgbUtils/pyAudioRecorder.py rename to server/rgbUtils/pyAudioRecorder.py diff --git a/app/rgbUtils/rgbStripController.py b/server/rgbUtils/rgbStripController.py similarity index 100% rename from app/rgbUtils/rgbStripController.py rename to server/rgbUtils/rgbStripController.py diff --git a/app/rgbUtils/rgbStripControllerJsonHelper.py b/server/rgbUtils/rgbStripControllerJsonHelper.py similarity index 100% rename from app/rgbUtils/rgbStripControllerJsonHelper.py rename to server/rgbUtils/rgbStripControllerJsonHelper.py