aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stendahl <jakob.stendahl@outlook.com>2018-10-18 12:41:52 +0200
committerJakob Stendahl <jakob.stendahl@outlook.com>2018-10-18 12:41:52 +0200
commit5cb309a9bb3481534b353cb50c707a64b4155c00 (patch)
tree7174a2ef0847fa278315f9425e4007771351bc28
parent48ff3bd3d62cf4d1d86438e817808fd204e6266a (diff)
downloadLuxcena-Neo-5cb309a9bb3481534b353cb50c707a64b4155c00.tar.gz
Luxcena-Neo-5cb309a9bb3481534b353cb50c707a64b4155c00.zip
:construction: Work on installer and making the supportfiles do led control
-rw-r--r--app.js7
-rwxr-xr-xbin/install.sh77
-rw-r--r--src/compileAndRun/pythonSupportFiles/LuxcenaNeo/Strip.py163
-rw-r--r--src/compileAndRun/pythonSupportFiles/entry.py4
4 files changed, 192 insertions, 59 deletions
diff --git a/app.js b/app.js
index 01f7242..406ecbd 100644
--- a/app.js
+++ b/app.js
@@ -63,7 +63,12 @@ if (!fse.existsSync(dataDir + "/config/versionChecker.json")) {
if (!fse.existsSync(dataDir + "/config/strip.json")) {
fse.writeJsonSync(dataDir + "/config/strip.json", {
"segments": [9, 8, 8, 8, 8, 8, 4],
- "segmentConfiguration": "snake"
+ "segmentConfiguration": "snake",
+ "led_pin": 18,
+ "led_freq_hz": 800000,
+ "led_dma": 10,
+ "led_invert": false,
+ "led_channel": 0
})
}
diff --git a/bin/install.sh b/bin/install.sh
index c72949b..25c5dc8 100755
--- a/bin/install.sh
+++ b/bin/install.sh
@@ -98,69 +98,44 @@ tput sgr0
tput sc
tput bel
-piModel=0
-printf "\n\n\n" # So that the menu just erases things it has alredy written
-while :
-do
- tput cuu 3
- tput ed
- tput sc
- tput setaf 8
-
- if [[ piModel -eq 0 ]]; then
- tput sgr0; fi
- printf '%s\n' "- Raspberry Pi B"
- tput setaf 8
- if [[ piModel -eq 1 ]]; then
- tput sgr0; fi
- printf '%s\n' "- Raspberry Pi B+"
- tput setaf 8
- if [[ piModel -eq 2 ]]; then
- tput sgr0; fi
- printf '%s\n' "- Raspberry Pi Model 2"
- tput setaf 8
-
- read -sn1 key
- if [ "$key" == "j" ]; then
- piModel=$((piModel+1))
- if [[ piModel -gt 2 ]]; then
- piModel=2
- fi
- fi
- if [ "$key" == "k" ]; then
- piModel=$((piModel-1))
- if [[ piModel -lt 0 ]]; then
- piModel=0
- fi
- fi
- if [ "$key" == "" ]; then
- tput cuu 4
- tput ed
- tput sgr0
- printf "%s\e[0;34m%s\e[0m\n" ". Which rPi is this? " "ListItem #$piModel"
- break
- fi
-
-done
-
-
tput setaf 4
printf ". Installing the app itself...\n"
tput sgr0
+# Create user 'luxcena-neo'
+tput setaf 8
+printf '%s\n' " - Creating user 'lux-neo'..."
+username="lux-neo"
+egrep "^$username" /etc/passwd >/dev/null
+if [ $? -eq 0 ]; then
+ echo "$username exists!"
+ exit 1
+else
+ #pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
+ useradd -m $username
+ [ $? -eq 0 ] && echo "User has been added to system!" || { printf "\n\nInstall failed.\n"; exit 1; }
+fi
+tput sgr0
+
+# Change to the new user
+tput setaf 8
+printf '%s\n' " - Changing to new user..."
+sudo su lux-neo
+tput sgr0
+
# First we make our directories
tput setaf 8
printf '%s\n' " - Making app-dir (/bin/luxcena-neo)..."
tput sgr0
-mkdir ~/luxcena-neo-install || { printf "\n\nInstall failed.\n"; exit 1; }
-mkdir ~/luxcena-neo-install/src || { printf "\n\nInstall failed.\n"; exit 1; }
-mkdir ~/luxcena-neo-install/userdata || { printf "\n\nInstall failed.\n"; exit 1; }
+mkdir ~/install || { printf "\n\nInstall failed.\n"; exit 1; }
+mkdir ~/install/src || { printf "\n\nInstall failed.\n"; exit 1; }
+mkdir ~/install/userdata || { printf "\n\nInstall failed.\n"; exit 1; }
# Third we copy the source into the correct swap-folder
tput setaf 8
printf '%s\n' " - Copying sourceCode to app-dir..."
tput sgr0
-cp -r . ~/luxcena-neo-install/src || { printf "\n\nInstall failed.\n"; exit 1; }
+cp -r . ~/install/src || { printf "\n\nInstall failed.\n"; exit 1; }
# fourth we run npm i
tput setaf 8
@@ -168,7 +143,7 @@ printf '%s\n' " - Running npm i..."
tput sgr0
tput sc
export NODE_ENV=production || { printf "\n\nInstall failed.\n"; exit 1; }
-npm --prefix ~/luxcena-neo-install/src install ~/luxcena-neo-install/src --only=production || { printf "\n\nInstall failed.\n"; exit 1; } # This is probably a bit overkill to have --only=... but better safe than sorry?
+npm --prefix ~/install/src install ~/install/src --only=production || { printf "\n\nInstall failed.\n"; exit 1; } # This is probably a bit overkill to have --only=... but better safe than sorry?
tput rc; tput ed
# Fifth we add the service files
diff --git a/src/compileAndRun/pythonSupportFiles/LuxcenaNeo/Strip.py b/src/compileAndRun/pythonSupportFiles/LuxcenaNeo/Strip.py
index c4ac8c9..f5beaa4 100644
--- a/src/compileAndRun/pythonSupportFiles/LuxcenaNeo/Strip.py
+++ b/src/compileAndRun/pythonSupportFiles/LuxcenaNeo/Strip.py
@@ -1,6 +1,161 @@
+#from neopixel import *
+import atexit
+import _rpi_ws281x as ws
+
class Strip:
- def __init__(self, segments, segmentConfiguration):
- self.segments = segments
- self.segmentConfiguration = segmentConfiguration
- return
+ def __init__(self, stripConf):
+ """Class to represent a NeoPixel/WS281x LED display. Num should be the
+ number of pixels in the display, and pin should be the GPIO pin connected
+ to the display signal line (must be a PWM pin like 18!). Optional
+ parameters are freq, the frequency of the display signal in hertz (default
+ 800khz), dma, the DMA channel to use (default 10), invert, a boolean
+ specifying if the signal line should be inverted (default False), and
+ channel, the PWM channel to use (defaults to 0).
+ """
+ self.SEGMENTS = stripConf["segments"]
+ self.SEGMENT_CONFIG = stripConf["segment_config"]
+
+ self.LED_FREQ_HZ = stripConf["led_freq_hz"] # LED signal frequency in hertz (usually 800khz)
+ self.LED_CHANNEL = stripConf["led_channel"] # Set to '1' for GPIOs 13, 19, 41, 45, 53
+ self.LED_INVERT = stripConf["led_invert"] # True to invert the signal, (when using NPN transistor level shift)
+ self.LED_PIN = stripConf["led_pin"] # 18 uses PWM, 10 uses SPI /dev/spidev0.0
+ self.LED_DMA = stripConf["led_dma"] # DMA channel for generating the signal, on the newer ones, try 10
+ self.LED_COUNT = sum(self.SEGMENTS) # Number of LEDs in strip
+
+
+ self.LED_BRIGHTNESS = 255
+
+ # Create ws2811_t structure and fill in parameters.
+ self._leds = ws.new_ws2811_t()
+
+ # Initialize the channels to zero
+ for channum in range(2):
+ chan = ws.ws2811_channel_get(self._leds, channum)
+ ws.ws2811_channel_t_count_set(chan, 0)
+ ws.ws2811_channel_t_gpionum_set(chan, 0)
+ ws.ws2811_channel_t_invert_set(chan, 0)
+ ws.ws2811_channel_t_brightness_set(chan, 0)
+
+ # Initialize the channel in use
+ self._channel = ws.ws2811_channel_get(self._leds, channel)
+ ws.ws2811_channel_t_count_set(self._channel, num)
+ ws.ws2811_channel_t_gpionum_set(self._channel, pin)
+ ws.ws2811_channel_t_invert_set(self._channel, 0 if not invert else 1)
+ ws.ws2811_channel_t_brightness_set(self._channel, brightness)
+ ws.ws2811_channel_t_strip_type_set(self._channel, strip_type)
+
+ # Initialize the controller
+ ws.ws2811_t_freq_set(self._leds, freq_hz)
+ ws.ws2811_t_dmanum_set(self._leds, dma)
+
+ # Grab the led data array.
+ self._led_data = _LED_Data(self._channel, num)
+
+ # Substitute for __del__, traps an exit condition and cleans up properly
+ atexit.register(self._cleanup)
+
+ def _cleanup(self):
+ # Clean up memory used by the library when not needed anymore.
+ if self._leds is not None:
+ ws.delete_ws2811_t(self._leds)
+ self._leds = None
+ self._channel = None
+
+ def begin(self):
+ """Initialize library, must be called once before other functions are
+ called.
+ """
+ resp = ws.ws2811_init(self._leds)
+ if resp != ws.WS2811_SUCCESS:
+ message = ws.ws2811_get_return_t_str(resp)
+ raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message))
+
+ def show(self):
+ """Update the display with the data from the LED buffer."""
+ resp = ws.ws2811_render(self._leds)
+ if resp != ws.WS2811_SUCCESS:
+ message = ws.ws2811_get_return_t_str(resp)
+ raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message))
+
+ def setPixelColor(self, n, color):
+ """Set LED at position n to the provided 24-bit color value (in RGB order).
+ """
+ self._led_data[n] = color
+
+ def setPixelColorRGB(self, n, red, green, blue, white = 0):
+ """Set LED at position n to the provided red, green, and blue color.
+ Each color component should be a value from 0 to 255 (where 0 is the
+ lowest intensity and 255 is the highest intensity).
+ """
+ self.setPixelColor(n, Color(red, green, blue, white))
+
+ def setBrightness(self, brightness):
+ """Scale each LED in the buffer by the provided brightness. A brightness
+ of 0 is the darkest and 255 is the brightest.
+ """
+ ws.ws2811_channel_t_brightness_set(self._channel, brightness)
+
+ def getBrightness(self):
+ """Get the brightness value for each LED in the buffer. A brightness
+ of 0 is the darkest and 255 is the brightest.
+ """
+ return ws.ws2811_channel_t_brightness_get(self._channel)
+
+ def getPixels(self):
+ """Return an object which allows access to the LED display data as if
+ it were a sequence of 24-bit RGB values.
+ """
+ return self._led_data
+
+ def numPixels(self):
+ """Return the number of pixels in the display."""
+ return ws.ws2811_channel_t_count_get(self._channel)
+
+ def getPixelColor(self, n):
+ """Get the 24-bit RGB color value for the LED at position n."""
+ return self._led_data[n]
+
+
+def Color(red, green, blue, white = 0):
+ """Convert the provided red, green, blue color to a 24-bit color value.
+ Each color component should be a value 0-255 where 0 is the lowest intensity
+ and 255 is the highest intensity.
+ """
+ return (white << 24) | (red << 16)| (green << 8) | blue
+
+
+class _LED_Data(object):
+ """Wrapper class which makes a SWIG LED color data array look and feel like
+ a Python list of integers.
+ """
+ def __init__(self, channel, size):
+ self.size = size
+ self.channel = channel
+
+ def __getitem__(self, pos):
+ """Return the 24-bit RGB color value at the provided position or slice
+ of positions.
+ """
+ # Handle if a slice of positions are passed in by grabbing all the values
+ # and returning them in a list.
+ if isinstance(pos, slice):
+ return [ws.ws2811_led_get(self.channel, n) for n in xrange(*pos.indices(self.size))]
+ # Else assume the passed in value is a number to the position.
+ else:
+ return ws.ws2811_led_get(self.channel, pos)
+
+ def __setitem__(self, pos, value):
+ """Set the 24-bit RGB color value at the provided position or slice of
+ positions.
+ """
+ # Handle if a slice of positions are passed in by setting the appropriate
+ # LED data values to the provided values.
+ if isinstance(pos, slice):
+ index = 0
+ for n in xrange(*pos.indices(self.size)):
+ ws.ws2811_led_set(self.channel, n, value[index])
+ index += 1
+ # Else assume the passed in value is a number to the position.
+ else:
+ return ws.ws2811_led_set(self.channel, pos, value)
diff --git a/src/compileAndRun/pythonSupportFiles/entry.py b/src/compileAndRun/pythonSupportFiles/entry.py
index 4ba1031..3dab945 100644
--- a/src/compileAndRun/pythonSupportFiles/entry.py
+++ b/src/compileAndRun/pythonSupportFiles/entry.py
@@ -49,14 +49,12 @@ def main():
print ("> Loading pixel-configuration...")
with open(config_dir + "strip.json", "r") as rawStripConf:
stripConf = json.load(rawStripConf)
- segments = stripConf["segments"]
- segmentConfiguration = stripConf["segmentConfiguration"]
print ("> Initializing script...")
moduleSc = importlib.import_module("script")
if ("LuxcenaNeo" in dir(moduleSc)):
- moduleSc.LuxcenaNeo.strip = moduleSc.LuxcenaNeo.Strip(segments, segmentConfiguration)
+ moduleSc.LuxcenaNeo.strip = moduleSc.LuxcenaNeo.Strip(stripConf)
elif ("neo" in dir(moduleSc)):
moduleSc.neo.strip = moduleSc.neo.Strip(segments, segmentConfiguration)
else: