https://github.com/jgarff/rpi_ws281x
Being totally ignorant on Python, it appears that I can use Jython to drive this. Fighting through numerous pathing issues, I was able to call my own Python class from Java but for some reason I am unable to invoke the neopixel.py in the rpi_ws281x/python directory. I've got it so that it will locate the .py file, but the import atexit on line 3 fails. I believe its any import for that matter, because commenting out that one fails the next import _rpi_ws281x as ws.
I've got a really simple SpringBoot application that I've built that loads a mockNeoPixel driver that loads my own neopixle.py. This all works on my Windows pc and this class does nothing but print out some information and was my proof that I could call Python from Java. I'm also using Maven and a jython-standalone dependency, but had many issues with that and it was suggested to copy the Lib directory into my project. I've done that and put them at my src/main/resources/Lib. That seemed to resolve some issues and in fact that is where the atexit.py class is. What's odd is that in my mock neopixel.py class I have the same import atexit, although I'm not using it for anything, and that class seems to work fine. Is there a difference in where I launch that executable jar from? For example my neopixel.py is in a /home/pi/apps/python/neopixel.py directory whereas the API to drive the neopixels is in the /home/pi/rpi_ws281x/python/neopixel.py directory. The jar that I launch with java -jar hackathon.jar is in the /home/pi/apps directory.
I've also found where I need to set the path and I've done that as follows, but I still must be missing something. The code blows up on the pyton.execFile in the @PostContsruct method.
I was able to output my path using the following. The atexit is in the lib/LIB or the jar so not sure why it can't be found.
Code: Select all
import sys
print(sys.path)
Code: Select all
package com.hackathon;
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.python.core.PyInteger;
import org.python.core.PyLong;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class NeopixelDriver {
private static final Logger logger = LoggerFactory.getLogger(NeopixelDriver.class);
@Value(value = "${red}")
private String RED = "0";
@Value(value = "${green}")
private String GREEN = "0";
@Value(value = "${blue}" )
private String BLUE = "0";
@Value(value = "${sleepTime}" )
private String SLEEP_TIME;
@Value(value = "${neoscript}")
private String NEO_SCRIPT;
private static final int LED_COUNT = 30; // # Number of LED pixels.
private static final int LED_PIN = 18; // # GPIO pin connected to the pixels
// (must support PWM!).
private static final long LED_FREQ_HZ = 800000; // # LED signal frequency in
// hertz (usually 800khz)
private static final int LED_DMA = 5; // # DMA channel to use for generating
// signal (try 5)
private static final int LED_BRIGHTNESS = 200; // # Set to 0 for darkest and
// 255 for brightest
private static final String LED_INVERT = "False"; // # True to invert the
// signal (when using
// NPN transistor level
// shift)
private PythonInterpreter python;
private PyObject neoPixel;
PyObject colorClass;
private PyObject color;
@PostConstruct
public void start() {
logger.info("Starting initialization of Neopixel Driver");
// # Create NeoPixel object with appropriate configuration.
// strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA,
// LED_INVERT, LED_BRIGHTNESS)
// # Intialize the library (must be called once before other functions).
// strip.begin()
// Call ws2811_init()
Properties pyProperties = new Properties();
pyProperties.put("python.path", "./Lib:/home/pi/rpi_ws281x/python" );
pyProperties.put("python.console.encoding", "UTF-8"); // Used to prevent: console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0.
pyProperties.put("python.security.respectJavaAccessibility", "false"); //don't respect java accessibility, so that we can access protected members on subclasses
pyProperties.put("python.import.site","false");
PythonInterpreter.initialize(System.getProperties(), pyProperties, new String[0]);
python = new PythonInterpreter();
python.execfile(NEO_SCRIPT);
PyObject neoPixelClass = python.get("Adafruit_NeoPixel");
PyObject[] args = { new PyInteger(LED_COUNT),
new PyInteger(LED_PIN),
new PyLong(LED_FREQ_HZ),
new PyInteger(LED_DMA),
new PyString(LED_INVERT),
new PyInteger(LED_BRIGHTNESS) };
neoPixel = neoPixelClass.__call__(args);
logger.info("Starting up the neopixel");
// Initialize the library (must be called once before other functions).
neoPixel.invoke("begin");
colorClass = python.get("Color");
color = colorClass.__call__( new PyInteger(Integer.parseInt(RED)),
new PyInteger(Integer.parseInt(GREEN)),
new PyInteger(Integer.parseInt(BLUE)));
logger.info("Ending initialization of Neopixel Driver");
}
public void wipe() throws Exception {
// LEDs are changed by modifying the color in the .led[index] array and
// calling ws2811_render().
// Call ws2811_render()
logger.info("Wipe the neopixel");
for (int i = 0; i < LED_COUNT; i++) {
neoPixel.invoke("setPixelColor", new PyObject[] { new PyInteger(i), color } );
neoPixel.invoke("show");
Thread.sleep(Long.parseLong(SLEEP_TIME));
}
}
public void wipe( int red, int green, int blue )throws Exception {
logger.info("Wipe the neopixel");
//PyObject colorMethod = python.get("Color");
color = colorClass.__call__( new PyInteger(red),
new PyInteger(green),
new PyInteger(blue));
for (int i = 0; i < LED_COUNT; i++) {
neoPixel.invoke("setPixelColor", new PyObject[] { new PyInteger(i), color } );
neoPixel.invoke("show");
Thread.sleep(Long.parseLong(SLEEP_TIME));
}
}
}
Code: Select all
red=255
green=0
blue=0
sleepTime=100
neoscript=/home/pi/rpi_ws281x/python/neopixel.py
#neoscript=src/main/resources/neopixel.py
#Has to be outside the project and can't be in the jar.
mockneoscript=src/main/resources/python/neopixel.py
# On the Pi it needs to be the following or just pass
#--mockneoscript=python/neopixel.py
#mockneoscript=python/neopixel.py
Code: Select all
package com.hackathon;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController(value="/neo")
public class HelloNeoPixel {
private static final String MESSAGE = "Hello Neo Pixel";
@Autowired NeopixelDriver driver;
@RequestMapping
public String index() throws Exception {
driver.wipe();
return MESSAGE;
}
@RequestMapping(params={"r"} )
public String indexRed(@RequestParam("r") int red) throws Exception {
driver.wipe( red, 0, 0 );
return MESSAGE;
}
@RequestMapping(params={"g"})
public String indexGreen(@RequestParam("g") int green) throws Exception {
driver.wipe( 0, green, 0 );
return MESSAGE;
}
@RequestMapping(params={"b"})
public String indexBlue(@RequestParam("b") int blue) throws Exception {
driver.wipe( 0,0, blue );
return MESSAGE;
}
@RequestMapping(params={"r","g","b"})
public String indexColor(@RequestParam("r") int red, @RequestParam("g") int green, @RequestParam("b") int blue) throws Exception {
driver.wipe( red, green, blue );
return MESSAGE;
}
}
Code: Select all
# Adafruit NeoPixel library port to the rpi_ws281x library.
# Author: Tony DiCola ([email protected]), Jeremy Garff ([email protected])
import atexit
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 Adafruit_NeoPixel(object):
def __init__(self, num, pin, freq_hz=800000, dma=5, invert=False,
brightness=255, channel=0, strip_type='WS2811_STRIP_RGB'):
"""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 5), invert, a boolean
specifying if the signal line should be inverted (default False), and
channel, the PWM channel to use (defaults to 0).
"""
print("Number of Pixels: " + str(num))
print("Pin Number: " + str(pin))
print("Frequency: " + str(freq_hz))
print("DMA: " + str(dma))
print("Brightness: " + str(brightness))
print("Channel: " + str(channel))
def begin(self):
print("Begin the neopixel")
def show(self):
print("Show the neopixel")
def setPixelColor(self, n, color):
print("Setting neopixel " + str(n) + " to " + str(color) )
def numPixels(self):
print("Returning the number of neopixels as 30")
return 30