├── Android └── tasker │ └── LedTable.prj.xml ├── Arduino-LedTable ├── .cproject ├── .project ├── .settings │ └── it.baeyens.core.prefs ├── AdaFruitEx.cpp ├── AdaFruitEx.h ├── LedTable.cpp └── LedTable.h ├── LICENSE ├── README.md └── RPi-Java-LedTable ├── .classpath ├── .gitignore ├── .project ├── MANIFEST.MF ├── README.md ├── build.xml ├── effectAnimations ├── circle_7x7 │ ├── circle1.bmp │ ├── circle10.bmp │ ├── circle11.bmp │ ├── circle12.bmp │ ├── circle13.bmp │ ├── circle2.bmp │ ├── circle3.bmp │ ├── circle4.bmp │ ├── circle5.bmp │ ├── circle6.bmp │ ├── circle7.bmp │ ├── circle8.bmp │ └── circle9.bmp └── square_5x5 │ ├── square1.bmp │ ├── square2.bmp │ └── square3.bmp ├── lib └── pi4j │ ├── junit.jar │ ├── pi4j-core-javadoc.jar │ ├── pi4j-core-sources.jar │ ├── pi4j-core.jar │ ├── pi4j-device-javadoc.jar │ ├── pi4j-device-sources.jar │ ├── pi4j-device.jar │ ├── pi4j-example-javadoc.jar │ ├── pi4j-example-sources.jar │ ├── pi4j-example.jar │ ├── pi4j-gpio-extension-javadoc.jar │ ├── pi4j-gpio-extension-sources.jar │ ├── pi4j-gpio-extension.jar │ ├── pi4j-service-javadoc.jar │ ├── pi4j-service-sources.jar │ └── pi4j-service.jar ├── logging.properties ├── settings.txt ├── src ├── com │ └── mikelduke │ │ └── java │ │ └── util │ │ └── log │ │ └── LogUtil.java └── net │ └── mdp3 │ └── java │ ├── rpi │ └── ledtable │ │ ├── LedTable.java │ │ ├── LedTable_Selection.java │ │ ├── LedTable_Settings.java │ │ ├── LedTable_Util.java │ │ ├── effects │ │ ├── AnimationEffect.java │ │ ├── Effect.java │ │ ├── EffectFactory.java │ │ ├── EffectInfo.java │ │ ├── EffectInfoParameter.java │ │ ├── EffectMode.java │ │ ├── Effect_Util.java │ │ ├── ImageScanEffect.java │ │ ├── MidiEffect.java │ │ ├── PulseEffect.java │ │ ├── RainbowEffect.java │ │ ├── RandomFillEffect.java │ │ ├── SetColorEffect.java │ │ ├── TransparencyAnimationEffect.java │ │ └── playlist │ │ │ ├── Playlist.java │ │ │ ├── PlaylistEvent.java │ │ │ ├── PlaylistEventListener.java │ │ │ ├── PlaylistItem.java │ │ │ └── PlaylistTimer.java │ │ ├── gui │ │ ├── EffectWindow.java │ │ ├── MainWindow.java │ │ ├── PlaylistWindow.java │ │ └── TablePanel.java │ │ ├── table │ │ ├── Table.java │ │ ├── TableCMD.java │ │ ├── TableFactory.java │ │ ├── TableFile.java │ │ ├── TableSPI.java │ │ ├── TableSerial.java │ │ └── WriteListener.java │ │ └── webservice │ │ ├── WebserviceCommands.java │ │ ├── WebserviceFunctions.java │ │ └── WebserviceHandler.java │ └── util │ ├── console │ ├── ConsoleArgumentHandler.java │ ├── ConsoleBatch.java │ ├── ConsoleReader.java │ └── ConsoleUtil.java │ ├── file │ ├── FileNameFormatter.java │ └── SimpleFileIO.java │ ├── gui │ └── MenuBarHelper.java │ ├── misc │ ├── MapUtil.java │ └── ObjectNotInitializedException.java │ ├── settings │ ├── CmdLineProperties.java │ ├── Settings.java │ └── SettingsLoader.java │ ├── string │ └── StringUtils.java │ ├── test │ ├── BatchTest.java │ ├── BatchTest.txt │ ├── ConsoleArgumentHandlerTest.java │ ├── SettingsSaveTest.java │ ├── SettingsTest.java │ ├── SettingsTest.txt │ ├── SimpleFileIOTest.java │ ├── Util_Test.java │ └── WebserviceTest.java │ ├── webservice │ ├── WSResponse.java │ ├── Webservice.java │ ├── WebserviceBase.java │ ├── WebserviceClient.java │ ├── WebserviceConstants.java │ ├── WebserviceListener.java │ └── WebserviceUtil.java │ └── xml │ ├── DomXml.java │ └── XmlHelper.java ├── testAnimation ├── 001.bmp ├── 002.bmp ├── 003.bmp └── 004.bmp ├── testAnimation2 ├── ChristmasTree.bmp └── HOHOHO.bmp ├── testImages ├── ChristmasTree.bmp ├── HI.bmp ├── HOHOHO.bmp ├── test.bmp ├── testScale1.bmp └── test_vert.bmp └── www ├── LedTable.html └── LedTable.js /Arduino-LedTable/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | LedTable 4 | 5 | 6 | Arduino_Uno 7 | 8 | 9 | 10 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 11 | clean,full,incremental, 12 | 13 | 14 | 15 | 16 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 17 | full,incremental, 18 | 19 | 20 | 21 | 22 | 23 | org.eclipse.cdt.core.cnature 24 | org.eclipse.cdt.core.ccnature 25 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 26 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 27 | it.baeyens.arduinonature 28 | 29 | 30 | 31 | Adafruit_WS2801 32 | 2 33 | PivateLibPath/Adafruit_WS2801 34 | 35 | 36 | SPI 37 | 2 38 | ArduinoLibPath/SPI 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Arduino-LedTable/.settings/it.baeyens.core.prefs: -------------------------------------------------------------------------------- 1 | avrtarget/ClockFrequency=16000000 2 | avrtarget/ExtRAMSize=0 3 | avrtarget/ExtendedRAM=false 4 | avrtarget/MCUType=atmega328p 5 | avrtarget/UseEEPROM=false 6 | avrtarget/UseExtendedRAMforHeap=true 7 | avrtarget/avrdude/BitBangDelay= 8 | avrtarget/avrdude/Bitclock= 9 | avrtarget/avrdude/EEPROMFile= 10 | avrtarget/avrdude/EEPROMFromConfig=true 11 | avrtarget/avrdude/FlashFile= 12 | avrtarget/avrdude/FlashFromConfig=true 13 | avrtarget/avrdude/NoChipErase=false 14 | avrtarget/avrdude/NoSigCheck=false 15 | avrtarget/avrdude/NoVerify=false 16 | avrtarget/avrdude/NoWrite=false 17 | avrtarget/avrdude/OtherOptions= 18 | avrtarget/avrdude/ProgrammerID=programmerconfig.9 19 | avrtarget/avrdude/UseCounter=false 20 | avrtarget/avrdude/WriteEEPROM=false 21 | avrtarget/avrdude/WriteFlash=true 22 | eclipse.preferences.version=1 23 | -------------------------------------------------------------------------------- /Arduino-LedTable/AdaFruitEx.cpp: -------------------------------------------------------------------------------- 1 | #include "SPI.h" 2 | #include "Adafruit_WS2801.h" 3 | #include "AdaFruitEx.h" 4 | #include "LedTable.h" 5 | 6 | /**************************************************************************** 7 | * This File has been modified from the original example code that comes with 8 | * the AdaFruit WS2801 Library. The two examples gridtest and strandtest have 9 | * been combined into one library, with the necessary header file for eclipse. 10 | * Some other minor modifications have been made, such as including the strip 11 | * variable as a parameter in several of the functions in order to make it 12 | * work correctly. 13 | * 14 | * The original Header/Liscense is included below. 15 | * 16 | * Modified by Mikel Duke http://www.mikelduke.com 17 | * 18 | * https://github.com/adafruit/Adafruit-WS2801-Library 19 | *****************************************************************************/ 20 | 21 | /***************************************************************************** 22 | Example sketch for driving Adafruit WS2801 pixels! 23 | 24 | 25 | Designed specifically to work with the Adafruit RGB Pixels! 26 | 12mm Bullet shape ----> https://www.adafruit.com/products/322 27 | 12mm Flat shape ----> https://www.adafruit.com/products/738 28 | 36mm Square shape ----> https://www.adafruit.com/products/683 29 | 30 | These pixels use SPI to transmit the color data, and have built in 31 | high speed PWM drivers for 24 bit color per pixel 32 | 2 pins are required to interface 33 | 34 | Adafruit invests time and resources providing this open source code, 35 | please support Adafruit and open-source hardware by purchasing 36 | products from Adafruit! 37 | 38 | Written by David Kavanagh (dkavanagh@gmail.com). 39 | BSD license, all text above must be included in any redistribution 40 | 41 | *****************************************************************************/ 42 | /* 43 | // Choose which 2 pins you will use for output. 44 | // Can be any valid output pins. 45 | // The colors of the wires may be totally different so 46 | // BE SURE TO CHECK YOUR PIXELS TO SEE WHICH WIRES TO USE! 47 | uint8_t dataPin = 2; // Yellow wire on Adafruit Pixels 48 | uint8_t clockPin = 3; // Green wire on Adafruit Pixels 49 | 50 | // Don't forget to connect the ground wire to Arduino ground, 51 | // and the +5V wire to a +5V supply 52 | 53 | // Set the first variable to the NUMBER of pixels in a row and 54 | // the second value to number of pixels in a column. 55 | //Adafruit_WS2801 strip = Adafruit_WS2801((uint16_t)12, (uint16_t)8, dataPin, clockPin); 56 | */ 57 | 58 | void drawX(uint8_t w, uint8_t h, uint8_t wait, Adafruit_WS2801 strip) { 59 | uint16_t x, y; 60 | for (x=0; x 0) return; 103 | 104 | delay(wait); 105 | strip.setPixelColor(x, y, 0, 0, 0); 106 | } 107 | } 108 | 109 | void rainbow(uint8_t wait, Adafruit_WS2801 strip) { 110 | uint8_t i, j; 111 | 112 | for (j=0; j < 256; j++) { // 3 cycles of all 256 colors in the wheel 113 | for (i=0; i < strip.numPixels(); i++) { 114 | strip.setPixelColor(i, Wheel( (i + j) % 255)); 115 | } 116 | strip.show(); // write all the pixels out 117 | 118 | //Added to quickly break the loop when serial data comes in 119 | if (Serial.available() > 0) return; 120 | 121 | delay(wait); 122 | } 123 | } 124 | 125 | // Slightly different, this one makes the rainbow wheel equally distributed 126 | // along the chain 127 | void rainbowCycle(uint8_t wait, Adafruit_WS2801 strip) { 128 | uint8_t i, j; 129 | 130 | for (j=0; j < 256 * 5; j++) { // 5 cycles of all 25 colors in the wheel 131 | for (i=0; i < strip.numPixels(); i++) { 132 | // tricky math! we use each pixel as a fraction of the full 96-color wheel 133 | // (thats the i / strip.numPixels() part) 134 | // Then add in j which makes the colors go around per pixel 135 | // the % 96 is to make the wheel cycle around 136 | strip.setPixelColor(i, Wheel( ((i * 256 / strip.numPixels()) + j) % 256) ); 137 | 138 | //Added to quickly break the loop when serial data comes in 139 | if (Serial.available() > 0) return; 140 | } 141 | strip.show(); // write all the pixels out 142 | delay(wait); 143 | } 144 | } 145 | 146 | // fill the dots one after the other with said color 147 | // good for testing purposes 148 | void colorWipe(uint32_t c, uint8_t wait, Adafruit_WS2801 strip) { 149 | uint8_t i; 150 | 151 | for (i=0; i < strip.numPixels(); i++) { 152 | strip.setPixelColor(i, c); 153 | strip.show(); 154 | 155 | //Added to quickly break the loop when serial data comes in 156 | if (Serial.available() > 0) return; 157 | 158 | delay(wait); 159 | } 160 | } 161 | 162 | /* Helper functions */ 163 | 164 | // Create a 24 bit color value from R,G,B 165 | uint32_t Color(byte r, byte g, byte b) 166 | { 167 | uint32_t c; 168 | c = r; 169 | c <<= 8; 170 | c |= g; 171 | c <<= 8; 172 | c |= b; 173 | return c; 174 | } 175 | 176 | //Input a value 0 to 255 to get a color value. 177 | //The colours are a transition r - g -b - back to r 178 | uint32_t Wheel(byte WheelPos) 179 | { 180 | if (WheelPos < 85) { 181 | return Color(WheelPos * 3, 255 - WheelPos * 3, 0); 182 | } else if (WheelPos < 170) { 183 | WheelPos -= 85; 184 | return Color(255 - WheelPos * 3, 0, WheelPos * 3); 185 | } else { 186 | WheelPos -= 170; 187 | return Color(0, WheelPos * 3, 255 - WheelPos * 3); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Arduino-LedTable/AdaFruitEx.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * AdaFruitEx.h 3 | * 4 | * Created on: Jul 15, 2013 5 | * Author: Mikel 6 | * 7 | * Header file created to use the Adafruit WS2801 library and examples in 8 | * eclipse 9 | * 10 | * http://www.mikelduke.com 11 | * 12 | * https://github.com/adafruit/Adafruit-WS2801-Library 13 | * 14 | *****************************************************************************/ 15 | 16 | #ifndef ADAFRUITEX_H_ 17 | #define ADAFRUITEX_H_ 18 | 19 | uint32_t Color(byte r, byte g, byte b); 20 | uint32_t Wheel(byte WheelPos); 21 | 22 | void rainbow(uint8_t wait, Adafruit_WS2801 strip); 23 | void rainbowCycle(uint8_t wait, Adafruit_WS2801 strip); 24 | void colorWipe(uint32_t c, uint8_t wait, Adafruit_WS2801 strip); 25 | 26 | void drawX(uint8_t w, uint8_t h, uint8_t wait, Adafruit_WS2801 strip); 27 | void bounce(uint8_t w, uint8_t h, uint8_t wait, Adafruit_WS2801 strip); 28 | 29 | 30 | #endif /* ADAFRUITEX_H_ */ 31 | -------------------------------------------------------------------------------- /Arduino-LedTable/LedTable.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * LedTable.cpp 3 | * 4 | * Created on: Jul 14, 2013 5 | * Author: Mikel 6 | * 7 | * http://www.mikelduke.com 8 | * 9 | * Main program for use in the LedTable coffee table project based on an 8x12 array 10 | * of WS2801 RGB leds on a string. 11 | * 12 | * This program runs on an Arduino Uno using 50pc WS2801 based RGB LEDS similar to 13 | * these http://www.adafruit.com/products/322 14 | * 15 | * This program requires the use of the Adafruit WS2801 Arduino Library available 16 | * here https://github.com/adafruit/Adafruit-WS2801-Library 17 | * 18 | * The code compiled in Eclipse when set up for Arduino following these instructions 19 | * http://www.baeyens.it/eclipse/ and maybe using the Arduino IDE if renamed to .ino 20 | * but this is untested and changes are probably needed. 21 | * 22 | * Demo 1: https://www.youtube.com/watch?v=T2C9mu11J88 23 | * Demo 2: https://www.youtube.com/watch?v=4fyQAG1ji9Y 24 | * Demo 3: https://www.youtube.com/watch?v=qthHU0W8SG4 25 | * 26 | *****************************************************************************/ 27 | 28 | #include "SPI.h" 29 | #include "Adafruit_WS2801.h" 30 | #include "LedTable.h" 31 | #include "AdafruitEx.h" 32 | 33 | #define TIMEOUT 2000 34 | 35 | uint8_t dataPin = 2; // Yellow wire on Adafruit Pixels 36 | uint8_t clockPin = 3; // Green wire on Adafruit Pixels 37 | 38 | int arrayX = 12; 39 | int arrayY = 8; 40 | int numLeds = arrayX * arrayY; 41 | 42 | enum States { STOPPED, DEMO, PULSE1, PULSE2, SERIAL_READ, SET_COLOR, PULSE_RANDOM, WAITING}; 43 | int state = DEMO; 44 | String statusStr = "init"; 45 | 46 | Adafruit_WS2801 strip = Adafruit_WS2801((uint16_t)arrayX, (uint16_t)arrayY, dataPin, clockPin); 47 | 48 | void setup() { 49 | randomSeed(analogRead(0)); 50 | Serial.begin(57600); 51 | Serial.println("Led Table"); 52 | 53 | strip.begin(); 54 | strip.show(); 55 | } 56 | 57 | void loop() { 58 | if (Serial.available() > 0) { 59 | char c; 60 | c = Serial.read(); 61 | //Serial.print("Received: "); 62 | //Serial.println(c); 63 | handleRead(c); 64 | } 65 | 66 | if (state == STOPPED) { 67 | statusStr = "Stopped"; 68 | setTableColor(0, 0, 0); 69 | } 70 | else if (state == DEMO) runDemos(0); 71 | else if (state == PULSE1) tablePulse(1); 72 | else if (state == PULSE2) tablePulse2(5); 73 | else if (state == SERIAL_READ) readLedArray(); 74 | else if (state == PULSE_RANDOM) randomColorPulse(1); 75 | else if (state == WAITING) delay(5); 76 | //strip.show(); 77 | } 78 | 79 | void handleRead(char c) { 80 | if (c == 'X') { 81 | sendStatus(); 82 | } 83 | else if (c == '0') { 84 | state = STOPPED; 85 | dumpSerial(); 86 | } 87 | else if (c == '1') { 88 | state = DEMO; 89 | dumpSerial(); 90 | } 91 | else if (c == '2') { 92 | state = PULSE1; 93 | dumpSerial(); 94 | } 95 | else if (c == '3') { 96 | state = PULSE2; 97 | readLedTableColor(); 98 | dumpSerial(); 99 | } 100 | else if (c == '4') { 101 | state = SERIAL_READ; 102 | //readLedArray(); 103 | //dumpSerial(); 104 | } 105 | else if (c == '5') { 106 | state = SET_COLOR; 107 | dumpSerial(); 108 | } 109 | else if (c == '6') { 110 | state = PULSE_RANDOM; 111 | dumpSerial(); 112 | } 113 | //else dumpSerial(); 114 | } 115 | 116 | void runDemos(uint8_t wait) { 117 | statusStr = "Running AdaFruit Demos"; 118 | runGridDemos(wait); 119 | runStrandDemos(wait); 120 | } 121 | 122 | void runGridDemos(uint8_t wait) { 123 | //Serial.println("Running AdaFruit Grid Demos"); 124 | drawX(12, 8, 100, strip); 125 | bounce(12, 8, 50, strip); 126 | } 127 | 128 | void runStrandDemos(uint8_t wait) { 129 | //Serial.println("Running Adafruit Strip Demos"); 130 | colorWipe(Color(255, 0, 0), wait, strip); 131 | colorWipe(Color(0, 255, 0), wait, strip); 132 | colorWipe(Color(0, 0, 255), wait, strip); 133 | rainbow(wait, strip); 134 | rainbowCycle(wait, strip); 135 | } 136 | 137 | void tablePulse(int inc) { 138 | statusStr = "Running Table Pulses"; 139 | for (byte i = 0; i < 255; i += inc) { 140 | setTableColor(i, 0, 0); 141 | 142 | //Added to quickly break the loop when serial data comes in 143 | if (Serial.available() > 0) return; 144 | } 145 | for (byte i = 0; i < 255; i += inc) { 146 | setTableColor(0, i, 0); 147 | 148 | //Added to quickly break the loop when serial data comes in 149 | if (Serial.available() > 0) return; 150 | } 151 | for (byte i = 0; i < 255; i += inc) { 152 | setTableColor(0, 0, i); 153 | 154 | //Added to quickly break the loop when serial data comes in 155 | if (Serial.available() > 0) return; 156 | } 157 | //Added to quickly break the loop when serial data comes in 158 | if (Serial.available() > 0) return; 159 | } 160 | 161 | void setTableColor(byte r, byte g, byte b) { 162 | for (int x = 0; x < arrayX; x++) { 163 | for (int y = 0; y < arrayY; y++) { 164 | strip.setPixelColor(x, y, r, g, b); 165 | } 166 | } 167 | strip.show(); 168 | } 169 | 170 | void dumpSerial() { 171 | while (Serial.available() > 0) { 172 | byte b; 173 | b = Serial.read(); 174 | } 175 | } 176 | 177 | void sendStatus() { 178 | Serial.print("Status: "); 179 | Serial.println(statusStr); 180 | } 181 | 182 | void readLedTableColor() { 183 | int r = 0; 184 | int g = 0; 185 | int b = 0; 186 | 187 | r = Serial.parseInt(); 188 | g = Serial.parseInt(); 189 | b = Serial.parseInt(); 190 | 191 | setTableColor(r, g, b); 192 | } 193 | 194 | //Serial buffer is only 64b! 195 | void readLedArray() { 196 | int ledsRead = 0; 197 | int delayTime = 0; 198 | while (ledsRead < numLeds) { 199 | while (Serial.available() < 3) { 200 | delay(5); 201 | delayTime += 5; 202 | if (delayTime > TIMEOUT) { 203 | state = STOPPED; 204 | return; 205 | } 206 | } 207 | char r = Serial.read(); 208 | char g = Serial.read(); 209 | char b = Serial.read(); 210 | strip.setPixelColor(ledsRead, r, g, b); 211 | ledsRead++; 212 | } 213 | strip.show(); 214 | state = WAITING; 215 | } 216 | 217 | void tablePulse2(int inc) { 218 | //statusStr = "Running Table Pulses"; 219 | for (int i = 20; i <= 255; i += inc) { 220 | setTableColor((byte)i, 0, 0); 221 | //if (Serial.available() > 0) return; 222 | } 223 | for (int i = 255; i >= 20; i -= inc) { 224 | setTableColor((byte)i, 0, 0); 225 | //if (Serial.available() > 0) return; 226 | } 227 | for (int i = 20; i <= 255; i += inc) { 228 | setTableColor(0, (byte)i, 0); 229 | //if (Serial.available() > 0) return; 230 | } 231 | for (int i = 255; i >= 20; i -= inc) { 232 | setTableColor(0, (byte)i, 0); 233 | //if (Serial.available() > 0) return; 234 | } 235 | for (int i = 20; i <= 255; i += inc) { 236 | setTableColor(0, 0, (byte)i); 237 | //if (Serial.available() > 0) return; 238 | } 239 | for (int i = 255; i >= 20; i -= inc) { 240 | setTableColor(0, 0, (byte)i); 241 | //if (Serial.available() > 0) return; 242 | } 243 | //Added to quickly break the loop when serial data comes in 244 | if (Serial.available() > 0) return; 245 | } 246 | 247 | void randomColorPulse(int inc) { 248 | byte oldR = strip.pixels[0]; 249 | byte oldG = strip.pixels[1]; 250 | byte oldB = strip.pixels[2]; 251 | 252 | byte newR = random(255); 253 | byte newG = random(255); 254 | byte newB = random(255); 255 | 256 | while ((newR > oldR + inc/2) || (newR < oldR - inc/2)) { 257 | if (oldR < newR) { 258 | oldR += inc; 259 | } 260 | else if (oldR > newR) { 261 | oldR -= inc; 262 | } 263 | setTableColor(oldR, oldG, oldB); 264 | if (Serial.available() > 0) return; 265 | } 266 | while ((newG > oldG + inc/2) || (newG < oldG - inc/2)) { 267 | if (oldG < newG) { 268 | oldG += inc; 269 | } 270 | else if (oldG > newG) { 271 | oldG -= inc; 272 | } 273 | setTableColor(oldR, oldG, oldB); 274 | if (Serial.available() > 0) return; 275 | } 276 | while ((newB > oldB + inc/2) || (newB < oldB - inc/2)) { 277 | if (oldB < newB) { 278 | oldB += inc; 279 | } 280 | else if (oldB > newB) { 281 | oldB -= inc; 282 | } 283 | setTableColor(oldR, oldG, oldB); 284 | if (Serial.available() > 0) return; 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /Arduino-LedTable/LedTable.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * LedTable.h 3 | * 4 | * Created on: Jul 14, 2013 5 | * Author: Mikel 6 | * 7 | * http://www.mikelduke.com 8 | * 9 | * This program runs on an Arduino Uno using 50pc WS2801 based RGB LEDS similar to 10 | * these http://www.adafruit.com/products/322 11 | * 12 | * This program requires the use of the Adafruit WS2801 Arduino Library available 13 | * here https://github.com/adafruit/Adafruit-WS2801-Library 14 | * 15 | * The code compiled in Eclipse when set up for Arduino following these instructions 16 | * http://www.baeyens.it/eclipse/ and maybe using the Arduino IDE if renamed to .ino 17 | * but this is untested and changes are probably needed. 18 | * 19 | *****************************************************************************/ 20 | 21 | // Only modify this file to include 22 | // - function definitions (prototypes) 23 | // - include files 24 | // - extern variable definitions 25 | // In the appropriate section 26 | 27 | #ifndef LedTable_H_ 28 | #define LedTable_H_ 29 | #include "Arduino.h" 30 | //add your includes for the project LedTable here 31 | 32 | 33 | //end of add your includes here 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | void loop(); 38 | void setup(); 39 | #ifdef __cplusplus 40 | } // extern "C" 41 | #endif 42 | 43 | //constructors for functions that run a demo of adafruit examples 44 | void runDemos(uint8_t wait); 45 | void runGridDemos(uint8_t wait); 46 | void runStrandDemos(uint8_t wait); 47 | 48 | void tablePulse(int inc); 49 | void tablePulse2(int inc); 50 | void randomColorPulse(int inc); 51 | void setTableColor(byte r, byte g, byte b); 52 | 53 | void handleRead(char c); 54 | void dumpSerial(); 55 | 56 | void sendStatus(); 57 | void readLedTableColor(); 58 | void readLedArray(); 59 | 60 | //Do not add code below this line 61 | #endif /* LedTable_H_ */ 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LedTable 2 | ======== 3 | 4 | http://www.mikelduke.com 5 | 6 | Code for my LedTable, an 8x12 rgb led string based table using WS2801 chips and 7 | controlled by and Arduino using a RPi for internet connectivity and higher level 8 | functionality. 9 | 10 | The Arduino code requires the Adafruit WS2801 Library and contains modifications 11 | to the included example code to combine the examples for use as a header file. 12 | 13 | https://github.com/adafruit/Adafruit-WS2801-Library 14 | 15 | This program runs on an Arduino Uno using 50pc WS2801 based RGB LEDS similar to 16 | these http://www.adafruit.com/products/322 17 | 18 | The code compiles in Eclipse when set up for Arduino following these instructions 19 | http://www.baeyens.it/eclipse/ and might compile using the Arduino IDE if renamed 20 | to .ino but this is untested and changes are probably needed. 21 | 22 | Demo 1: https://www.youtube.com/watch?v=T2C9mu11J88 23 | Demo 2: https://www.youtube.com/watch?v=4fyQAG1ji9Y 24 | Demo 3: https://www.youtube.com/watch?v=qthHU0W8SG4 25 | 26 | 27 | ======== 28 | The Java app for the Raspberry pi to control the Arduino requires the Pi4J library. 29 | 30 | http://pi4j.com/ 31 | 32 | The Raspberry Pi connects to the Arduino via the USB port. This is the simplest 33 | connection type available. The app requires Java which is included in newer 34 | Raspbian releases and must be run with sudo. 35 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | 3 | build/ 4 | dist/ 5 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | LedTable 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.wst.common.project.facet.core.builder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.jdt.core.javanature 26 | org.eclipse.wst.common.project.facet.core.nature 27 | org.eclipse.wst.jsdt.core.jsNature 28 | 29 | 30 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Ant-Version: Apache Ant 1.10.1 3 | Created-By: 9.0.4+11 (Oracle Corporation) 4 | Built-By: mikel 5 | Main-Class: net.mdp3.java.rpi.ledtable.LedTable 6 | Class-Path: ./lib/pi4j/junit.jar ./lib/pi4j/pi4j-core-javadoc.jar 7 | ./lib/pi4j/pi4j-core-sources.jar ./lib/pi4j/pi4j-core.jar 8 | ./lib/pi4j/pi4j-device-javadoc.jar ./lib/pi4j/pi4j-device-source 9 | s.jar ./lib/pi4j/pi4j-device.jar ./lib/pi4j/pi4j-example-java 10 | doc.jar ./lib/pi4j/pi4j-example-sources.jar ./lib/pi4j/pi4j-e 11 | xample.jar ./lib/pi4j/pi4j-gpio-extension-javadoc.jar ./lib/p 12 | i4j/pi4j-gpio-extension-sources.jar ./lib/pi4j/pi4j-gpio-extensio 13 | n.jar ./lib/pi4j/pi4j-service-javadoc.jar ./lib/pi4j/pi4j-ser 14 | vice-sources.jar ./lib/pi4j/pi4j-service.jar 15 | 16 | Name: common 17 | Specification-Title: LedTable 18 | Specification-Version: 0.2.1 19 | Specification-Vendor: mdp3.net 20 | Implementation-Title: Java LedTable Controller 21 | Implementation-Version: 0.2.1 February 20 2018 22 | Implementation-Vendor: mdp3.net 23 | 24 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/README.md: -------------------------------------------------------------------------------- 1 | LedTable 2 | ======== 3 | 4 | http://www.mikelduke.com 5 | 6 | Code for my LedTable, an 8x12 rgb led string based table using WS2801 chips and 7 | controlled by and Arduino using a RPi for internet connectivity and higher level 8 | functionality. 9 | 10 | The Arduino code requires the Adafruit WS2801 Library and contains modifications 11 | to the included example code to combine the examples for use as a header file. 12 | 13 | https://github.com/adafruit/Adafruit-WS2801-Library 14 | 15 | This program runs on an Arduino Uno using 50pc WS2801 based RGB LEDS similar to 16 | these http://www.adafruit.com/products/322 17 | 18 | The code compiles in Eclipse when set up for Arduino following these instructions 19 | http://www.baeyens.it/eclipse/ and might compile using the Arduino IDE if renamed 20 | to .ino but this is untested and changes are probably needed. 21 | 22 | Demo 1: https://www.youtube.com/watch?v=T2C9mu11J88 23 | Demo 2: https://www.youtube.com/watch?v=4fyQAG1ji9Y 24 | Demo 3: https://www.youtube.com/watch?v=qthHU0W8SG4 25 | 26 | 27 | ======== 28 | The Java app for the Raspberry pi to control the Arduino requires the Pi4J library. 29 | 30 | http://pi4j.com/ 31 | 32 | The Raspberry Pi connects to the Arduino via the USB port. This is the simplest 33 | connection type available. The app requires Java which is included in newer 34 | Raspbian releases and must be run with sudo. 35 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Build file for LedTable 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
-------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle1.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle10.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle10.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle11.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle11.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle12.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle12.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle13.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle13.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle2.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle3.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle4.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle5.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle5.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle6.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle6.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle7.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle7.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle8.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle8.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/circle_7x7/circle9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/circle_7x7/circle9.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/square_5x5/square1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/square_5x5/square1.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/square_5x5/square2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/square_5x5/square2.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/effectAnimations/square_5x5/square3.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/effectAnimations/square_5x5/square3.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/junit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/junit.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-core-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-core-javadoc.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-core-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-core-sources.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-core.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-device-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-device-javadoc.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-device-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-device-sources.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-device.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-device.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-example-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-example-javadoc.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-example-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-example-sources.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-example.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-example.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension-javadoc.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension-sources.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-gpio-extension.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-service-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-service-javadoc.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-service-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-service-sources.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/lib/pi4j/pi4j-service.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/lib/pi4j/pi4j-service.jar -------------------------------------------------------------------------------- /RPi-Java-LedTable/logging.properties: -------------------------------------------------------------------------------- 1 | # Properties file which configures the operation of the JDK 2 | # logging facility. 3 | 4 | # The system will look for this config file, first using 5 | # a System property specified at startup: 6 | # 7 | # >java -Djava.util.logging.config.file=myLoggingConfigFilePath 8 | # 9 | # If this property is not specified, then the config file is 10 | # retrieved from its default location at: 11 | # 12 | # JDK_HOME/jre/lib/logging.properties 13 | 14 | # Global logging properties. 15 | # ------------------------------------------ 16 | # The set of handlers to be loaded upon startup. 17 | # Comma-separated list of class names. 18 | # (? LogManager docs say no comma here, but JDK example has comma.) 19 | handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler 20 | 21 | # Default global logging level. 22 | # Loggers and Handlers may override this level 23 | .level=INFO 24 | 25 | # Loggers 26 | # ------------------------------------------ 27 | # Loggers are usually attached to packages. 28 | # Here, the level for each package is specified. 29 | # The global level is used by default, so levels 30 | # specified here simply act as an override. 31 | net.mdp3.java.rpi.ledtable.level=INFO 32 | #net.mdp3.java.jams.level=ALL 33 | #net.mdp3.java.jams.midi.level=FINEST 34 | 35 | # Handlers 36 | # ----------------------------------------- 37 | 38 | # --- ConsoleHandler --- 39 | # Override of global logging level 40 | java.util.logging.ConsoleHandler.level=INFO 41 | java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 42 | 43 | # --- FileHandler --- 44 | # Override of global logging level 45 | java.util.logging.FileHandler.level=INFO 46 | 47 | # Naming style for the output file: 48 | # (The output file is placed in the directory 49 | # defined by the "user.home" System property.) 50 | #java.util.logging.FileHandler.pattern=%h/java%u.log 51 | java.util.logging.FileHandler.pattern=ledTable%u.log 52 | 53 | # Limiting size of output file in bytes: 54 | java.util.logging.FileHandler.limit=50000 55 | 56 | # Number of output files to cycle through, by appending an 57 | # integer to the base file name: 58 | java.util.logging.FileHandler.count=1 59 | 60 | # Style of output (Simple or XML): 61 | java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter 62 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/settings.txt: -------------------------------------------------------------------------------- 1 | #LedTable Settings 2 | 3 | #Debug Mode 4 | debug: true 5 | 6 | #Test GUI Settings 7 | enableGUI: true 8 | guiW: 520 9 | guiH: 366 10 | flipY: true 11 | 12 | #Webservice Settings 13 | wsName: /ledtable 14 | wsPort: 85 15 | 16 | #Remote Webservice Connection Settings 17 | remoteWS: false 18 | remoteWSURL: http://ip:85/ledtable 19 | 20 | #Output Settings 21 | enableTableOutput: false 22 | tableMode: SPI 23 | 24 | #Serial Settings 25 | serialPort: /dev/ttyACM0 26 | serialBaud: 57600 27 | 28 | #SPI Settings 29 | spiSpeed: 1953000 30 | 31 | #File Output Settings 32 | outputFile: /dev/spidev0.0 33 | 34 | #LedTable Settings 35 | ledY: 8 36 | ledX: 12 37 | snakedLeds: true 38 | 39 | #Midi Settings 40 | midiUpdateDelay: 100 41 | 42 | #File Save Settings 43 | defaultSaveFolder: C:/mdp3/projects/LedTable/java/saves 44 | defaultFilePrefix: LedTable 45 | 46 | #Auto load and play settings 47 | autoplaySelection: false 48 | defaultSelectionFile: C:/mdp3/projects/LedTable/java/saves/selections/LedTable-20150930183017.xml 49 | 50 | autoplayPlaylist: true 51 | defaultPlaylistFile: C:/mdp3/projects/LedTable/java/saves/playlists/LedTable-20151022150223.xml 52 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/com/mikelduke/java/util/log/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.mikelduke.java.util.log; 2 | 3 | import java.util.Map; 4 | import java.util.logging.Level; 5 | import java.util.logging.Logger; 6 | 7 | public class LogUtil { 8 | private static final String CLAZZ = LogUtil.class.getName(); 9 | private static final Logger LOGGER = Logger.getLogger(CLAZZ); 10 | 11 | public static void logMap(Level level, String clazz, String msg, Map map) { 12 | StringBuilder sb = new StringBuilder(); 13 | 14 | if (level == null) { 15 | level = Level.FINEST; 16 | } 17 | 18 | if (clazz == null || clazz.isEmpty()) { 19 | clazz = CLAZZ; 20 | } 21 | 22 | if (msg == null || msg.isEmpty()) { 23 | msg = "Map Values"; 24 | } 25 | 26 | if (map == null) { 27 | sb.append("Map is null"); 28 | } 29 | 30 | if (map.isEmpty()) { 31 | sb.append("Map is empty"); 32 | } 33 | 34 | for (K key : map.keySet()) { 35 | sb.append(key + ": " + map.get(key)); 36 | sb.append("\n"); 37 | } 38 | 39 | LOGGER.logp(level, clazz, "logMap", msg + ": " + sb.toString()); 40 | } 41 | 42 | public static void logMap(Level level, String clazz, Map map) { 43 | logMap(level, clazz, "", map); 44 | } 45 | 46 | public static void logMap(Level level, Map map) { 47 | logMap(level, CLAZZ, "", map); 48 | } 49 | 50 | public static void logMap(Map map) { 51 | logMap(Level.FINEST, CLAZZ, "Map", map); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/LedTable_Settings.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable; 2 | 3 | import java.util.logging.Logger; 4 | 5 | import net.mdp3.java.util.settings.SettingsLoader; 6 | 7 | /** 8 | * 9 | * @author Mikel 10 | * 11 | * Class of static variables to hold the global settings 12 | * Has database, serial port, and table info 13 | */ 14 | 15 | public class LedTable_Settings { 16 | private final static Logger LOG = Logger.getLogger(LedTable_Settings.class.getName()); 17 | private final static String name = "LedTable_Settings"; 18 | 19 | //Default settings if not overwritten in settings.txt 20 | public static boolean enableGUI = true; 21 | public static int guiW = 504; 22 | public static int guiH = 336; 23 | public static boolean flipY = true; 24 | 25 | public static String wsName = "/ledtable"; 26 | public static int wsPort = 85; 27 | 28 | public static boolean enableTableOutput = false; 29 | public static String tableMode = "SPI"; 30 | public static String serialPort = "/dev/ttyACM0"; 31 | public static int serialBaud = 57600; 32 | 33 | public static int spiSpeed = 1953000; 34 | 35 | public static String outputFile = "/dev/spidev0.0"; 36 | 37 | public static int ledY = 8; 38 | public static int ledX = 12; 39 | public static boolean snakedLeds = true; 40 | 41 | public static boolean debug = true; 42 | 43 | public static long midiUpdateDelay = 100; 44 | 45 | public static String defaultSaveFolder = ""; 46 | public static String defaultFilePrefix = "LedTable"; 47 | 48 | public static boolean remoteWS = false; 49 | public static String remoteWSURL = ""; 50 | 51 | public static boolean autoplaySelection = false; 52 | public static String defaultSelectionFile = ""; 53 | 54 | public static boolean autoplayPlaylist = false; 55 | public static String defaultPlaylistFile = ""; 56 | 57 | /** 58 | * Loads the settings to the static variables using the mdp3_Util 59 | * Settings methods 60 | * 61 | * Currently hardcoded to use filename of settings.txt 62 | */ 63 | public static void loadSettings() { 64 | loadSettings("settings.txt"); 65 | } 66 | 67 | /** 68 | * Loads the settings to the static variables using the mdp3_Util 69 | * Settings methods 70 | * 71 | * @param fileName 72 | */ 73 | public static void loadSettings(String fileName) { 74 | LOG.entering(name, "loadSettings", "Filename: " + fileName); 75 | 76 | SettingsLoader set = new SettingsLoader(LedTable_Settings.class, false); 77 | 78 | //URL url = SettingsTest.class.getResource("SettingsTest.txt"); 79 | //File file = new File(url.getPath()); 80 | set.loadSettings(fileName); 81 | 82 | checkSettings(); 83 | 84 | LOG.exiting(name, "loadSettings"); 85 | } 86 | 87 | /** 88 | * Method to run to bounds check variables after being loaded from file 89 | */ 90 | public static void checkSettings() { 91 | //Check bounds, must have atleast 1 row of each 92 | if (ledX < 1) { 93 | LOG.warning("Error in settings: ledX < 1; changing value to ledX = 1"); 94 | ledX = 1; 95 | } 96 | 97 | if (ledY < 1) { 98 | LOG.warning("Error in settings: ledY < 1; changing value to ledY = 1"); 99 | ledY = 1; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/AnimationEffect.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.effects; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 7 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 8 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 9 | import net.mdp3.java.rpi.ledtable.table.Table; 10 | 11 | public class AnimationEffect extends Effect { 12 | private final static String name = "AnimationEffect"; 13 | 14 | protected File[] fileList; 15 | 16 | protected byte[][] imageAr; 17 | 18 | protected boolean fade = false; 19 | protected int numOfFrames = 10; 20 | protected int fadeDelay = 10; 21 | 22 | public AnimationEffect(Table t, LedTable_Selection s) { 23 | super(t, s); 24 | 25 | if(s.getParams().get("fade") != null) this.fade = Boolean.parseBoolean(s.getParams().get("fade")); 26 | if(s.getParams().get("numOfFrames") != null) this.numOfFrames = Integer.parseInt(s.getParams().get("numOfFrames")); 27 | if(s.getParams().get("fadeDelay") != null) this.fadeDelay = Integer.parseInt(s.getParams().get("fadeDelay")); 28 | 29 | String f = selection.getParams().get("folder"); 30 | File folder; 31 | if (f != null && f != "") { 32 | folder = new File(f); 33 | fileList = folder.listFiles(); 34 | loadImages(); 35 | } 36 | } 37 | 38 | public void effectsLoop() { 39 | for (int i = 0; i < fileList.length; i++) { 40 | if (run) { //checked again so that when the mode changes, the thread can quit on the next frame 41 | if (i < imageAr.length) { 42 | if (!this.fade) 43 | table.write(imageAr[i]); 44 | else { 45 | try { 46 | Effect_Util.fade(this, table, imageAr[i], numOfFrames, fadeDelay); 47 | table.write(imageAr[i]); 48 | } catch (InterruptedException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | delay(); 54 | } 55 | } 56 | } 57 | 58 | public long getRuntime() { 59 | return this.delay * fileList.length; 60 | } 61 | 62 | protected byte[] loadImage(String imgPath) { 63 | LOG.entering(name, "loadImage", imgPath); 64 | 65 | byte tableAr[] = null; 66 | try { 67 | tableAr = LedTable_Util.loadImage(imgPath).clone(); 68 | } 69 | catch (IOException ioe) { 70 | LOG.info("Error opening file: " + ioe); 71 | ioe.printStackTrace(); 72 | } 73 | 74 | LOG.exiting(name, "loadImage", tableAr); 75 | return tableAr; 76 | } 77 | 78 | protected void loadImages() { 79 | LOG.entering(name, "loadImages"); 80 | 81 | imageAr = new byte[fileList.length][]; 82 | 83 | for (int i = 0; i < fileList.length; i++) { 84 | imageAr[i] = loadImage(fileList[i].getAbsolutePath()); 85 | } 86 | 87 | LOG.exiting(name, "loadImages"); 88 | } 89 | 90 | @Override 91 | public EffectInfo setEffectInfo() { 92 | EffectInfoParameter[] paramInfo = { 93 | new EffectInfoParameter("fade", "Toggle Fading between Images", EffectInfoParameterType.BOOL), 94 | new EffectInfoParameter("numOfFrames", "Number of Frames to fade", EffectInfoParameterType.INT, 1, 1000), 95 | new EffectInfoParameter("fadeDelay", "Time between each fade frame", EffectInfoParameterType.INT, 1, 20000), 96 | new EffectInfoParameter("folder", "Folder to select images from", EffectInfoParameterType.FOLDER) 97 | }; 98 | EffectInfo ei = new EffectInfo("AnimationEffect", "Can show images in a folder", paramInfo); 99 | 100 | return ei; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/Effect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.awt.Color; 7 | import java.util.Random; 8 | import java.util.logging.Logger; 9 | 10 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 11 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 12 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 13 | import net.mdp3.java.rpi.ledtable.table.Table; 14 | 15 | /** 16 | * Effect class is abstract class meant to be extended to add new complex 17 | * threaded effects to the Led Table. It sets up the main thread and gets 18 | * called from LedTable.java to start the effect loop without hanging the 19 | * main app. 20 | * 21 | * When adding a new effect, a new mode entry should be added to 22 | * LedTable_Selection.Mode with the class name if one is needed. This will 23 | * allow the class to be loaded via Reflection in LedTable.newSelection 24 | * without having to constantly update a big switch statement. 25 | * 26 | * @author Mikel 27 | * 28 | */ 29 | public abstract class Effect extends Thread { 30 | protected final static Logger LOG = Logger.getLogger(Effect.class.getName()); 31 | private final static String name = "Effect"; 32 | 33 | protected Table table = null; 34 | protected LedTable_Selection selection; 35 | protected Color[][] tableC = LedTable_Util.getTableColor(); 36 | 37 | protected boolean run = false; 38 | protected long delay = 100; 39 | protected int minDelay = 1; 40 | protected int maxDelay = 1000; 41 | 42 | protected EffectInfo effectInfo; 43 | 44 | protected Random rnd = new Random(); 45 | 46 | public Effect(Table t, LedTable_Selection s) { 47 | LOG.entering(name, "new"); 48 | 49 | this.effectInfo = setEffectInfo(); 50 | if (this.effectInfo == null) { 51 | LOG.warning("No Effect Info Set!"); 52 | this.effectInfo = new EffectInfo("Unknown Effect", "Not Set", null); 53 | } 54 | 55 | //Common Parameters for all effects 56 | this.effectInfo.getParamInfo().add(0, new EffectInfoParameter("delay", "Main delay amount", EffectInfoParameterType.INT, this.minDelay, this.maxDelay)); 57 | 58 | this.table = t; 59 | setMode(s); 60 | 61 | this.setPriority(Thread.MAX_PRIORITY); 62 | 63 | LOG.exiting(name, "new"); 64 | } 65 | 66 | public Effect() { 67 | this.setPriority(Thread.MAX_PRIORITY); 68 | } 69 | 70 | public void setTable(Table t) { 71 | this.table = t; 72 | } 73 | 74 | public void setMode(LedTable_Selection s) { 75 | this.selection = s; 76 | 77 | if (s.getParams().get("delay") != null) 78 | this.setDelay(Long.parseLong(s.getParams().get("delay"))); 79 | } 80 | 81 | public LedTable_Selection getSelection() { 82 | return this.selection; 83 | } 84 | 85 | public boolean isRunning() { 86 | return run; 87 | } 88 | 89 | public void setDelay(long t) { 90 | delay = t; 91 | } 92 | 93 | public long getDelay() { 94 | return delay; 95 | } 96 | 97 | public void stopEffect() { 98 | run = false; 99 | } 100 | 101 | protected void delay() { 102 | try { 103 | Thread.sleep(this.delay); 104 | } catch (InterruptedException e) { 105 | e.printStackTrace(); 106 | } 107 | } 108 | 109 | public final void run() { 110 | run = true; 111 | 112 | while (run) { 113 | effectsLoop(); 114 | } 115 | } 116 | 117 | /** 118 | * Main loop for the effect 119 | * 120 | * Must check variable run if looping inside of this loop to see if it 121 | * needs to be broke out of 122 | * 123 | * Should call delay in between loops 124 | */ 125 | public abstract void effectsLoop(); 126 | 127 | /** 128 | * Method to be implemented by subclasses. This will store data about the 129 | * effect, name, desc, parameters, etc. 130 | * 131 | * @Example Implementation: 132 | * 133 | * public EffectInfo setEffectInfo() { 134 | * EffectInfoParameter[] paramInfo = { 135 | * new EffectInfoParameter("fade", "Toggle Fading between Images", "bool"), 136 | * new EffectInfoParameter("numOfFrames", "Number of Frames to fade", "int", 1, 1000), 137 | * new EffectInfoParameter("fadeDelay", "Time between each fade frame", "int", 1, 20000) 138 | * }; 139 | * EffectInfo ei = new EffectInfo("AnimationEffect", "Can show images in a folder", paramInfo); 140 | * 141 | * return ei; 142 | * } 143 | * 144 | * @return EffectInfo for the subclass 145 | */ 146 | public abstract EffectInfo setEffectInfo(); 147 | 148 | public EffectInfo getEffectInfo() { 149 | return this.effectInfo; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/EffectFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.lang.reflect.Constructor; 7 | import java.util.logging.Logger; 8 | 9 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 10 | import net.mdp3.java.rpi.ledtable.table.Table; 11 | 12 | /** 13 | * @author Mikel 14 | * 15 | */ 16 | public class EffectFactory { 17 | private final static Logger LOG = Logger.getLogger(EffectFactory.class.getName()); 18 | private final static String name = "EffectFactory"; 19 | 20 | public static Effect getEffect(EffectMode mode, Table table, LedTable_Selection s) throws Exception { 21 | LOG.entering(name, "getEffect", "mode: " + mode); 22 | 23 | Effect effect = null; 24 | 25 | if (mode.getEffectClass() != null) { 26 | LOG.fine("Loading Class with reflection " + mode); 27 | Class clazz = mode.getEffectClass(); 28 | Constructor c = clazz.getConstructor(Table.class, LedTable_Selection.class); 29 | effect = c.newInstance(table, s); 30 | } else { 31 | LOG.warning("Warning: Possible Invalid Mode " + mode + ": Effect Class Not Set"); 32 | } 33 | 34 | LOG.exiting(name, "getEffect", "Effect: " + effect); 35 | 36 | return effect; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/EffectInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | 9 | import net.mdp3.java.util.xml.DomXml; 10 | import net.mdp3.java.util.xml.XmlHelper; 11 | 12 | import org.w3c.dom.Document; 13 | import org.w3c.dom.Element; 14 | 15 | /** 16 | * Data Container for Effect Info and parameter info 17 | * 18 | * @author Mikel 19 | * 20 | */ 21 | public class EffectInfo implements DomXml { 22 | private String effectName; 23 | private String effectDesc; 24 | 25 | private ArrayList paramInfo = new ArrayList(); 26 | 27 | public static final String NODE_NAME = "EffectInfo"; 28 | public static final String NODE_EFFECT_NAME = "EffectName"; 29 | public static final String NODE_EFFECT_DESC = "EffectDesc"; 30 | 31 | public EffectInfo(String name, String desc, EffectInfoParameter[] paramInfo) { 32 | this.setEffectName(name); 33 | this.setEffectDesc(desc); 34 | this.setParamInfo(paramInfo); 35 | } 36 | 37 | public EffectInfoParameter[] getParamInfoAr() { 38 | return (EffectInfoParameter[]) paramInfo.toArray(); 39 | } 40 | 41 | public ArrayList getParamInfo() { 42 | return this.paramInfo; 43 | } 44 | 45 | public void setParamInfo(EffectInfoParameter[] paramInfo) { 46 | if (paramInfo != null && paramInfo.length > 0) 47 | this.paramInfo.addAll(Arrays.asList(paramInfo)); 48 | } 49 | 50 | public void setParamInfo(ArrayList paramInfoList) { 51 | if (paramInfoList != null) 52 | this.paramInfo = paramInfoList; 53 | } 54 | 55 | public void addParameterInfo(EffectInfoParameter newParam) { 56 | this.paramInfo.add(newParam); 57 | } 58 | 59 | public String getEffectDesc() { 60 | return effectDesc; 61 | } 62 | 63 | public void setEffectDesc(String effectDesc) { 64 | this.effectDesc = effectDesc; 65 | } 66 | 67 | public String getEffectName() { 68 | return effectName; 69 | } 70 | 71 | public void setEffectName(String effectName) { 72 | this.effectName = effectName; 73 | } 74 | 75 | public String toString() { 76 | String ret = ""; 77 | 78 | ret += "Name: " + this.getEffectName(); 79 | ret += "\nDesc: " + this.getEffectDesc(); 80 | 81 | if (this.paramInfo.size() > 0) { 82 | ret += "\n\nParameter Info: \n"; 83 | 84 | for (EffectInfoParameter eip : this.paramInfo) { 85 | ret += "\n" + eip.toString(); 86 | } 87 | } 88 | 89 | return ret; 90 | } 91 | 92 | @Override 93 | public Element toXml(Document doc) { 94 | Element effectInfoE = doc.createElement(EffectInfo.NODE_NAME); 95 | 96 | effectInfoE.appendChild(XmlHelper.newTextElement(doc, EffectInfo.NODE_EFFECT_NAME, this.effectName)); 97 | effectInfoE.appendChild(XmlHelper.newTextElement(doc, EffectInfo.NODE_EFFECT_DESC, this.effectDesc)); 98 | 99 | Element eipListE = doc.createElement(EffectInfoParameter.NODE_NAME + "List"); 100 | 101 | for (EffectInfoParameter eip : this.getParamInfo()) 102 | eipListE.appendChild(eip.toXml(doc)); 103 | 104 | effectInfoE.appendChild(eipListE); 105 | 106 | return effectInfoE; 107 | } 108 | 109 | @Override 110 | public void fromXml(Element e) throws Exception { 111 | //Not Used 112 | throw new Exception("Effect Info fromXml not implemented"); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/EffectInfoParameter.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.effects; 2 | 3 | import net.mdp3.java.util.xml.DomXml; 4 | import net.mdp3.java.util.xml.XmlHelper; 5 | 6 | import org.w3c.dom.Document; 7 | import org.w3c.dom.Element; 8 | 9 | /** 10 | * Data container for Effect Parameter Info 11 | * 12 | * @author Mikel 13 | * 14 | */ 15 | public class EffectInfoParameter implements DomXml { 16 | private String paramName; 17 | private String paramDesc; 18 | private EffectInfoParameterType paramDataType; 19 | private String[] paramValues; 20 | 21 | private int minValue = 0; 22 | private int maxValue = 0; 23 | 24 | public static final String NODE_NAME = "EffectInfoParameter"; 25 | public static final String NODE_EIP_NAME = "Name"; 26 | public static final String NODE_EIP_DESC = "Desc"; 27 | public static final String NODE_EIP_DATATYPE = "DataType"; 28 | public static final String NODE_EIP_MIN = "MinValue"; 29 | public static final String NODE_EIP_MAX = "MaxValue"; 30 | public static final String NODE_EIP_VALUE = "Value"; //TODO Implement taking an array of values 31 | 32 | public static enum EffectInfoParameterType { 33 | INT, 34 | BOOL, 35 | STRING, 36 | SELECT, //probably be used for most string eips, switches to use String Array 37 | FOLDER, 38 | FILE 39 | } 40 | 41 | //TODO Add taking in values list for String types 42 | public EffectInfoParameter(String name, String desc, EffectInfoParameterType dataType) { 43 | this(name, desc, dataType, 0, 0); 44 | } 45 | 46 | public EffectInfoParameter(String name, String desc, String[] valuesAr) { 47 | this(name, desc, EffectInfoParameterType.SELECT, 0, 0); 48 | this.setValues(valuesAr); 49 | } 50 | 51 | public EffectInfoParameter(String name, String desc, EffectInfoParameterType dataType, int min, int max) { 52 | this.setParamName(name); 53 | this.setParamDesc(desc); 54 | this.setParamDataType(dataType); 55 | this.setMinValue(min); 56 | this.setMaxValue(max); 57 | } 58 | 59 | public void setValues(String[] values) { 60 | this.paramValues = values; 61 | } 62 | 63 | public String[] getValues() { 64 | return this.paramValues; 65 | } 66 | 67 | public int getMaxValue() { 68 | return maxValue; 69 | } 70 | 71 | public void setMaxValue(int maxValue) { 72 | this.maxValue = maxValue; 73 | } 74 | 75 | public int getMinValue() { 76 | return minValue; 77 | } 78 | 79 | public void setMinValue(int minValue) { 80 | this.minValue = minValue; 81 | } 82 | 83 | public EffectInfoParameterType getParamDataType() { 84 | return paramDataType; 85 | } 86 | 87 | public void setParamDataType(EffectInfoParameterType paramDataType) { 88 | this.paramDataType = paramDataType; 89 | } 90 | 91 | public String getParamDesc() { 92 | return paramDesc; 93 | } 94 | 95 | public void setParamDesc(String paramDesc) { 96 | this.paramDesc = paramDesc; 97 | } 98 | 99 | public String getParamName() { 100 | return paramName; 101 | } 102 | 103 | public void setParamName(String paramName) { 104 | this.paramName = paramName; 105 | } 106 | 107 | public String toString() { 108 | String ret = ""; 109 | 110 | ret += "Name: " + this.getParamName(); 111 | ret += "\nDesc: " + this.getParamDesc(); 112 | ret += "\nData Type: " + this.getParamDataType(); 113 | 114 | if (this.getMinValue() != 0 || this.getMaxValue() != 0) { 115 | ret += "\nMin Value: " + this.getMinValue(); 116 | ret += "\nMax Value: " + this.getMaxValue(); 117 | } 118 | 119 | return ret; 120 | } 121 | 122 | @Override 123 | public Element toXml(Document doc) { 124 | Element eipE = doc.createElement(EffectInfoParameter.NODE_NAME); 125 | 126 | eipE.appendChild(XmlHelper.newTextElement(doc, EffectInfoParameter.NODE_EIP_NAME, this.paramName)); 127 | eipE.appendChild(XmlHelper.newTextElement(doc, EffectInfoParameter.NODE_EIP_DESC, this.paramDesc)); 128 | eipE.appendChild(XmlHelper.newTextElement(doc, EffectInfoParameter.NODE_EIP_DATATYPE, this.paramDataType.toString())); 129 | 130 | if (this.minValue != 0 || this.maxValue != 0) { 131 | eipE.appendChild(XmlHelper.newTextElement(doc, EffectInfoParameter.NODE_EIP_MIN, this.minValue)); 132 | eipE.appendChild(XmlHelper.newTextElement(doc, EffectInfoParameter.NODE_EIP_MAX, this.maxValue)); 133 | } else { 134 | if (this.paramValues != null && this.paramValues.length > 0) { 135 | Element eipValuesListE = doc.createElement(EffectInfoParameter.NODE_EIP_VALUE + "List"); 136 | 137 | for (String value : this.paramValues) { 138 | eipValuesListE.appendChild(XmlHelper.newTextElement(doc, NODE_EIP_VALUE, value)); 139 | } 140 | 141 | eipE.appendChild(eipValuesListE); 142 | } 143 | } 144 | 145 | return eipE; 146 | } 147 | 148 | @Override 149 | public void fromXml(Element e) throws Exception { 150 | //Not Used 151 | throw new Exception("fromXml for EffectInfoParameter is not used"); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/EffectMode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import net.mdp3.java.util.xml.DomXml; 7 | import net.mdp3.java.util.xml.XmlHelper; 8 | 9 | import org.w3c.dom.Document; 10 | import org.w3c.dom.Element; 11 | 12 | /** 13 | * @author Mikel 14 | * 15 | */ 16 | public enum EffectMode implements DomXml { 17 | OFF( "Off"), 18 | PULSE1(PulseEffect.class, "Pulse Effect"), 19 | //PULSE2(PulseEffect.class, "Pulse 2 Not Available"), 20 | RAW, 21 | SET_COLOR(SetColorEffect.class, "Set Color"), 22 | //PULSE_RANDOM(PulseEffect.class), 23 | IMAGE( "Set Image"),//TODO Create Set Image Effect 24 | ANIMATION(AnimationEffect.class, "Animate"), 25 | //MIDI(MidiEffect.class, "Midi Reactive Effect (NA)"), 26 | RAINBOW(RainbowEffect.class, "Rainbow Colors"), 27 | IMAGE_SCAN(ImageScanEffect.class, "Image Scan"), 28 | //ANIM_TRANS(TransparencyAnimationEffect.class, "Image with Transparency"), 29 | RANDOM_FILL(RandomFillEffect.class, "Random Fill"); 30 | 31 | public static final String NODE_NAME = "EffectMode"; 32 | public static final String NODE_MODE_NAME = "ModeName"; 33 | public static final String NODE_MODE_DESC = "ModeDescName"; 34 | public static final String NODE_MODE_CLASS = "ModeClass"; 35 | 36 | Class effectClass; 37 | String name = ""; 38 | 39 | private EffectMode() { 40 | this(null, ""); 41 | } 42 | 43 | private EffectMode(String name) { 44 | this(null, name); 45 | } 46 | 47 | private EffectMode(Class effectClass) { 48 | this(effectClass, ""); 49 | } 50 | 51 | private EffectMode(Class effectClass, String name) { 52 | this.effectClass = effectClass; 53 | this.name = name; 54 | } 55 | 56 | public Class getEffectClass() { 57 | return this.effectClass; 58 | } 59 | 60 | public String getDescName() { 61 | //if (this.name != null && this.name.length() > 0) 62 | return this.name; 63 | //else return this.name(); 64 | } 65 | 66 | @Override 67 | public Element toXml(Document doc) { 68 | Element effectModeE = doc.createElement(EffectMode.NODE_NAME); 69 | 70 | effectModeE.appendChild(XmlHelper.newTextElement(doc, EffectMode.NODE_MODE_NAME, this.name())); 71 | if (this.getDescName() != null) 72 | effectModeE.appendChild(XmlHelper.newTextElement(doc, EffectMode.NODE_MODE_DESC, this.getDescName())); 73 | if (this.getEffectClass() != null) 74 | effectModeE.appendChild(XmlHelper.newTextElement(doc, EffectMode.NODE_MODE_CLASS, this.getEffectClass().getName())); 75 | 76 | return effectModeE; 77 | } 78 | 79 | @Override 80 | public void fromXml(Element e) throws Exception { 81 | //Not implemented 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/Effect_Util.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.awt.Color; 7 | import java.io.IOException; 8 | import java.lang.reflect.Field; 9 | import java.util.Arrays; 10 | import java.util.logging.Logger; 11 | 12 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 13 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 14 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 15 | import net.mdp3.java.rpi.ledtable.table.Table; 16 | import net.mdp3.java.util.string.StringUtils; 17 | 18 | /** 19 | * @author Mikel 20 | * 21 | */ 22 | public class Effect_Util { 23 | private final static Logger LOG = Logger.getLogger(Effect_Util.class.getName()); 24 | private final static String NAME = "Effect_Util"; 25 | 26 | /** 27 | * Uses the current tableAr in LedTable_Util and fades it towards the finishAr 28 | * 29 | * @param e Reference to the Effect that object that is calling Fade, used to check if it is still running to break out of the loop. Can be null 30 | * @param t LedTable to output to 31 | * @param finishAr byte array to fade to 32 | * @param numOfFrames number of frames to fade over 33 | * @param delay time between each frame 34 | * @throws InterruptedException 35 | */ 36 | public static void fade(Effect e, Table t, byte[] finishAr, int numOfFrames, int delay) throws InterruptedException { 37 | LOG.entering(NAME, "fade"); 38 | 39 | if (numOfFrames < 1) return; 40 | if (delay < 1) return; 41 | 42 | byte[] lastWrite = Arrays.copyOf(t.getLastWrite(), t.getLastWrite().length); 43 | if (lastWrite == null) { 44 | LOG.warning("Last Write not Initialized"); 45 | return; 46 | } 47 | 48 | if (finishAr.length != lastWrite.length) { 49 | LOG.severe("Invalid Array Lengths"); 50 | return; 51 | } 52 | 53 | for (int i = 0; i < numOfFrames; i++) { 54 | //Simple change of every byte in the array by frame/numberofframes amount 55 | for (int j = 0; j < lastWrite.length; j++) { 56 | int diff = (int)(lastWrite[j] & 0xFF) - (int)(finishAr[j] & 0xFF); 57 | diff /= numOfFrames; 58 | lastWrite[j] -= diff; 59 | } 60 | 61 | t.write(lastWrite); 62 | 63 | if (e == null || e.isRunning()) { 64 | Thread.sleep(delay); 65 | } else { 66 | return; 67 | } 68 | } 69 | 70 | LOG.exiting(NAME, "fade"); 71 | } 72 | 73 | /** 74 | * Changes the table to the specified color 75 | * 76 | * @param table 77 | * @param s 78 | * @throws Exception 79 | */ 80 | public static void colorSelection(Table table, LedTable_Selection s) throws Exception { 81 | boolean colorsSet = false; 82 | 83 | byte r = 0; 84 | byte g = 0; 85 | byte b = 0; 86 | 87 | if (s.getParams().get("color") != null && s.getParams().get("color") != "") { 88 | String colorStr = s.getParams().get("color"); 89 | final Field f = Color.class.getField(colorStr); 90 | Color color = (Color) f.get(null); 91 | 92 | if (color != null) { 93 | r = (byte)color.getRed(); 94 | g = (byte)color.getGreen(); 95 | b = (byte)color.getBlue(); 96 | 97 | colorsSet = true; 98 | } 99 | } else if (s.getParams().get("r") != null && s.getParams().get("r") != "" && 100 | s.getParams().get("g") != null && s.getParams().get("g") != "" && 101 | s.getParams().get("b") != null && s.getParams().get("b") != "") { 102 | 103 | int iR = StringUtils.tryParseInt(s.getParams().get("r")); 104 | int iG = StringUtils.tryParseInt(s.getParams().get("g")); 105 | int iB = StringUtils.tryParseInt(s.getParams().get("b")); 106 | 107 | r = (byte) iR; 108 | g = (byte) iG; 109 | b = (byte) iB; 110 | 111 | colorsSet = true; 112 | } else throw new Exception("Invalid Color Selection for Mode"); 113 | 114 | if (colorsSet) { 115 | table.write(LedTable_Util.getRGBArray(r, g, b)); 116 | } 117 | } 118 | 119 | public static void showImage(Table table, LedTable_Selection s) { 120 | int x = 0; 121 | int y = 0; 122 | boolean scaleToFit = false; 123 | 124 | if (s.getParams().get("x") != null) x = Integer.parseInt(s.getParams().get("x")); 125 | if (s.getParams().get("y") != null) y = Integer.parseInt(s.getParams().get("y")); 126 | if (s.getParams().get("scale") != null) scaleToFit = Boolean.parseBoolean(s.getParams().get("scale")); 127 | 128 | String img = s.getParams().get("img"); 129 | if (img == null || img == "") return; 130 | 131 | try { 132 | if (scaleToFit) 133 | table.write(LedTable_Util.loadImage(img, x, y, LedTable_Settings.ledX, LedTable_Settings.ledY)); 134 | else 135 | table.write(LedTable_Util.loadImage(img, x, y)); 136 | } catch (IOException e) { 137 | LOG.warning("Error load image: " + img + " x: " + x + " y: " + y); 138 | e.printStackTrace(); 139 | } 140 | } 141 | 142 | /** 143 | * Returns a Color object created from the parameters for Selection 144 | * 145 | * @param s 146 | * @return 147 | * @throws Exception 148 | */ 149 | protected static Color loadColor(LedTable_Selection s) throws Exception { 150 | int r = 0; 151 | int g = 0; 152 | int b = 0; 153 | 154 | if (s.getParams().get("color") != null && s.getParams().get("color") != "") { 155 | String colorStr = s.getParams().get("color"); 156 | final Field f = Color.class.getField(colorStr); 157 | Color color = (Color) f.get(null); 158 | 159 | if (color != null) { 160 | r = color.getRed(); 161 | g = color.getGreen(); 162 | b = color.getBlue(); 163 | } 164 | } else if (s.getParams().get("r") != null && s.getParams().get("r") != "" && 165 | s.getParams().get("g") != null && s.getParams().get("g") != "" && 166 | s.getParams().get("b") != null && s.getParams().get("b") != "") { 167 | 168 | r = StringUtils.tryParseInt(s.getParams().get("r")); 169 | g = StringUtils.tryParseInt(s.getParams().get("g")); 170 | b = StringUtils.tryParseInt(s.getParams().get("b")); 171 | } else throw new Exception("Invalid Color Selection"); 172 | 173 | Color c = new Color(r, g, b); 174 | return c; 175 | } 176 | 177 | protected static void drawSquare(Color[][] colorAr, int startX, int startY, int w, int h, Color color, boolean fill) { 178 | if (startX < 0) return; 179 | if (startY < 0) return; 180 | if (colorAr.length < 1) return; 181 | if (startX >= colorAr[0].length) return; 182 | if (startY >= colorAr.length) return; 183 | if (w <= 0) return; 184 | if (h <= 0) return; 185 | 186 | int stopX = startX + w; 187 | int stopY = startY + h; 188 | 189 | for (int y = startY; y <= stopY; y++) { 190 | for (int x = startX; x <= stopX; x++) { 191 | if (fill) { 192 | colorAr[y][x] = color; 193 | } else { 194 | if (x == startX || y == startY || x == stopX || y == stopY) { 195 | colorAr[y][x] = color; 196 | } 197 | } 198 | } 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/ImageScanEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.io.IOException; 7 | import java.util.Random; 8 | 9 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 10 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 11 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 12 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 13 | import net.mdp3.java.rpi.ledtable.table.Table; 14 | 15 | /** 16 | * @author Mikel 17 | * 18 | */ 19 | public class ImageScanEffect extends Effect { 20 | private final static String name = "ImageScanEffect"; 21 | 22 | private Random rnd = new Random(); 23 | 24 | private String imgPath = ""; 25 | private boolean imageLoaded = false; 26 | private int inc = 1; 27 | private int x = 0; 28 | private int y = 0; 29 | 30 | public ImageScanEffect(Table t, LedTable_Selection s) { 31 | super(t, s); 32 | 33 | if (s.getParams().get("img") != null) this.imgPath = s.getParams().get("img"); 34 | if (s.getParams().get("inc") != null) this.inc = Integer.parseInt(s.getParams().get("inc")); 35 | if (inc < 1) inc = 1; 36 | 37 | if (imgPath != "") { 38 | try { 39 | LedTable_Util.loadImage(imgPath); 40 | imageLoaded = true; 41 | } catch (IOException e) { 42 | LOG.warning("Error loading Image: " + imgPath); 43 | e.printStackTrace(); 44 | } 45 | } 46 | } 47 | 48 | @Override 49 | public EffectInfo setEffectInfo() { 50 | EffectInfoParameter[] paramInfo = { 51 | new EffectInfoParameter("img", "Path to Image File", EffectInfoParameterType.FILE), 52 | new EffectInfoParameter("inc", "Number of pixels to move by", EffectInfoParameterType.INT, 1, 100) 53 | }; 54 | EffectInfo ei = new EffectInfo("ImageScanEffect", 55 | "Randomly moves around a portion of a larger image", paramInfo); 56 | 57 | return ei; 58 | } 59 | 60 | @Override 61 | public void effectsLoop() { 62 | this.scan(); 63 | } 64 | 65 | private void scan() { 66 | LOG.entering(name, "scan"); 67 | 68 | if (imageLoaded && run) { 69 | try { 70 | getNextCoords(); 71 | 72 | LOG.finer("Displaying Image at x:" + x + ", y:" + y); 73 | table.write(LedTable_Util.getImagePart(this.x, this.y)); 74 | 75 | delay(); 76 | } catch (IOException e) { 77 | LOG.warning("Error Displaying Image part image: " + this.imgPath + " x:"+ this.x + ", y:" + this.y); 78 | e.printStackTrace(); 79 | } 80 | } 81 | 82 | LOG.exiting(name, "scan"); 83 | } 84 | 85 | private void getNextCoords() { 86 | LOG.entering(name, "getNextCoords"); 87 | LOG.finer("Old Coords x:" + this.x + ", y:" + this.y + " inc: " + this.inc); 88 | 89 | int dirX = rnd.nextInt(3); 90 | int dirY = rnd.nextInt(3); 91 | 92 | switch (dirX) { 93 | case 0: this.x += this.inc; 94 | break; 95 | case 1: break; 96 | case 2: this.x -= this.inc; 97 | break; 98 | } 99 | 100 | switch (dirY) { 101 | case 0: this.y += this.inc; 102 | break; 103 | case 1: break; 104 | case 2: this.y -= this.inc; 105 | break; 106 | } 107 | 108 | //bounds check 109 | if (x < 0) x = 0; 110 | if (y < 0) y = 0; 111 | if (x > LedTable_Util.getImage().getWidth() - LedTable_Settings.ledX) x = LedTable_Util.getImage().getWidth() - LedTable_Settings.ledX; 112 | if (y > LedTable_Util.getImage().getHeight() - LedTable_Settings.ledY) y = LedTable_Util.getImage().getHeight() - LedTable_Settings.ledY; 113 | 114 | LOG.finer("New Coords x:" + this.x + ", y:" + this.y + " inc: " + this.inc); 115 | LOG.exiting(name, "getNextCoords"); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/MidiEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.util.LinkedList; 7 | import java.util.Random; 8 | 9 | import javax.sound.midi.MidiDevice; 10 | import javax.sound.midi.MidiMessage; 11 | import javax.sound.midi.MidiSystem; 12 | import javax.sound.midi.MidiUnavailableException; 13 | import javax.sound.midi.Receiver; 14 | import javax.sound.midi.ShortMessage; 15 | import javax.sound.midi.Transmitter; 16 | 17 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 18 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 19 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 20 | import net.mdp3.java.rpi.ledtable.table.Table; 21 | 22 | /** 23 | * @author Mikel 24 | * 25 | */ 26 | public class MidiEffect extends Effect implements Receiver { 27 | 28 | private LinkedList openDevices = new LinkedList(); 29 | private LinkedList transmitters = new LinkedList(); 30 | 31 | private int mode = 1; 32 | private final int NOTE = 144; //0x90 33 | 34 | Random rand = new Random(); 35 | private boolean devicesLoaded = false; 36 | 37 | public MidiEffect(Table t, LedTable_Selection s) { 38 | super(t, s); 39 | } 40 | 41 | @Override 42 | public EffectInfo setEffectInfo() { 43 | EffectInfoParameter[] paramInfo = { 44 | //TODO add parameter info 45 | }; 46 | EffectInfo ei = new EffectInfo("MidiEffect", 47 | "Listens to midi info and does stuff", paramInfo); 48 | 49 | return ei; 50 | } 51 | 52 | public void effectsLoop() { 53 | if (!devicesLoaded) { 54 | loadInputDevices(); 55 | } 56 | updateTable(); 57 | 58 | if (run) { 59 | delay(); 60 | } else { //extra check to close inputs cleanly 61 | close(); 62 | } 63 | } 64 | 65 | public void setMode(int m) { 66 | this.mode = m; 67 | } 68 | 69 | public void stopEffect() { 70 | LOG.finer("Stopping Midi Thread!"); 71 | if (run) { 72 | run = false; 73 | close(); 74 | } 75 | } 76 | 77 | private boolean loadInputDevices() { 78 | MidiDevice device = null; 79 | MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); 80 | boolean deviceLoaded = false; 81 | 82 | for (int i = 0; i < infos.length; i++) { 83 | System.out.println(i + ": " + infos[i].getName()); 84 | try { 85 | device = MidiSystem.getMidiDevice(infos[i]); 86 | System.out.println(" " + i + " class: " + device.getClass().getName()); 87 | System.out.println(" " + i + " receivers: " + device.getMaxReceivers()); 88 | System.out.println(" " + i + " transmitters: " + device.getMaxTransmitters()); 89 | 90 | if (device.getClass().getName().equalsIgnoreCase("com.sun.media.sound.MidiInDevice")) { 91 | System.out.println("MIDI In Found!"); 92 | if (!device.isOpen() && device.getMaxTransmitters() != 0) { 93 | device.open(); 94 | openDevices.addLast(device); 95 | 96 | Transmitter t = device.getTransmitter(); 97 | transmitters.addLast(t); 98 | t.setReceiver(this); 99 | 100 | deviceLoaded = true; 101 | } 102 | } 103 | device = null; 104 | } 105 | catch (MidiUnavailableException e) { 106 | System.out.println("Error loading device " + i + " " + e); 107 | } 108 | } 109 | 110 | this.devicesLoaded = deviceLoaded; 111 | return deviceLoaded; 112 | } 113 | 114 | @Override 115 | public void close() { 116 | for (int i = 0; i < transmitters.size(); i++) 117 | transmitters.get(i).close(); 118 | for (int i = 0; i < openDevices.size(); i++) 119 | openDevices.get(i).close(); 120 | run = false; 121 | } 122 | 123 | @Override 124 | public void send(MidiMessage arg0, long arg1) { 125 | ShortMessage message = new LedTable_ShortMessage(arg0.getMessage()); 126 | 127 | if (LedTable_Settings.debug) 128 | System.out.println("MIDIMessage [Channel: " + message.getChannel() 129 | + ", Command: " + message.getCommand() + ", Data1: " + message.getData1() 130 | + ", Data2: " + message.getData2() + ']'); 131 | 132 | if (mode == 1) handleMidi(message.getCommand(), message.getData1(), message.getData2()); 133 | } 134 | 135 | /** 136 | * handleMidi 137 | * 138 | * Midi Handler to switch modes 139 | * 140 | * @param cmd Midi Command 141 | * @param data1 Midi Data 1 (Typically Note) 142 | * @param data2 Midi Data 2 (Typically Velocity) 143 | */ 144 | private void handleMidi(int cmd, int data1, int data2) { 145 | if (mode == 1) handleMidiMode1(cmd, data1, data2); 146 | } 147 | 148 | /** 149 | * handleMidiMode1 150 | * 151 | * Mode 1 for Midi Input, Controls how the table initially reacts to Midi Input 152 | * 153 | * @param cmd 154 | * @param data1 155 | * @param data2 156 | */ 157 | private void handleMidiMode1(int cmd, int data1, int data2) { 158 | if (cmd == NOTE) { 159 | int scaleNote = data1 % 12; 160 | LedTable_Util.getTableAr()[0][scaleNote * 3] = (byte) rand.nextInt(255); //data2 * 2; //R 161 | LedTable_Util.getTableAr()[0][scaleNote * 3 + 1] = (byte) rand.nextInt(255); //data2 * 2; //G 162 | LedTable_Util.getTableAr()[0][scaleNote * 3 + 2] = (byte) rand.nextInt(255); //data2 * 2; //B 163 | } 164 | } 165 | 166 | /** 167 | * updateTable 168 | * 169 | * Function called from the Run method when thread is running, this 170 | * method calls different table utility update methods based on the mode. 171 | * This allows the table leds to change when there is no midi input. 172 | */ 173 | private void updateTable() { 174 | if (mode == 1) { 175 | //TODO implement this 176 | } 177 | } 178 | 179 | /** 180 | * LedTable_ShortMessage 181 | * @author Mikel 182 | * 183 | * Simple class extended from javax.sound.midi.ShortMessage to be able 184 | * to use the protected new ShortMessage(byte[]) method. 185 | */ 186 | private class LedTable_ShortMessage extends ShortMessage { 187 | public LedTable_ShortMessage(byte[] bAr) { 188 | super(bAr); 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/PulseEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 7 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 8 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 9 | import net.mdp3.java.rpi.ledtable.table.Table; 10 | import net.mdp3.java.util.string.StringUtils; 11 | 12 | /** 13 | * @author Mikel 14 | * 15 | */ 16 | public class PulseEffect extends Effect { 17 | private final static String name = "PulseEffect"; 18 | 19 | private int pulseInc = 1; 20 | private PulseType pulseType = PulseType.RGB; 21 | 22 | private int oldR = 0; 23 | private int oldG = 0; 24 | private int oldB = 0; 25 | 26 | private static enum PulseType { 27 | RGB, 28 | RGB2, 29 | RANDOM, 30 | RANDOM2, 31 | RANDOM3 32 | } 33 | 34 | public PulseEffect(Table t, LedTable_Selection s) { 35 | super(t, s); 36 | delay = 1; 37 | setMode(s); 38 | 39 | table.write(LedTable_Util.getRGBArray(0, 0, 0)); 40 | } 41 | 42 | @Override 43 | public EffectInfo setEffectInfo() { 44 | EffectInfoParameter[] paramInfo = { 45 | new EffectInfoParameter("inc", "Amount to change colors by", EffectInfoParameterType.INT, 1, 100), 46 | new EffectInfoParameter("pulseType", "Pulse Type Mode", StringUtils.enumToString(PulseType.class)) 47 | }; 48 | EffectInfo ei = new EffectInfo("PulseEffect", 49 | "Fades the table color in and out", paramInfo); 50 | 51 | return ei; 52 | } 53 | 54 | public void setMode(LedTable_Selection s) { 55 | super.setMode(s); 56 | 57 | if(s.getParams().get("inc") != null) this.pulseInc = Integer.parseInt(s.getParams().get("inc")); 58 | if(s.getParams().get("pulseType") != null) this.pulseType = PulseType.valueOf(s.getParams().get("pulseType").toUpperCase()); 59 | } 60 | 61 | @Override 62 | public void effectsLoop() { 63 | if (this.pulseType == PulseType.RGB) this.rgbPulse(); 64 | else if (this.pulseType == PulseType.RGB2) this.rgbPulse2(); 65 | else if (this.pulseType == PulseType.RANDOM) this.randomPulse(); 66 | else if (this.pulseType == PulseType.RANDOM2) this.randomPulse2(); 67 | else if (this.pulseType == PulseType.RANDOM3) this.randomPulse3(); 68 | } 69 | 70 | private void rgbPulse() { 71 | LOG.entering(name, "rgbPulse"); 72 | 73 | for (int i = 0; i <= 255; i += pulseInc) { 74 | if (!run) return; 75 | 76 | LOG.finer("pulse RED"); 77 | table.write(LedTable_Util.getRGBArray(i, 0, 0)); 78 | this.delay(); 79 | } 80 | for (int i = 0; i <= 255; i += pulseInc) { 81 | if (!run) return; 82 | 83 | LOG.finer("pulse GREEN"); 84 | table.write(LedTable_Util.getRGBArray(0, i, 0)); 85 | this.delay(); 86 | } 87 | for (int i = 0; i <= 255; i += pulseInc) { 88 | if (!run) return; 89 | 90 | LOG.finer("pulse BLUE"); 91 | table.write(LedTable_Util.getRGBArray(0, 0, i)); 92 | this.delay(); 93 | } 94 | 95 | LOG.exiting(name, "rgbPulse"); 96 | } 97 | 98 | private void rgbPulse2() { 99 | LOG.entering(name, "rgbPulse2"); 100 | 101 | for (int i = 0; i <= 255; i += pulseInc) { 102 | if (!run) return; 103 | 104 | table.write(LedTable_Util.getRGBArray(i, 0, 0)); 105 | this.delay(); 106 | } 107 | for (int i = 255; i >= 0; i -= pulseInc) { 108 | if (!run) return; 109 | 110 | table.write(LedTable_Util.getRGBArray(i, 0, 0)); 111 | this.delay(); 112 | } 113 | for (int i = 0; i <= 255; i += pulseInc) { 114 | if (!run) return; 115 | 116 | table.write(LedTable_Util.getRGBArray(0, i, 0)); 117 | this.delay(); 118 | } 119 | for (int i = 255; i >= 0; i -= pulseInc) { 120 | if (!run) return; 121 | 122 | table.write(LedTable_Util.getRGBArray(0, i, 0)); 123 | this.delay(); 124 | } 125 | for (int i = 0; i <= 255; i += pulseInc) { 126 | if (!run) return; 127 | 128 | table.write(LedTable_Util.getRGBArray(0, 0, i)); 129 | this.delay(); 130 | } 131 | for (int i = 255; i >= 0; i -= pulseInc) { 132 | if (!run) return; 133 | 134 | table.write(LedTable_Util.getRGBArray(0, 0, i)); 135 | this.delay(); 136 | } 137 | 138 | LOG.exiting(name, "rgbPulse"); 139 | } 140 | 141 | /** 142 | * Fades to the next random color, once color type at a time R then G then B 143 | */ 144 | private void randomPulse() { 145 | int newR = rnd.nextInt(256); 146 | int newG = rnd.nextInt(256); 147 | int newB = rnd.nextInt(256); 148 | 149 | while ((newR > oldR + pulseInc/2) || (newR < oldR - pulseInc/2)) { 150 | if (oldR < newR) { 151 | oldR += pulseInc; 152 | } 153 | else if (oldR > newR) { 154 | oldR -= pulseInc; 155 | } 156 | 157 | table.write(LedTable_Util.getRGBArray(oldR, oldG, oldB)); 158 | if (!run) return; 159 | this.delay(); 160 | } 161 | while ((newG > oldG + pulseInc/2) || (newG < oldG - pulseInc/2)) { 162 | if (oldG < newG) { 163 | oldG += pulseInc; 164 | } 165 | else if (oldG > newG) { 166 | oldG -= pulseInc; 167 | } 168 | table.write(LedTable_Util.getRGBArray(oldR, oldG, oldB)); 169 | if (!run) return; 170 | this.delay(); 171 | } 172 | while ((newB > oldB + pulseInc/2) || (newB < oldB - pulseInc/2)) { 173 | if (oldB < newB) { 174 | oldB += pulseInc; 175 | } 176 | else if (oldB > newB) { 177 | oldB -= pulseInc; 178 | } 179 | table.write(LedTable_Util.getRGBArray(oldR, oldG, oldB)); 180 | if (!run) return; 181 | this.delay(); 182 | } 183 | } 184 | 185 | /** 186 | * Different from randomPulse because it uses the fade method, which will 187 | * fade through all 3 colors at once instead of doing R then G then B 188 | */ 189 | private void randomPulse2() { 190 | int newR = rnd.nextInt(256); 191 | int newG = rnd.nextInt(256); 192 | int newB = rnd.nextInt(256); 193 | 194 | byte[] newTable = LedTable_Util.getRGBArray(newR, newG, newB); 195 | 196 | try { 197 | Effect_Util.fade((Effect)this, table, newTable, pulseInc, (int)delay); 198 | delay(); 199 | } catch (InterruptedException e) { 200 | e.printStackTrace(); 201 | LOG.severe("Error in randomPulse2 waiting thread: " + e); 202 | } 203 | 204 | } 205 | 206 | private void randomPulse3() { 207 | int oldRed = table.getLastWrite()[0] & 0xFF; 208 | int oldGreen = table.getLastWrite()[1] & 0xFF; 209 | int oldBlue = table.getLastWrite()[2] & 0xFF; 210 | 211 | int newR; 212 | int newG; 213 | int newB; 214 | 215 | int colorToChange = rnd.nextInt(3); 216 | 217 | if (colorToChange == 0) newR = rnd.nextInt(256); 218 | else newR = oldRed; 219 | 220 | if (colorToChange == 0) newG = rnd.nextInt(256); 221 | else newG = oldGreen; 222 | 223 | if (colorToChange == 0) newB = rnd.nextInt(256); 224 | else newB = oldBlue; 225 | 226 | byte[] newTable = LedTable_Util.getRGBArray(newR, newG, newB); 227 | 228 | try { 229 | Effect_Util.fade((Effect)this, table, newTable, pulseInc, (int)delay); 230 | delay(); 231 | } catch (InterruptedException e) { 232 | e.printStackTrace(); 233 | LOG.severe("Error in randomPulse2 waiting thread: " + e); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/RainbowEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.awt.Color; 7 | 8 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 9 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 10 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 11 | import net.mdp3.java.rpi.ledtable.table.Table; 12 | 13 | /** 14 | * @author Mikel 15 | * 16 | */ 17 | public class RainbowEffect extends Effect { 18 | private final static String name = "RainbowEffect"; 19 | 20 | private int rbInc1 = 10; 21 | private int rbInc2 = 1; 22 | private int rbType = 1; 23 | 24 | public RainbowEffect(Table t, LedTable_Selection s) { 25 | super(t, s); 26 | setMode(s); 27 | } 28 | 29 | @Override 30 | public EffectInfo setEffectInfo() { 31 | EffectInfoParameter[] paramInfo = { 32 | new EffectInfoParameter("rbInc1", "Amount to change colors by", EffectInfoParameterType.INT, 1, 100), 33 | new EffectInfoParameter("rbInc2", "Other amount to change by", EffectInfoParameterType.INT, 1, 100), 34 | new EffectInfoParameter("rbType", "Rainbow Mode", EffectInfoParameterType.INT, 1, 2) 35 | }; 36 | EffectInfo ei = new EffectInfo("RainbowEffect", 37 | "Changes between lots of colors", paramInfo); 38 | 39 | return ei; 40 | } 41 | 42 | public void setMode(LedTable_Selection s) { 43 | super.setMode(s); 44 | 45 | if(s.getParams().get("rbInc1") != null) this.rbInc1 = Integer.parseInt(s.getParams().get("rbInc1")); 46 | if(s.getParams().get("rbInc2") != null) this.rbInc2 = Integer.parseInt(s.getParams().get("rbInc2")); 47 | if(s.getParams().get("rbType") != null) this.rbType = Integer.parseInt(s.getParams().get("rbType")); 48 | } 49 | 50 | @Override 51 | public void effectsLoop() { 52 | if (rbType == 1) this.rainbow(); 53 | else this.rainbow2(); 54 | } 55 | 56 | private void rainbow() { 57 | LOG.entering(name, "rainbow"); 58 | 59 | byte[] bAr = LedTable_Util.getbAr(); 60 | //TODO Change to user tableAr[][] instead of byteAr[], the snake code is being passed over when ran 61 | for (int j=0; j < 256; j += rbInc1) { // 3 cycles of all 256 colors in the wheel 62 | for (int i = 0; i < LedTable_Util.getbAr().length; i += rbInc2) { 63 | Color c = wheel((i + j) % 255); 64 | bAr[i++] = (byte)c.getRed(); 65 | bAr[i++] = (byte)c.getGreen(); 66 | bAr[i] = (byte)c.getBlue(); 67 | } 68 | table.write(bAr); 69 | 70 | if (!run) return; 71 | delay(); 72 | } 73 | 74 | LOG.exiting(name, "rainbow"); 75 | } 76 | 77 | private void rainbow2() { 78 | for (int j = 0; j < 256; j += rbInc1) { 79 | for (int y = 0; y < LedTable_Util.getTableAr().length; y++) { 80 | for (int x = 0; x < LedTable_Util.getTableAr()[y].length; x++) { 81 | Color c = wheel((j + rbInc2) % 255); 82 | LedTable_Util.getTableAr()[y][x] = (byte)c.getRed(); 83 | LedTable_Util.getTableAr()[y][x++] = (byte)c.getGreen(); 84 | LedTable_Util.getTableAr()[y][x++] = (byte)c.getBlue(); 85 | 86 | table.write(LedTable_Util.tableArToByteAr()); 87 | 88 | if (!run) return; 89 | delay(); 90 | } 91 | } 92 | } 93 | } 94 | 95 | private Color wheel(int pos) { 96 | if (pos < 85) { 97 | return new Color(pos * 3, 255 - pos * 3, 0); 98 | } else if (pos < 170) { 99 | pos -= 85; 100 | return new Color(255 - pos * 3, 0, pos * 3); 101 | } else { 102 | pos -= 170; 103 | return new Color(0, pos * 3, 255 - pos * 3); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/RandomFillEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import java.awt.Color; 7 | import java.util.Arrays; 8 | import java.util.Stack; 9 | 10 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 11 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 12 | import net.mdp3.java.rpi.ledtable.LedTable_Util; 13 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 14 | import net.mdp3.java.rpi.ledtable.table.Table; 15 | import net.mdp3.java.util.string.StringUtils; 16 | 17 | /** 18 | * @author Mikel 19 | * 20 | */ 21 | public class RandomFillEffect extends Effect { 22 | 23 | private RandomMode randomType = RandomMode.FILL; 24 | private boolean enableFade = true; 25 | private boolean direction = true; 26 | 27 | private int totalNumOfPixels = LedTable_Settings.ledX * LedTable_Settings.ledY; 28 | 29 | private static enum RandomMode { 30 | FILL, 31 | RANDOM, 32 | RANDOM_TO_COLOR, 33 | SEQ, 34 | SEQ_RAND, 35 | DIRECTIONAL_FILL, 36 | SQUARES 37 | } 38 | 39 | /** 40 | * @param t 41 | * @param s 42 | */ 43 | public RandomFillEffect(Table t, LedTable_Selection s) { 44 | super(t, s); 45 | 46 | setMode(s); 47 | } 48 | 49 | /* (non-Javadoc) 50 | * @see net.mdp3.java.rpi.ledtable.effects.Effect#effectsLoop() 51 | */ 52 | @Override 53 | public void effectsLoop() { 54 | if (this.randomType == RandomMode.FILL) randomFill(); 55 | else if (this.randomType == RandomMode.RANDOM) randomRandom(); 56 | else if (this.randomType == RandomMode.RANDOM_TO_COLOR) randomToColor(); 57 | else if (this.randomType == RandomMode.SEQ) randomSeq(); 58 | else if (this.randomType == RandomMode.SEQ_RAND) randomSeqRandom(); 59 | else if (this.randomType == RandomMode.DIRECTIONAL_FILL) randomDirectionFill(); 60 | else if (this.randomType == RandomMode.SQUARES) randomRectangles(); 61 | } 62 | 63 | /* (non-Javadoc) 64 | * @see net.mdp3.java.rpi.ledtable.effects.Effect#setEffectInfo() 65 | */ 66 | @Override 67 | public EffectInfo setEffectInfo() { 68 | EffectInfoParameter[] paramInfo = { 69 | new EffectInfoParameter("randomType", "Random Type Mode", StringUtils.enumToString(RandomMode.class)), 70 | new EffectInfoParameter("enableFade", "Enable Fading between frames", EffectInfoParameterType.BOOL), 71 | new EffectInfoParameter("direction", "Direction to sequential fill", EffectInfoParameterType.BOOL), 72 | }; 73 | EffectInfo ei = new EffectInfo("RandomFillEffect", 74 | "Sets pixels to random colors", paramInfo); 75 | 76 | return ei; 77 | } 78 | 79 | @Override 80 | public void setMode(LedTable_Selection s) { 81 | super.setMode(s); 82 | 83 | if(s.getParams().get("randomType") != null) this.randomType = RandomMode.valueOf(s.getParams().get("randomType").toUpperCase()); 84 | if(s.getParams().get("enableFade") != null) this.enableFade = Boolean.parseBoolean(s.getParams().get("enableFade")); 85 | if(s.getParams().get("direction") != null) this.direction = Boolean.parseBoolean(s.getParams().get("direction")); 86 | } 87 | 88 | /** 89 | * Fill the table with all random colors 90 | */ 91 | private void randomFill() { 92 | byte[] newTableAr = new byte[table.getLastWrite().length]; 93 | 94 | for (int i = 0; i < newTableAr.length; i++) { 95 | newTableAr[i] = (byte) rnd.nextInt(256); 96 | } 97 | 98 | showTable(newTableAr); 99 | } 100 | 101 | /** 102 | * Changes a random amount of pixels on the table to a random color 103 | */ 104 | private void randomRandom() { 105 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 106 | 107 | int numOfPixelsToFill = rnd.nextInt(totalNumOfPixels); 108 | 109 | for (int i = 0; i < numOfPixelsToFill; i++) { 110 | int pixel = rnd.nextInt(totalNumOfPixels); 111 | pixel *= 3; 112 | 113 | newTableAr[pixel] = (byte) rnd.nextInt(256); //R 114 | newTableAr[pixel+1] = (byte) rnd.nextInt(256); //G 115 | newTableAr[pixel+2] = (byte) rnd.nextInt(256); //B 116 | } 117 | 118 | showTable(newTableAr); 119 | } 120 | 121 | /** 122 | * Randomly fills pixels on the table until it is full of the next random color 123 | */ 124 | private void randomToColor() { 125 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 126 | 127 | Color targetColor = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 128 | 129 | int numOfPixelsToFill = totalNumOfPixels; 130 | int numOfPixelsToFillAtATime = 1; 131 | 132 | Stack s = new Stack(); 133 | 134 | int pixel = rnd.nextInt(totalNumOfPixels); 135 | 136 | for (int i = 0; i < numOfPixelsToFill; i++) { 137 | if (!run) return; 138 | 139 | for (int j = 0; j < numOfPixelsToFillAtATime; j++) { 140 | if (!run) return; 141 | 142 | while (s.contains(Integer.valueOf(pixel))) pixel = rnd.nextInt(totalNumOfPixels); 143 | s.push(Integer.valueOf(pixel)); 144 | 145 | setPixelColor(newTableAr, pixel, targetColor); 146 | } 147 | showTable(newTableAr); 148 | } 149 | } 150 | 151 | /** 152 | * Fills the table sequentially with random colors, snake like effect if 153 | * leds are snaked 154 | */ 155 | private void randomSeq() { 156 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 157 | 158 | Color targetColor = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 159 | 160 | int numOfPixelsToFill = totalNumOfPixels; 161 | 162 | if (direction) { 163 | for (int i = 0; i < numOfPixelsToFill; i++) { 164 | if (!run) return; 165 | 166 | setPixelColor(newTableAr, i, targetColor); 167 | 168 | showTable(newTableAr); 169 | } 170 | } else { 171 | for (int i = numOfPixelsToFill-1; i >= 0; i--) { 172 | if (!run) return; 173 | 174 | setPixelColor(newTableAr, i, targetColor); 175 | 176 | showTable(newTableAr); 177 | } 178 | } 179 | } 180 | 181 | /** 182 | * Fills the table sequentially with random colors 183 | */ 184 | private void randomSeqRandom() { 185 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 186 | 187 | Color targetColor = null; 188 | 189 | int numOfPixelsToFill = totalNumOfPixels; 190 | 191 | if (direction) { 192 | for (int i = 0; i < numOfPixelsToFill; i++) { 193 | if (!run) return; 194 | 195 | targetColor = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 196 | 197 | setPixelColor(newTableAr, i, targetColor); 198 | 199 | showTable(newTableAr); 200 | } 201 | } else { 202 | for (int i = numOfPixelsToFill-1; i >= 0; i--) { 203 | if (!run) return; 204 | 205 | targetColor = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 206 | 207 | setPixelColor(newTableAr, i, targetColor); 208 | 209 | showTable(newTableAr); 210 | } 211 | } 212 | } 213 | 214 | private void randomDirectionFill() { 215 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 216 | Color[][] colorTableAr = LedTable_Util.bArToColorAr(newTableAr); 217 | 218 | Color targetColor = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 219 | 220 | 221 | int runTime = this.totalNumOfPixels; 222 | int x = rnd.nextInt(LedTable_Settings.ledX); 223 | int y = rnd.nextInt(LedTable_Settings.ledY); 224 | 225 | for (int i = 0; i < runTime; i++) { 226 | if (!run) return; 227 | 228 | colorTableAr[y][x] = targetColor; 229 | 230 | int oldX = x; 231 | int oldY = y; 232 | 233 | int direction = rnd.nextInt(4); 234 | if (direction == 0) x--; 235 | else if (direction == 1) x++; 236 | else if (direction == 2) y--; 237 | else if (direction == 3) y++; 238 | 239 | if (y < 0) y = 0; 240 | if (y > colorTableAr.length - 1) y = colorTableAr.length - 1; 241 | if (x < 0) x = 0; 242 | if (x > colorTableAr[y].length - 1) x = colorTableAr[y].length - 1; 243 | 244 | //If the new pixel has already been filled, the go back 245 | if (colorTableAr[y][x] == colorTableAr[oldY][oldX]) { 246 | y = oldY; 247 | x = oldX; 248 | } 249 | 250 | showTable(LedTable_Util.tableColorToByteAr(colorTableAr)); 251 | } 252 | } 253 | 254 | private void randomRectangles() { 255 | byte[] newTableAr = Arrays.copyOf(table.getLastWrite(), table.getLastWrite().length); 256 | Color[][] colorTableAr = LedTable_Util.bArToColorAr(newTableAr); 257 | 258 | int startX = rnd.nextInt(LedTable_Settings.ledX - 1); 259 | int startY = rnd.nextInt(LedTable_Settings.ledY - 1); 260 | int width = rnd.nextInt(LedTable_Settings.ledX - startX); 261 | int height = rnd.nextInt(LedTable_Settings.ledY - startY); 262 | 263 | if (width < 1) width = 1; 264 | if (height < 1) height = 1; 265 | 266 | Color color = new Color(rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); 267 | 268 | Effect_Util.drawSquare(colorTableAr, startX, startY, width, height, color, true); 269 | 270 | showTable(LedTable_Util.tableColorToByteAr(colorTableAr)); 271 | 272 | delay(); 273 | } 274 | 275 | private void setPixelColor(byte[] newTableAr, int pos, Color c) { 276 | newTableAr[pos*3] = (byte) c.getRed(); 277 | newTableAr[pos*3+1] = (byte) c.getGreen(); 278 | newTableAr[pos*3+2] = (byte) c.getBlue(); 279 | } 280 | 281 | private void showTable(byte[] newTableAr) { 282 | if (enableFade) { 283 | try { 284 | Effect_Util.fade((Effect)this, table, newTableAr, 10, (int)delay); 285 | } catch (InterruptedException e) { 286 | LOG.severe("Error fading RandomFill: " + e); 287 | } 288 | } else { 289 | table.write(newTableAr); 290 | delay(); 291 | } 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/SetColorEffect.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects; 5 | 6 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 7 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 8 | import net.mdp3.java.rpi.ledtable.table.Table; 9 | 10 | /** 11 | * @author Mikel 12 | * 13 | */ 14 | public class SetColorEffect extends Effect { 15 | 16 | /** 17 | * @param t 18 | * @param s 19 | */ 20 | public SetColorEffect(Table t, LedTable_Selection s) { 21 | super(t, s); 22 | } 23 | 24 | /* (non-Javadoc) 25 | * @see net.mdp3.java.rpi.ledtable.effects.Effect#effectsLoop() 26 | */ 27 | @Override 28 | public void effectsLoop() { 29 | try { 30 | Effect_Util.colorSelection(table, selection); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | LOG.severe("Error setting table color: " + e); 34 | } 35 | 36 | stopEffect(); 37 | } 38 | 39 | /* (non-Javadoc) 40 | * @see net.mdp3.java.rpi.ledtable.effects.Effect#setEffectInfo() 41 | */ 42 | @Override 43 | public EffectInfo setEffectInfo() { 44 | EffectInfoParameter[] paramInfo = { 45 | new EffectInfoParameter("color", "Name of color", EffectInfoParameterType.STRING), 46 | new EffectInfoParameter("r", "Red", EffectInfoParameterType.INT, 0, 255), 47 | new EffectInfoParameter("g", "Green", EffectInfoParameterType.INT, 0, 255), 48 | new EffectInfoParameter("b", "Blue", EffectInfoParameterType.INT, 0, 255) 49 | }; 50 | EffectInfo ei = new EffectInfo("Set Color", 51 | "Sets the table to a set color", paramInfo); 52 | 53 | return ei; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/TransparencyAnimationEffect.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.effects; 2 | 3 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 4 | import net.mdp3.java.rpi.ledtable.effects.EffectInfoParameter.EffectInfoParameterType; 5 | import net.mdp3.java.rpi.ledtable.table.Table; 6 | 7 | /** 8 | * Class extends AnimationEffect to add transparency feature for effects 9 | * Image Series for animation will be loaded, shown in random location, 10 | * and will use 1 random new color to overwrite existing colors. 11 | * 12 | * Images should be 2 color black and white, black will be used as 13 | * transparency color 14 | * 15 | * @author Mikel 16 | * 17 | */ 18 | public class TransparencyAnimationEffect extends AnimationEffect { 19 | private final static String name = "TransparencyAnimationEffect"; 20 | 21 | public TransparencyAnimationEffect(Table t, LedTable_Selection s) { 22 | super(t, s); 23 | } 24 | 25 | public void effectsLoop() { 26 | LOG.entering(TransparencyAnimationEffect.name, "effectsLoop"); 27 | 28 | //TODO Implement new transparency effect, right now this just shows plain animations 29 | for (int i = 0; i < fileList.length; i++) { 30 | if (run) { //checked again so that when the mode changes, the thread can quit on the next frame 31 | if (i < super.imageAr.length) { 32 | if (!this.fade) 33 | super.table.write(imageAr[i]); 34 | else { 35 | try { 36 | Effect_Util.fade(this, super.table, super.imageAr[i], super.numOfFrames, super.fadeDelay); 37 | super.table.write(super.imageAr[i]); 38 | } catch (InterruptedException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | } 43 | delay(); 44 | } 45 | } 46 | 47 | LOG.exiting(TransparencyAnimationEffect.name, "effectsLoop"); 48 | } 49 | 50 | public long getRuntime() { 51 | return this.delay * fileList.length; 52 | } 53 | 54 | @Override 55 | public EffectInfo setEffectInfo() { 56 | EffectInfoParameter[] paramInfo = { 57 | new EffectInfoParameter("fade", "Toggle Fading between Images", EffectInfoParameterType.BOOL), 58 | new EffectInfoParameter("numOfFrames", "Number of Frames to fade", EffectInfoParameterType.INT, 1, 1000), 59 | new EffectInfoParameter("fadeDelay", "Time between each fade frame", EffectInfoParameterType.INT, 1, 20000), 60 | new EffectInfoParameter("folder", "Folder to select images from", EffectInfoParameterType.FOLDER) 61 | }; 62 | EffectInfo ei = new EffectInfo("TransparencyAnimationEffect", "Can show images in a folder", paramInfo); 63 | 64 | return ei; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/playlist/PlaylistEvent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects.playlist; 5 | 6 | /** 7 | * @author Mikel 8 | * 9 | */ 10 | public class PlaylistEvent { 11 | private PlaylistEventName eventName = null; 12 | private Object eventValue = ""; 13 | 14 | private Object eventSource = null; 15 | 16 | public static enum PlaylistEventName { 17 | PLAYBACK_PLAY, 18 | PLAYBACK_STOP, 19 | PLAYBACK_MODE_CHANGED, 20 | INDEX_CHANGED, 21 | ITEM_ADDED, 22 | ITEM_REMOVED, 23 | PLAYLIST_SAVED, 24 | PLAYLIST_LOADED, 25 | PLAYLIST_CLEARED 26 | } 27 | 28 | public PlaylistEvent(PlaylistEventName eventName) { 29 | this(eventName, null); 30 | } 31 | 32 | public PlaylistEvent(PlaylistEventName eventName, Object eventValue) { 33 | this(eventName, eventValue, null); 34 | } 35 | 36 | public PlaylistEvent(PlaylistEventName eventName, Object eventValue, Object source) { 37 | this.setEventName(eventName); 38 | this.setEventValue(eventValue); 39 | this.setEventSource(source); 40 | } 41 | 42 | public PlaylistEventName getEventName() { 43 | return eventName; 44 | } 45 | 46 | public void setEventName(PlaylistEventName eventName) { 47 | this.eventName = eventName; 48 | } 49 | 50 | public Object getEventValue() { 51 | return eventValue; 52 | } 53 | 54 | public void setEventValue(Object eventValue) { 55 | this.eventValue = eventValue; 56 | } 57 | 58 | public Object getEventSource() { 59 | return eventSource; 60 | } 61 | 62 | public void setEventSource(Object eventSource) { 63 | this.eventSource = eventSource; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/playlist/PlaylistEventListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects.playlist; 5 | 6 | /** 7 | * @author Mikel 8 | * 9 | */ 10 | public interface PlaylistEventListener { 11 | public void playlistEvent(PlaylistEvent pev); 12 | } 13 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/playlist/PlaylistItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects.playlist; 5 | 6 | import java.util.logging.Logger; 7 | 8 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 9 | import net.mdp3.java.util.xml.DomXml; 10 | import net.mdp3.java.util.xml.XmlHelper; 11 | 12 | import org.w3c.dom.Document; 13 | import org.w3c.dom.Element; 14 | import org.w3c.dom.Node; 15 | import org.w3c.dom.NodeList; 16 | 17 | /** 18 | * @author Mikel 19 | * 20 | */ 21 | public class PlaylistItem implements DomXml { 22 | private final static Logger LOG = Logger.getLogger(PlaylistItem.class.getName()); 23 | private final static String name = "PlaylistItem"; 24 | 25 | public final static String NODE_NAME = "playlistItem"; 26 | public final static String NODE_PLAYTIME = "playTime"; 27 | 28 | private int playTime = 10; 29 | public static final int DEFAULT_PLAYTIME = 10; 30 | 31 | private LedTable_Selection selection = null; 32 | 33 | public PlaylistItem() { 34 | this(new LedTable_Selection()); 35 | } 36 | 37 | public PlaylistItem(LedTable_Selection selection) { 38 | this(DEFAULT_PLAYTIME, selection); 39 | } 40 | 41 | public PlaylistItem(int playTime, LedTable_Selection selection) { 42 | this.setPlayTime(playTime); 43 | this.setSelection(selection); 44 | } 45 | 46 | public int getPlayTime() { 47 | return playTime; 48 | } 49 | 50 | public void setPlayTime(int playTime) { 51 | this.playTime = playTime; 52 | } 53 | 54 | public LedTable_Selection getSelection() { 55 | return selection; 56 | } 57 | 58 | public void setSelection(LedTable_Selection selection) { 59 | this.selection = selection; 60 | } 61 | 62 | @Override 63 | public boolean equals(Object o) { 64 | if (this.getClass() != o.getClass()) return false; 65 | 66 | final PlaylistItem oItem = (PlaylistItem)o; 67 | if (this.getPlayTime() != oItem.getPlayTime()) return false; 68 | 69 | if (!this.getSelection().equals(oItem.getSelection())) return false; 70 | 71 | return true; 72 | } 73 | 74 | @Override 75 | public int hashCode() { 76 | int hash = 1; 77 | hash = 2 * hash + (this.getPlayTime()); 78 | hash = 2 * hash + (this.getSelection().hashCode()); 79 | return hash; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | String ret = ""; 85 | ret += "PlaylistItem: "; 86 | ret += " PlayTime: " + this.getPlayTime(); 87 | ret += " Selection: " + this.getSelection(); 88 | return ret; 89 | } 90 | 91 | @Override 92 | public Element toXml(Document doc) { 93 | LOG.entering(name, "toXml", "doc:"+doc); 94 | 95 | Element selectionE = doc.createElement(PlaylistItem.NODE_NAME); 96 | 97 | selectionE.appendChild(XmlHelper.newTextElement(doc, PlaylistItem.NODE_PLAYTIME, this.getPlayTime())); 98 | selectionE.appendChild(this.getSelection().toXml(doc)); 99 | 100 | LOG.exiting(name, "toXml"); 101 | return selectionE; 102 | } 103 | 104 | @Override 105 | public void fromXml(Element e) throws Exception { 106 | LOG.entering(name, "fromXml", "e:"+e); 107 | 108 | int time = PlaylistItem.DEFAULT_PLAYTIME; 109 | LedTable_Selection s = new LedTable_Selection(); 110 | 111 | NodeList nl = e.getChildNodes(); 112 | for (int i = 0; i < nl.getLength(); i++) { 113 | Node n = nl.item(i); 114 | 115 | if (n.getNodeType() == Node.ELEMENT_NODE) { 116 | String key = n.getNodeName(); 117 | String value = n.getTextContent(); 118 | 119 | LOG.finer("fromXml Key: " + key + " Value: " + value); 120 | 121 | if (key.equals(PlaylistItem.NODE_PLAYTIME)) time = Integer.valueOf(value); 122 | else if (key.equals(LedTable_Selection.NODE_NAME)) s.fromXml((Element)n); 123 | } 124 | } 125 | 126 | this.setPlayTime(time); 127 | this.setSelection(s); 128 | 129 | LOG.exiting(name, "fromXml"); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/effects/playlist/PlaylistTimer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.effects.playlist; 5 | 6 | /** 7 | * @author Mikel 8 | * 9 | */ 10 | public class PlaylistTimer extends Thread { 11 | private long delay = 100; 12 | private long setTime = 100; 13 | private long currentTime = 0; 14 | 15 | private volatile boolean run = false; 16 | private volatile boolean isTiming = false; 17 | private Playlist pl = null; 18 | 19 | public PlaylistTimer(int seconds, Playlist pl) { 20 | this.pl = pl; 21 | setTime(seconds); 22 | } 23 | 24 | @Override 25 | public final void run() { 26 | run = true; 27 | 28 | while(run) { 29 | delay(); 30 | checkTimer(); 31 | } 32 | } 33 | 34 | /** 35 | * Resets the current time, sets the new time, and stops the current timer 36 | * 37 | * @param newTime 38 | */ 39 | public void setTime(int newTime) { 40 | stopTimer(); 41 | this.setTime = newTime * 1000; 42 | this.currentTime = 0; 43 | } 44 | 45 | private void checkTimer() { 46 | if (isTiming()) { 47 | timerTick(); 48 | if (this.currentTime >= this.setTime && run) { 49 | stopTimer(); 50 | pl.next(); 51 | } 52 | } 53 | } 54 | 55 | public boolean isRunning() { 56 | return run; 57 | } 58 | 59 | public long getDelay() { 60 | return delay; 61 | } 62 | 63 | public void setDelay(long delay) { 64 | this.delay = delay; 65 | } 66 | 67 | public void shutdownTimer() { 68 | stopTimer(); 69 | this.run = false; 70 | } 71 | 72 | private void timerTick() { 73 | //TODO change to use real time instead of just delay time 74 | this.currentTime += this.delay; 75 | } 76 | 77 | private void delay() { 78 | try { 79 | Thread.sleep(this.delay); 80 | } catch (InterruptedException e) { 81 | e.printStackTrace(); 82 | } 83 | } 84 | 85 | public synchronized void startTimer() { 86 | this.isTiming = true; 87 | } 88 | 89 | public synchronized void stopTimer() { 90 | this.isTiming = false; 91 | } 92 | 93 | public synchronized boolean isTiming() { 94 | return this.isTiming; 95 | } 96 | 97 | public void resetTimer() { 98 | this.currentTime = 0; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/gui/EffectWindow.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.gui; 5 | 6 | import java.awt.BorderLayout; 7 | import java.awt.FlowLayout; 8 | import java.util.logging.Logger; 9 | 10 | import javax.swing.JDialog; 11 | import javax.swing.JPanel; 12 | import javax.swing.border.EmptyBorder; 13 | 14 | /** 15 | * @author Mikel 16 | * 17 | */ 18 | public class EffectWindow extends JDialog { 19 | 20 | private final static Logger LOG = Logger.getLogger(EffectWindow.class.getName()); 21 | private final static String name = "EffectWindow"; 22 | 23 | private static final long serialVersionUID = -7970848848773218137L; 24 | 25 | private final JPanel contentPanel = new JPanel(); 26 | 27 | public EffectWindow() { 28 | LOG.entering(name, "new"); 29 | 30 | this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 31 | 32 | setBounds(100, 100, 350, 474); 33 | getContentPane().setLayout(new BorderLayout()); 34 | contentPanel.setLayout(new FlowLayout()); 35 | contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); 36 | getContentPane().add(contentPanel, BorderLayout.CENTER); 37 | 38 | 39 | 40 | this.setVisible(true); 41 | 42 | LOG.exiting(name, "new"); 43 | } 44 | 45 | public static void main(String[] args) { 46 | @SuppressWarnings("unused") 47 | EffectWindow ew = new EffectWindow(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/gui/PlaylistWindow.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.gui; 5 | 6 | import javax.swing.JFrame; 7 | 8 | /** 9 | * @author Mikel 10 | * 11 | */ 12 | public class PlaylistWindow extends JFrame { 13 | 14 | /** 15 | * 16 | */ 17 | private static final long serialVersionUID = -4516912803310179006L; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/gui/TablePanel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.gui; 5 | 6 | import java.awt.Color; 7 | import java.awt.Graphics; 8 | import java.awt.Graphics2D; 9 | import java.awt.image.BufferedImage; 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.util.logging.Logger; 13 | 14 | import javax.imageio.ImageIO; 15 | import javax.swing.JPanel; 16 | 17 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 18 | import net.mdp3.java.rpi.ledtable.table.WriteListener; 19 | 20 | /** 21 | * @author Mikel 22 | * 23 | */ 24 | public class TablePanel extends JPanel implements WriteListener { 25 | private final static Logger LOG = Logger.getLogger(TablePanel.class.getName()); 26 | private final static String name = "TablePanel"; 27 | 28 | /** 29 | * 30 | */ 31 | private static final long serialVersionUID = 4720593039682897655L; 32 | private int pixelW = (LedTable_Settings.guiW - 10) / LedTable_Settings.ledX; 33 | private int pixelH = (LedTable_Settings.guiH - 70) / LedTable_Settings.ledY; 34 | 35 | private Color grid[][]; 36 | 37 | public TablePanel() { 38 | LOG.finer("Pixel Size: " + pixelW + "x" + pixelH); 39 | 40 | this.setBackground(Color.BLACK); 41 | 42 | //init Color Grid 43 | grid = new Color[LedTable_Settings.ledY][]; 44 | for (int y = 0; y < LedTable_Settings.ledY; y++) { 45 | grid[y] = new Color[LedTable_Settings.ledX]; 46 | 47 | for (int x = 0; x < LedTable_Settings.ledX; x++) { 48 | grid[y][x] = Color.BLACK; 49 | } 50 | } 51 | } 52 | 53 | public void paintComponent(Graphics g) { 54 | super.paintComponent(g); 55 | 56 | LOG.entering(name, "paintComponent"); 57 | 58 | drawTable(g); 59 | drawPixelGrid(g); 60 | 61 | LOG.exiting(name, "paintComponent"); 62 | } 63 | 64 | /** 65 | * Draws the grid lines 66 | * 67 | * @param g 68 | */ 69 | private void drawPixelGrid(Graphics g) { 70 | LOG.entering(name, "drawPixelGrid"); 71 | 72 | g.setColor(Color.WHITE); 73 | 74 | for (int y = 0; y < LedTable_Settings.ledY + 1; y++) { 75 | g.drawLine(0, y * pixelH, this.getWidth(), y * pixelH); 76 | } 77 | for (int x = 0; x < LedTable_Settings.ledX + 1; x++) { 78 | g.drawLine(x * pixelW, 0, x * pixelW, this.getHeight()); 79 | } 80 | 81 | LOG.exiting(name, "drawPixelGrid"); 82 | } 83 | 84 | 85 | /** 86 | * Draws table grid to screen 87 | * 88 | * @param g 89 | */ 90 | private void drawTable(Graphics g) { 91 | LOG.entering(name, "drawTable"); 92 | 93 | Graphics2D g2d = (Graphics2D)g; 94 | 95 | if (LedTable_Settings.flipY) { 96 | g2d.scale(1, -1); 97 | g2d.translate(0, -getHeight()); 98 | } 99 | 100 | for (int y = 0; y < LedTable_Settings.ledY; y++) { 101 | for (int x = 0; x < LedTable_Settings.ledX; x++) { 102 | g2d.setColor(grid[y][x]); 103 | g2d.fillRect(x * pixelW, y * pixelH, pixelW, pixelH); 104 | } 105 | } 106 | 107 | LOG.exiting(name, "drawTable"); 108 | } 109 | 110 | /** 111 | * Converts the byte Array bAr to the Color[][] grid and calls repaint() 112 | * 113 | * @param bAr 114 | */ 115 | public void drawTable(byte bAr[]) { 116 | LOG.entering(name, "drawTable"); 117 | 118 | if (bAr.length != LedTable_Settings.ledX * LedTable_Settings.ledY * 3) { 119 | System.out.println("TablePanel.drawTable ERROR: bAr is wrong size!"); 120 | return; 121 | } 122 | 123 | int byteCounter = 0; 124 | 125 | if (LedTable_Settings.snakedLeds) { 126 | for (int y = 0; y < LedTable_Settings.ledY; y++) { 127 | if (y % 2 == 0) { 128 | for (int x = 0; x < LedTable_Settings.ledX; x++) { 129 | int r = (int)(bAr[byteCounter++] & 0xFF); 130 | int g = (int)(bAr[byteCounter++] & 0xFF); 131 | int b = (int)(bAr[byteCounter++] & 0xFF); 132 | 133 | grid[y][x] = new Color(r, g, b); 134 | } 135 | } else { 136 | for (int x = LedTable_Settings.ledX - 1; x >= 0; x--) { 137 | int r = (int)(bAr[byteCounter++] & 0xFF); 138 | int g = (int)(bAr[byteCounter++] & 0xFF); 139 | int b = (int)(bAr[byteCounter++] & 0xFF); 140 | 141 | grid[y][x] = new Color(r, g, b); 142 | } 143 | } 144 | } 145 | } else { 146 | for (int y = 0; y < LedTable_Settings.ledY; y++) { 147 | for (int x = 0; x < LedTable_Settings.ledX; x++) { 148 | int r = (int)(bAr[byteCounter++] & 0xFF); 149 | int g = (int)(bAr[byteCounter++] & 0xFF); 150 | int b = (int)(bAr[byteCounter++] & 0xFF); 151 | grid[y][x] = new Color(r, g, b); 152 | } 153 | } 154 | } 155 | 156 | //if (LedTable_Settings.debug) dumpColorGrid(); 157 | 158 | repaint(); 159 | LOG.exiting(name, "drawTable"); 160 | } 161 | 162 | @SuppressWarnings("unused") 163 | private void dumpColorGrid() { 164 | String gridStr = "Array: \n"; 165 | for (int y = 0; y < LedTable_Settings.ledY; y++) { 166 | for (int x = 0; x < LedTable_Settings.ledX; x++) { 167 | if (x % 8 == 0) gridStr += '\n'; 168 | gridStr += grid[y][x].getRed() + " "; 169 | gridStr += grid[y][x].getGreen() + " "; 170 | gridStr += grid[y][x].getBlue() + " "; 171 | } 172 | } 173 | System.out.println(gridStr); 174 | } 175 | 176 | @Override 177 | public void writeEvent(byte[] bAr) { 178 | this.drawTable(bAr); 179 | } 180 | 181 | /** 182 | * Saves the current table grid to an image file for later loading 183 | * Note: This saves exactly what is shown at the time 184 | * 185 | * @param fileName 186 | * @throws IOException 187 | */ 188 | public void saveTable(String fileName) throws IOException { 189 | saveTable(new File(fileName)); 190 | } 191 | 192 | /** 193 | * Saves the current table grid to an image file for later loading 194 | * Note: This saves exactly what is shown at the time 195 | * 196 | * @param file 197 | * @throws IOException 198 | */ 199 | public void saveTable(File file) throws IOException { 200 | //if (!file.canWrite()) throw new IOException("Cannot write to file: " + file); 201 | 202 | BufferedImage bi = new BufferedImage(LedTable_Settings.ledX, LedTable_Settings.ledY, BufferedImage.TYPE_INT_RGB); 203 | for (int y = 0; y < grid.length; y++) { 204 | for (int x = 0; x < grid[y].length; x++) { 205 | bi.setRGB(x, y, grid[y][x].getRGB()); 206 | } 207 | } 208 | 209 | ImageIO.write(bi, "bmp", file); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/Table.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.table; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * @author Mikel 12 | * 13 | */ 14 | public abstract class Table { 15 | protected final static Logger LOG = Logger.getLogger(Table.class.getName()); 16 | private final static String name = "Table"; 17 | 18 | private List listeners = new ArrayList(); 19 | 20 | protected byte[] lastWrite = null; 21 | 22 | public synchronized void write(byte bAr[]) { 23 | this.lastWrite = bAr; 24 | for (WriteListener l : listeners) l.writeEvent(bAr); 25 | } 26 | 27 | public void addWriteListener(WriteListener listener) { 28 | LOG.entering(name, "addWriteListener", listener); 29 | 30 | if (!this.listeners.contains(listener)) 31 | this.listeners.add(listener); 32 | 33 | LOG.exiting(name, "addWriteListener"); 34 | } 35 | 36 | public byte[] getLastWrite() { 37 | return this.lastWrite; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/TableCMD.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.table; 2 | 3 | import java.io.IOException; 4 | 5 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 6 | 7 | public class TableCMD extends Table { 8 | private final static String name = "LedTable_CMD"; 9 | 10 | public synchronized void write(byte[] bAr) { 11 | LOG.entering(TableCMD.name, "write", bAr); 12 | //LOG.finest(LedTable_Util.bArToString(bAr)); 13 | //long t = System.currentTimeMillis(); 14 | 15 | if (LedTable_Settings.enableTableOutput) { 16 | try { 17 | String cmd = this.buildCmd(bAr); 18 | String cmdline[] = { "sh", "-c", cmd }; 19 | Runtime.getRuntime().exec(cmdline);//.waitFor(); 20 | 21 | Thread.sleep(10); 22 | } catch (InterruptedException | IOException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | //LOG.finest("Write Time: " + (System.currentTimeMillis() - t)); 28 | LOG.exiting(TableCMD.name, "write", bAr.length + " bytes written"); 29 | } 30 | 31 | private String buildCmd(byte bAr[]) { 32 | LOG.entering(name, "buildCmd"); 33 | 34 | String ret = ""; 35 | String bytes = ""; 36 | 37 | for (int i = 0; i < bAr.length; i++) { 38 | int val = (bAr[i] & 0xFF); 39 | String hex = Integer.toHexString(val).toUpperCase(); 40 | while (hex.length() < 2) hex = '0' + hex; 41 | 42 | bytes += "\\x" + hex; 43 | } 44 | 45 | ret = "echo -ne \"" + bytes + "\" > /dev/spidev0.0"; 46 | 47 | LOG.info(ret); 48 | LOG.exiting(name, "buildCmd", ret); 49 | return ret; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/TableFactory.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.table; 5 | 6 | import java.io.IOException; 7 | import java.util.logging.Logger; 8 | 9 | /** 10 | * @author Mikel 11 | * 12 | */ 13 | public class TableFactory { 14 | private final static Logger LOG = Logger.getLogger(TableFactory.class.getName()); 15 | private final static String NAME = "TableFactory"; 16 | 17 | public static enum TableOutputMode { 18 | SPI, 19 | CMD, 20 | FILE, 21 | SERIAL 22 | } 23 | 24 | public static Table getTable(TableOutputMode tableMode) throws IOException { 25 | LOG.entering(NAME, "getTable", "mode: " + tableMode); 26 | 27 | LOG.info("Creating Table to " + tableMode); 28 | 29 | Table table = null; 30 | 31 | if (tableMode == TableOutputMode.SPI) { 32 | table = new TableSPI(); 33 | } else if (tableMode == TableOutputMode.CMD) { 34 | table = new TableCMD(); 35 | } else if (tableMode == TableOutputMode.FILE) { 36 | table = new TableFile(); 37 | } else if (tableMode == TableOutputMode.SERIAL) { 38 | table = new TableSerial(); 39 | } else { 40 | LOG.info("Invalid Table Mode: " + tableMode); 41 | } 42 | 43 | LOG.exiting(NAME, "getTable", "table: " + table); 44 | 45 | return table; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/TableFile.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.table; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | 8 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 9 | 10 | public class TableFile extends Table { 11 | private final static String name = "LedTable_CMD"; 12 | 13 | private File file = null; 14 | private FileOutputStream fos = null; 15 | 16 | public TableFile() { 17 | super(); 18 | 19 | file = new File(LedTable_Settings.outputFile); 20 | try { 21 | fos = new FileOutputStream(file); 22 | } catch (FileNotFoundException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | public synchronized void write(byte[] bAr) { 28 | LOG.entering(TableFile.name, "write", bAr); 29 | //LOG.finest(LedTable_Util.bArToString(bAr)); 30 | //long t = System.currentTimeMillis(); 31 | 32 | if (LedTable_Settings.enableTableOutput) { 33 | try { 34 | if (fos != null) { 35 | fos.write(bAr); 36 | } 37 | Thread.sleep(10); 38 | } catch (InterruptedException | IOException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | //LOG.finest("Write Time: " + (System.currentTimeMillis() - t)); 44 | LOG.exiting(TableFile.name, "write", bAr.length + " bytes written"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/TableSPI.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.rpi.ledtable.table; 2 | 3 | import java.io.IOException; 4 | 5 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 6 | 7 | import com.pi4j.io.spi.SpiChannel; 8 | import com.pi4j.io.spi.SpiDevice; 9 | import com.pi4j.io.spi.SpiFactory; 10 | import com.pi4j.io.spi.SpiMode; 11 | 12 | public class TableSPI extends Table { 13 | private final static String name = "LedTable_SPI"; 14 | 15 | private SpiDevice spi = null; 16 | 17 | public TableSPI() throws IOException { 18 | LOG.entering(TableSPI.name, "new"); 19 | 20 | if (LedTable_Settings.enableTableOutput) 21 | spi = SpiFactory.getInstance(SpiChannel.CS0, LedTable_Settings.spiSpeed, SpiMode.MODE_0); 22 | 23 | LOG.exiting(TableSPI.name, "new"); 24 | } 25 | 26 | public synchronized void write(byte[] bAr) { 27 | LOG.entering(TableSPI.name, "write", bAr); 28 | //LOG.finest(LedTable_Util.bArToString(bAr)); 29 | //long t = System.currentTimeMillis(); 30 | super.write(bAr); 31 | 32 | if (LedTable_Settings.enableTableOutput) { 33 | try { 34 | spi.write(bAr); 35 | Thread.sleep(10); 36 | } catch (IOException | InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | //LOG.finest("Write Time: " + (System.currentTimeMillis() - t)); 42 | LOG.exiting(TableSPI.name, "write", bAr.length + " bytes written"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/TableSerial.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.table; 5 | 6 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 7 | 8 | import com.pi4j.io.serial.Serial; 9 | import com.pi4j.io.serial.SerialDataEvent; 10 | import com.pi4j.io.serial.SerialDataListener; 11 | import com.pi4j.io.serial.SerialFactory; 12 | import com.pi4j.io.serial.SerialPortException; 13 | 14 | /** 15 | * @author Mikel 16 | * 17 | */ 18 | public class TableSerial extends Table { 19 | private final static String name = "TableSerial"; 20 | private SerialDataListener sdl = null; 21 | 22 | public final Serial serial; 23 | private boolean connected = false; 24 | private String comPort = ""; 25 | private int baud = 57600; 26 | 27 | public TableSerial() { 28 | super(); 29 | serial = SerialFactory.createInstance(); 30 | 31 | this.comPort = LedTable_Settings.serialPort; 32 | this.baud = LedTable_Settings.serialBaud; 33 | 34 | sdl = new SerialDataListener() { 35 | @Override 36 | public void dataReceived(SerialDataEvent event) { 37 | // print out the data received to the console 38 | LOG.info(event.getData()); 39 | } 40 | }; 41 | 42 | serial.addListener(sdl); 43 | 44 | this.connect(); 45 | } 46 | 47 | public synchronized void write(byte[] bAr) { 48 | LOG.entering(name, "write", bAr); 49 | super.write(bAr); 50 | 51 | if (LedTable_Settings.enableTableOutput && connected) { 52 | serial.write(bAr); 53 | } 54 | 55 | //LOG.finest("Write Time: " + (System.currentTimeMillis() - t)); 56 | LOG.exiting(name, "write", bAr.length + " bytes written"); 57 | } 58 | 59 | /** 60 | * Returns true if the connection to the serial port is successful 61 | * Also returns true if the output is disabled so that debugging will work 62 | * 63 | * @return connected status 64 | */ 65 | public boolean connect() { 66 | if (LedTable_Settings.enableTableOutput) { 67 | try { 68 | // open the default serial port provided on the GPIO header 69 | serial.open(comPort, baud); 70 | Thread.sleep(1000); //connect time 71 | connected = true; 72 | return true; 73 | } 74 | catch(InterruptedException | SerialPortException e) { 75 | System.out.println("Exception in Serial: " + e); 76 | connected = false; 77 | return false; 78 | } 79 | } 80 | return connected; 81 | } 82 | 83 | public void disconnect() { 84 | serial.close(); 85 | } 86 | 87 | public boolean isConnected() { 88 | return connected; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/table/WriteListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.table; 5 | 6 | /** 7 | * @author Mikel 8 | * 9 | */ 10 | public interface WriteListener { 11 | public void writeEvent(byte[] bAr); 12 | } 13 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/webservice/WebserviceCommands.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.webservice; 5 | 6 | import net.mdp3.java.util.xml.DomXml; 7 | import net.mdp3.java.util.xml.XmlHelper; 8 | 9 | import org.w3c.dom.Document; 10 | import org.w3c.dom.Element; 11 | 12 | /** 13 | * @author Mikel 14 | * 15 | */ 16 | public class WebserviceCommands { 17 | 18 | public static final String WS_CMD = "cmd"; 19 | public static enum WebserviceCommand implements DomXml { 20 | COMMAND_LIST, 21 | MODE, 22 | SAVE, 23 | CURRENT_SELECTION_INFO, 24 | EFFECT_INFO, 25 | EFFECT_LIST, 26 | PLAYLIST, 27 | PLAYLIST_INFO, 28 | FILE; 29 | 30 | public static final String NODE_NAME = "Command"; 31 | public static final String NODE_CMD_NAME = "Name"; 32 | 33 | @Override 34 | public Element toXml(Document doc) { 35 | Element wsCmdE = doc.createElement(WebserviceCommand.NODE_NAME); 36 | 37 | wsCmdE.appendChild(XmlHelper.newTextElement(doc, WebserviceCommand.NODE_CMD_NAME, this.name())); 38 | 39 | return wsCmdE; 40 | } 41 | 42 | @Override 43 | public void fromXml(Element e) throws Exception { 44 | //Not Implemented 45 | throw new Exception("Not Implemented"); 46 | } 47 | } 48 | 49 | public static final String WS_MODE = "mode"; 50 | public static final String WS_OUTPUT = "output"; 51 | } -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/webservice/WebserviceFunctions.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.webservice; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.util.Map; 9 | import java.util.logging.Logger; 10 | 11 | import javax.xml.transform.TransformerException; 12 | import javax.xml.transform.TransformerFactoryConfigurationError; 13 | 14 | import org.w3c.dom.Document; 15 | import org.w3c.dom.Element; 16 | 17 | import net.mdp3.java.rpi.ledtable.LedTable; 18 | import net.mdp3.java.rpi.ledtable.LedTable_Selection; 19 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 20 | import net.mdp3.java.rpi.ledtable.effects.EffectMode; 21 | import net.mdp3.java.rpi.ledtable.webservice.WebserviceCommands.WebserviceCommand; 22 | import net.mdp3.java.util.file.SimpleFileIO; 23 | import net.mdp3.java.util.xml.XmlHelper; 24 | 25 | /** 26 | * @author Mikel 27 | * 28 | */ 29 | public class WebserviceFunctions { 30 | private final static Logger LOG = Logger.getLogger(WebserviceFunctions.class.getName()); 31 | private final static String name = "WebserviceFunctions"; 32 | 33 | private static LedTable table = null; 34 | 35 | private final static String DEFAULT_WEB_FILE = "LedTable.html"; 36 | private final static String WEB_FOLDER = "www"; 37 | 38 | /** 39 | * Set the ledTable for the methods to use, this must be called before 40 | * running the parseParams method 41 | * 42 | * @param t 43 | */ 44 | protected static void setLedTable(LedTable t) { 45 | table = t; 46 | } 47 | 48 | /** 49 | * Before calling this function, the LedTable must be set using the 50 | * setLedTable method 51 | * 52 | * @param params 53 | * @return 54 | * @throws Exception 55 | */ 56 | protected static String parseParams(Map params) throws Exception { 57 | LOG.entering(name, "parseParams"); 58 | 59 | if (table == null) throw new Exception("Table not Initialized"); 60 | 61 | String ret = ""; 62 | 63 | //read mode parameter 64 | WebserviceCommand wsCmd = loadCmd(params); 65 | 66 | if (wsCmd != null) { 67 | ret = processCmd(wsCmd, params); 68 | } 69 | 70 | LOG.exiting(name, "parseParams", "ret: " + ret); 71 | return ret; 72 | } 73 | 74 | private static WebserviceCommand loadCmd(Map params) { 75 | //read mode parameter 76 | WebserviceCommand wsCmd = null; 77 | String cmdStr = params.get(WebserviceCommands.WS_CMD); 78 | if (cmdStr != null && cmdStr.length() > 0) { 79 | try { 80 | wsCmd = WebserviceCommand.valueOf(cmdStr.toUpperCase().trim()); 81 | } catch (Exception e) { 82 | LOG.severe("Error Invalid Command: " + cmdStr + " " + e); 83 | 84 | return null; 85 | } 86 | } 87 | 88 | return wsCmd; 89 | } 90 | 91 | private static String processCmd(WebserviceCommand wsCmd, Map params) { 92 | String ret = ""; 93 | 94 | if (wsCmd == WebserviceCommand.MODE) { 95 | ret = processCmdMode(params); 96 | } else if (wsCmd == WebserviceCommand.SAVE) { 97 | ret = processCmdSave(params); 98 | } else if (wsCmd == WebserviceCommand.CURRENT_SELECTION_INFO) { 99 | ret = processCurSelectionInfo(params); 100 | } else if (wsCmd == WebserviceCommand.EFFECT_LIST) { 101 | ret = processCmdEffectList(params); 102 | } else if (wsCmd == WebserviceCommand.COMMAND_LIST) { 103 | ret = processCmdCommandList(); 104 | } else if (wsCmd == WebserviceCommand.FILE) { 105 | ret = processCmdFile(params); 106 | } else if (wsCmd == WebserviceCommand.EFFECT_INFO) { 107 | ret = processEffectInfo(params); 108 | } else if (wsCmd == WebserviceCommand.PLAYLIST_INFO) { 109 | ret = processPlaylistInfo(params); 110 | } 111 | 112 | return ret; 113 | } 114 | 115 | private static String processCmdMode(Map params) { 116 | String ret = ""; 117 | 118 | try { 119 | EffectMode mode = EffectMode.valueOf(params.get(WebserviceCommands.WS_MODE)); 120 | ret += table.newSelection(new LedTable_Selection(mode, params)); 121 | ret = "OK"; 122 | } catch (Exception e) { 123 | e.printStackTrace(); 124 | LOG.severe("Invalid Mode\n" + e.getMessage()); 125 | ret = "Invalid Mode\n" + e.getMessage(); 126 | } 127 | 128 | return ret; 129 | } 130 | 131 | private static String processCmdSave(Map params) { 132 | String ret = ""; 133 | ret += "LedTable
\n"; 134 | ret += "OK"; 135 | 136 | try { 137 | table.saveSelection(); 138 | ret = "Selection Saved"; 139 | } catch (Exception e) { 140 | System.err.println("Error Saving Selection"); 141 | ret = "Error Saving Selection\n" + e.getMessage(); 142 | 143 | e.printStackTrace(); 144 | } 145 | 146 | return ret; 147 | } 148 | 149 | private static String processCurSelectionInfo(Map params) { 150 | String ret = ""; 151 | 152 | Document doc = XmlHelper.getNewDoc(); 153 | try { 154 | ret += "\n" + XmlHelper.elementToString(table.getCurrentSelection().toXml(doc)); 155 | } catch (TransformerFactoryConfigurationError 156 | | TransformerException e) { 157 | e.printStackTrace(); 158 | LOG.severe("Error Converting current selection to XML: " + e); 159 | } 160 | 161 | ret = removeFormatting(ret); 162 | 163 | return ret; 164 | } 165 | 166 | private static String processEffectInfo(Map params) { 167 | String ret = ""; 168 | 169 | Document doc = XmlHelper.getNewDoc(); 170 | try { 171 | ret += "\n" + XmlHelper.elementToString(table.getEffect().getEffectInfo().toXml(doc)); 172 | } catch (TransformerFactoryConfigurationError 173 | | TransformerException e) { 174 | e.printStackTrace(); 175 | LOG.severe("Error Converting current selection to XML: " + e); 176 | } 177 | 178 | ret = removeFormatting(ret); 179 | 180 | return ret; 181 | } 182 | 183 | private static String processCmdEffectList(Map params) { 184 | String ret = ""; 185 | 186 | Document doc = XmlHelper.getNewDoc(); 187 | Element rootElement = doc.createElement("EffectList"); 188 | doc.appendChild(rootElement); 189 | 190 | for (EffectMode em : EffectMode.values()) 191 | rootElement.appendChild(em.toXml(doc)); 192 | 193 | try { 194 | ret = XmlHelper.elementToString(rootElement); 195 | } catch (TransformerFactoryConfigurationError | TransformerException e) { 196 | e.printStackTrace(); 197 | LOG.severe("Error Creating Effect List: " + e); 198 | } 199 | 200 | ret = removeFormatting(ret); 201 | 202 | return ret; 203 | } 204 | 205 | private static String processCmdCommandList() { 206 | String ret = ""; 207 | 208 | Document doc = XmlHelper.getNewDoc(); 209 | Element rootElement = doc.createElement("CommandList"); 210 | doc.appendChild(rootElement); 211 | 212 | for (WebserviceCommand ws : WebserviceCommand.values()) 213 | rootElement.appendChild(ws.toXml(doc)); 214 | 215 | try { 216 | ret = XmlHelper.elementToString(rootElement); 217 | } catch (TransformerFactoryConfigurationError | TransformerException e) { 218 | e.printStackTrace(); 219 | LOG.severe("Error Creating Command List: " + e); 220 | } 221 | 222 | return ret; 223 | } 224 | 225 | private static String processCmdFile(Map params) { 226 | String fileName = ""; 227 | 228 | if (params.get("fileName") != null) 229 | fileName = params.get("fileName").toString(); 230 | else if (params.get("file") != null) 231 | fileName = params.get("file").toString(); 232 | 233 | return serveFiles(fileName); 234 | } 235 | 236 | protected static String serveFiles() { 237 | return serveFiles(""); 238 | } 239 | 240 | protected static String serveFiles(String fileName) { 241 | String ret = ""; 242 | if (fileName == null || fileName == "") { 243 | try { 244 | //TODO improve landing page, maybe change html file to just header and try to generate content 245 | File f = new File(WEB_FOLDER + "/" + DEFAULT_WEB_FILE); 246 | ret = SimpleFileIO.loadFileToString(f); 247 | } catch (FileNotFoundException e) { 248 | e.printStackTrace(); 249 | } 250 | } else { 251 | if (fileName.contains("..")) return "Invalid Filename Sequence: .."; 252 | try { 253 | File f = new File(WEB_FOLDER + "/" + fileName); 254 | ret = SimpleFileIO.loadFileToString(f); 255 | } catch (FileNotFoundException e) { 256 | e.printStackTrace(); 257 | LOG.severe("File Not Found: " + e); 258 | 259 | ret = "Error File Not Found"; 260 | } 261 | } 262 | 263 | return ret; 264 | } 265 | 266 | private static String removeFormatting(String s) { 267 | //Remove xml formatting 268 | s = s.replaceAll("\r", ""); 269 | s = s.replaceAll("\n", ""); 270 | s = s.replaceAll("\t", ""); 271 | 272 | return s; 273 | } 274 | 275 | private static String processPlaylistInfo(Map params) { 276 | String ret = ""; 277 | 278 | if (table.getCurrentPlaylist().isPlaying()) { 279 | ret = "PLAYING"; 280 | } else ret = "STOPPED"; 281 | 282 | return ret; 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/rpi/ledtable/webservice/WebserviceHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.rpi.ledtable.webservice; 5 | 6 | import java.io.IOException; 7 | import java.net.BindException; 8 | import java.util.Map; 9 | import java.util.logging.Logger; 10 | 11 | import net.mdp3.java.rpi.ledtable.LedTable; 12 | import net.mdp3.java.rpi.ledtable.LedTable_Settings; 13 | import net.mdp3.java.util.webservice.Webservice; 14 | import net.mdp3.java.util.webservice.WebserviceListener; 15 | 16 | /** 17 | * @author Mikel 18 | * 19 | */ 20 | public class WebserviceHandler implements WebserviceListener { 21 | private final static Logger LOG = Logger.getLogger(WebserviceHandler.class.getName()); 22 | private final static String name = "WebserviceHandler"; 23 | 24 | Webservice ws; 25 | 26 | public WebserviceHandler(LedTable table, int port, String name) { 27 | WebserviceFunctions.setLedTable(table); 28 | 29 | boolean started = false; 30 | try { 31 | ws = new Webservice(port, name, this); 32 | started = true; 33 | } catch (BindException e) { 34 | System.out.println("Error opening port: " + port); 35 | } catch (IOException e) { 36 | System.out.println("Error starting webservice: " + e); 37 | e.printStackTrace(); 38 | } 39 | 40 | if (LedTable_Settings.debug && started) System.out.println("Webservice started on port: " + port + " for Context: " + name); 41 | } 42 | 43 | 44 | @Override 45 | public String wsAccess(Map params) { 46 | LOG.entering(name, "wsAccess", "params: " + params); 47 | 48 | String returnValue = ""; 49 | 50 | //Parameters are send, so send back link to homepage and process the params 51 | if (params.size() > 0) { 52 | try { 53 | returnValue += WebserviceFunctions.parseParams(params); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | LOG.severe("Error in Webservice: " + e); 57 | } 58 | } else { //No parameters sent so send landing page 59 | returnValue += WebserviceFunctions.serveFiles(); 60 | } 61 | 62 | LOG.exiting(name, "wsAccess", "returnValue: " + returnValue); 63 | return returnValue; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/console/ConsoleBatch.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.console; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Console Command Batch Process 10 | * 11 | * This class spawns a new thread to run the commands passed in to the batch 12 | * List and runs them with the specified delay in between each. This process 13 | * can be set to loop for continuous looping. Commands are not run against the 14 | * system shell, but are run against the ConsoleReader object which uses 15 | * Reflection to run methods on the object passed in. 16 | * 17 | * This class allows for an object to be set up with methods, and allows for a 18 | * text file list of methods to be run against it automatically. This can be 19 | * used to automate a configurable setup for a program and other things. 20 | * 21 | * @author Mikel 22 | * 23 | */ 24 | public class ConsoleBatch extends Thread { 25 | private ConsoleReader consoleHandler; 26 | private List batch; 27 | private boolean run = false; 28 | private int commandIndex = 0; 29 | private boolean looping = false; 30 | 31 | public ConsoleBatch(ConsoleReader cr, List v) { 32 | this.consoleHandler = cr; 33 | this.batch = v; 34 | } 35 | 36 | public void run() { 37 | while(run) { 38 | if (this.commandIndex >= batch.size() && this.looping) this.commandIndex = 0; 39 | else if (this.commandIndex >= batch.size()) { 40 | run = false; 41 | return; 42 | } 43 | 44 | String command = batch.get(this.commandIndex).getCommand(); 45 | System.out.println("Batch Command: " + command); 46 | try { 47 | this.consoleHandler.parseInput(command); 48 | } catch (Exception e1) { 49 | e1.printStackTrace(); 50 | System.out.println("Error in command batch with command " + command + "\n" + e1); 51 | } 52 | 53 | try { 54 | Thread.sleep(batch.get(this.commandIndex).getDelay()); 55 | } catch (InterruptedException e) { 56 | System.out.println("Error sleeping Command Batch " + e); 57 | e.printStackTrace(); 58 | } 59 | this.commandIndex++; 60 | } 61 | } 62 | 63 | public void startBatch() { 64 | if (batch.size() > 0 && !run) { 65 | run = true; 66 | this.start(); 67 | } 68 | } 69 | 70 | public void stopBatch() { 71 | run = false; 72 | } 73 | 74 | public void setLooping(boolean b) { 75 | this.looping = b; 76 | } 77 | 78 | public boolean isRunning() { 79 | return run; 80 | } 81 | } 82 | 83 | class ConsoleCommand { 84 | private String command = ""; 85 | private long waitTime = 100; 86 | 87 | public ConsoleCommand(String c, long l) { 88 | this.command = c; 89 | this.waitTime = l; 90 | } 91 | 92 | public String getCommand() { 93 | return this.command; 94 | } 95 | 96 | public long getDelay() { 97 | return this.waitTime; 98 | } 99 | } -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/console/ConsoleReader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.console; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.InputStreamReader; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Modifier; 13 | import java.util.ArrayList; 14 | import java.util.Scanner; 15 | import java.util.SortedSet; 16 | import java.util.TreeSet; 17 | 18 | /** 19 | * ConsoleReader class easily adds a threaded BufferedInput Console reader to a 20 | * Java app, to enable simple call backs to methods on the implementing object. 21 | * 22 | * All methods used by the lookups should implement all Strings in the parameter 23 | * list and do type conversion within the callback methods. 24 | * 25 | * Example: 26 | * 27 | * For some object o with methods: 28 | * 29 | * ConsoleReader cr = new ConsoleReader("App Name", o); 30 | * 31 | * Will instantiate and start an instance of the ConsoleReader which will call 32 | * back to methods on o when the method names and parameter counts match, 33 | * parameter types are unchecked and should all be String. 34 | * 35 | * @author Mikel Duke 36 | */ 37 | public class ConsoleReader extends Thread { 38 | 39 | private BufferedReader br; 40 | private boolean run = true; 41 | private String name = ""; 42 | private Object o; 43 | private ConsoleBatch consoleBatch = null; 44 | 45 | /** 46 | * Creates a new console reader that can call methods in Object o and will 47 | * print name to the console before each command. 48 | * 49 | * Automatically launches console command input thread 50 | * 51 | * @param name 52 | * @param o 53 | */ 54 | public ConsoleReader(String name, Object o) { 55 | this(name, o, true); 56 | } 57 | 58 | /** 59 | * Creates a new console reader that can call methods in Object o and will 60 | * print name to the console before each command. 61 | * 62 | * @param name 63 | * @param o 64 | * @param startThread true to start the console input thread 65 | */ 66 | public ConsoleReader(String name, Object o, boolean startThread) { 67 | this.name = name; 68 | this.o = o; 69 | if (startThread) this.start(); 70 | } 71 | 72 | /** 73 | * Run is the threaded method required when extending Thread. It outputs 74 | * the Name set in the constructor and waits for console input. 75 | */ 76 | public void run() { 77 | br = new BufferedReader(new InputStreamReader(System.in)); 78 | 79 | try { 80 | while (run) { 81 | System.out.print(name + ": "); 82 | parseInput(br.readLine()); 83 | } 84 | } 85 | catch (Exception e) { 86 | System.out.println("Error in " + name + " Thread: " + e); 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | /** 92 | * parseInput handles the keyboard console input. It looks up the input 93 | * string to check for matching methods on object o. 94 | * 95 | * Note: Parameters should be separated by a space character, and extra 96 | * parameters are ignored. 97 | * 98 | * @param input 99 | * @throws InvocationTargetException 100 | * @throws IllegalArgumentException 101 | * @throws IllegalAccessException 102 | */ 103 | protected boolean parseInput(String input) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 104 | Method methods[] = o.getClass().getMethods(); 105 | Object args[] = null; 106 | 107 | String inputAr[] = input.split(" "); 108 | if (inputAr.length == 0) return false; 109 | 110 | for (int i = 0; i < methods.length; i++) { 111 | //find matching public method of same name 112 | if (methods[i].getName().equalsIgnoreCase(inputAr[0]) 113 | && methods[i].getModifiers() == Modifier.PUBLIC) { 114 | Class params[] = methods[i].getParameterTypes(); 115 | if (params.length == 0) { 116 | args = null; 117 | } else if (inputAr.length >= params.length + 1) { 118 | args = new Object[params.length]; 119 | for (int j = 0; j < params.length; j++) { 120 | args[j] = inputAr[j+1]; 121 | } 122 | if (inputAr.length + 1 > params.length) { 123 | //combine extra params to last one 124 | for (int j = params.length; j < inputAr.length - 1; j++) { 125 | String s = ((String) args[args.length - 1]); 126 | s += " " + inputAr[j + 1]; 127 | args[args.length - 1] = s; 128 | } 129 | } 130 | } else { 131 | System.out.println("Error: Not Enough Arguments"); 132 | return false; 133 | } 134 | methods[i].invoke(o, args); 135 | return true; 136 | } 137 | } 138 | 139 | //default implementations for common methods, these items don't get 140 | //called if already implemented in object o 141 | if (input.equalsIgnoreCase("help")) { 142 | showDefaultHelp(); 143 | return true; 144 | } else if (inputAr[0].equalsIgnoreCase("openBatch") && inputAr.length == 2) { 145 | openBatch(inputAr[1]); 146 | return true; 147 | } else if (inputAr[0].equalsIgnoreCase("startBatch")) { 148 | startBatch(); 149 | return true; 150 | } else if (inputAr[0].equalsIgnoreCase("loopBatch")) { 151 | loopBatch(); 152 | return true; 153 | } else if (inputAr[0].equalsIgnoreCase("stopBatch")) { 154 | stopBatch(); 155 | return true; 156 | } else if (input.equalsIgnoreCase("quit") || input.equalsIgnoreCase("exit")) { 157 | quit(); 158 | return true; 159 | } else { 160 | System.out.println("Invalid Command"); 161 | return false; 162 | } 163 | } 164 | 165 | /** 166 | * Default quit implementation to stop the thread and close the ConsoleReader. 167 | * 168 | * If this method is implemented in o, it should call back to this method to 169 | * stop the ConsoleReader thread correctly. 170 | */ 171 | public void quit() { 172 | run = false; 173 | } 174 | 175 | /** 176 | * Default help implementation. This method will not be used if a help 177 | * method is implemented in object o. 178 | * 179 | * This method will output a sorted list of public method names on object o 180 | * with the parameter count. 181 | */ 182 | private void showDefaultHelp() { 183 | Method methods[] = o.getClass().getMethods(); 184 | SortedSet methodNames = new TreeSet(); 185 | 186 | for (int i = 0; i < methods.length; i++) { 187 | if (methods[i].getModifiers() == Modifier.PUBLIC) { 188 | Class params[] = methods[i].getParameterTypes(); 189 | String str = methods[i].getName(); 190 | if (!(str.equalsIgnoreCase("toString") || str.equalsIgnoreCase("equals"))) 191 | methodNames.add(str + " " + params.length); 192 | } 193 | } 194 | 195 | if (!methodNames.isEmpty()) { 196 | Object methodNamesAr[] = methodNames.toArray(); 197 | for (int i = 0; i < methodNamesAr.length; i++) 198 | System.out.println((String)methodNamesAr[i]); 199 | } 200 | } 201 | 202 | /** 203 | * Opens a new command batch process using the commands in fileName 204 | * 205 | * @param fileName 206 | */ 207 | public void openBatch(String fileName) { 208 | File file = new File(fileName); 209 | this.openBatch(file); 210 | } 211 | 212 | /** 213 | * Opens a new command batch process using the commands in fileName 214 | * 215 | * @param file 216 | */ 217 | public void openBatch(File file) { 218 | ArrayList commandList = new ArrayList(); 219 | String command = ""; 220 | long delay = 100; 221 | String input = ""; 222 | 223 | try { 224 | Scanner sc = new Scanner(file); 225 | while (sc.hasNext()) input += sc.nextLine() + "\n"; 226 | sc.close(); 227 | } catch (FileNotFoundException e) { 228 | System.out.println("Settings File Not Found"); 229 | //e.printStackTrace(); 230 | } 231 | 232 | if (!input.equals("")) { 233 | String line[] = input.split("\n"); 234 | for (int i = 0; i < line.length; i++) { 235 | if (line[i].length() < 1) continue; 236 | if (line[i].charAt(0) == '#') { 237 | continue; 238 | } else if (line[i].toLowerCase().contains("batch")) { 239 | continue; 240 | } 241 | 242 | String parts[] = line[i].split(" "); 243 | if (parts.length < 2) { 244 | delay = 100; 245 | command = line[i]; 246 | } else try { 247 | Long l = Long.parseLong(parts[parts.length - 1]); 248 | delay = l.longValue(); 249 | 250 | command = ""; 251 | for (int j = 0; j < parts.length - 1; j++) { 252 | command += parts[j]; 253 | } 254 | } catch (NumberFormatException e) { 255 | delay = 100; 256 | command = line[i]; 257 | } 258 | 259 | commandList.add(new ConsoleCommand(command, delay)); 260 | } 261 | } 262 | 263 | if (commandList.size() > 0) { 264 | this.consoleBatch = new ConsoleBatch(this, commandList); 265 | } else { 266 | System.out.println("No Commands Loaded"); 267 | } 268 | } 269 | 270 | /** 271 | * If a console batch process has been opened, this starts it 272 | */ 273 | public void startBatch() { 274 | if (this.consoleBatch != null) { 275 | this.consoleBatch.startBatch(); 276 | } 277 | } 278 | 279 | /** 280 | * Sets the batch process mode loop parameter 281 | */ 282 | public void loopBatch() { 283 | if (this.consoleBatch != null) { 284 | this.consoleBatch.setLooping(true); 285 | this.consoleBatch.startBatch(); 286 | } 287 | } 288 | 289 | /** 290 | * If a patch process has been opened, then stop it 291 | */ 292 | public void stopBatch() { 293 | if (this.consoleBatch != null) { 294 | this.consoleBatch.stopBatch(); 295 | } 296 | } 297 | 298 | /** 299 | * Returns the command batch running state 300 | * @return 301 | */ 302 | public boolean isBatchRunning() { 303 | if (this.consoleBatch != null) { 304 | return this.consoleBatch.isRunning(); 305 | } else { 306 | return false; 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/console/ConsoleUtil.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.console; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.List; 7 | 8 | /** 9 | * Class to hold Util functions for doing things in console mode in an app 10 | * 11 | * 12 | * @author Mikel 13 | * 14 | */ 15 | public class ConsoleUtil { 16 | private static Process p; 17 | 18 | /** 19 | * Runs the specified cmd string as a shell command, if wait = true, then 20 | * this method will block until the command is finished 21 | * 22 | * @param cmd 23 | * @param wait 24 | * @return 25 | * @throws IOException 26 | * @throws InterruptedException 27 | */ 28 | public static String execute(String cmd, boolean wait) throws IOException, InterruptedException { 29 | return execute(new String[]{ cmd }, wait); 30 | } 31 | 32 | /** 33 | * Combines the string array into a command and runs it as a shell command, 34 | * if wait = true then this method will block 35 | * 36 | * @param cmd 37 | * @param wait 38 | * @return 39 | * @throws IOException 40 | * @throws InterruptedException 41 | */ 42 | public static String execute(String cmd[], boolean wait) throws IOException, InterruptedException { 43 | StringBuffer output = new StringBuffer(); 44 | p = Runtime.getRuntime().exec(cmd); 45 | if (wait) { 46 | p.waitFor(); 47 | 48 | BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 49 | String line = ""; 50 | while ((line = reader.readLine())!= null) { 51 | output.append(line + "\n"); 52 | } 53 | 54 | return output.toString(); 55 | } else return ""; 56 | } 57 | 58 | /** 59 | * Returns true if any String item in the argList starts with the 60 | * argName parameter. This is useful to check for the presence of 61 | * a specific command like argument. 62 | * 63 | * @param argList 64 | * @param argName 65 | * @return 66 | */ 67 | public static boolean hasArg(List argList, String argName) { 68 | return hasArg(argList, argName, ""); 69 | } 70 | 71 | /** 72 | * Returns true if any String item in the argList starts with the 73 | * argName parameter. This is useful to check for the presence of 74 | * a specific command like argument. This method also allows for the 75 | * delimeter to be specified which gets appended to the argName, 76 | * ie to search for --file=blah then = is the delim. 77 | * 78 | * @param argList 79 | * @param argName 80 | * @param delim 81 | * @return 82 | */ 83 | public static boolean hasArg(List argList, String argName, String delim) { 84 | for (int i = 0; i < argList.size(); i++) { 85 | if (argList.get(i).startsWith(argName + delim)) return true; 86 | } 87 | 88 | return false; 89 | } 90 | 91 | /** 92 | * Returns the first item in the argList that starts with the string 93 | * argName not including the arg. 94 | * 95 | * @param argList 96 | * @param argName 97 | * @return 98 | */ 99 | public static String getArgStartsWith(List argList, String argName) { 100 | return getArgStartsWith(argList, argName, ""); 101 | } 102 | 103 | /** 104 | * Returns the first item in the argList that starts with the String 105 | * argName + delim, not including the arg. 106 | * 107 | * Example: If argList contains --file=blah, then if using 108 | * argName:--file and delim:= would return blah. 109 | * 110 | * @param argList 111 | * @param argName 112 | * @param delim 113 | * @return 114 | */ 115 | public static String getArgStartsWith(List argList, String argName, String delim) { 116 | String ret = ""; 117 | 118 | for (int i = 0; i < argList.size(); i++) { 119 | if (argList.get(i).startsWith(argName + delim)) { 120 | String arg = argList.get(i); 121 | return arg.substring(argName.length() + delim.length(), arg.length()); 122 | } 123 | } 124 | 125 | return ret; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/file/FileNameFormatter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.file; 5 | 6 | import java.text.DateFormat; 7 | import java.text.SimpleDateFormat; 8 | import java.util.Date; 9 | 10 | /** 11 | * @author Mikel 12 | * 13 | */ 14 | public class FileNameFormatter { 15 | 16 | /** 17 | * Common function to get the date string back in a format I like 18 | * 19 | * Example: 20151021153304 20 | * 21 | * @return Date/Time as yyyyMMddHHmmss 22 | */ 23 | public static String getDateString() { 24 | String ret = ""; 25 | 26 | DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 27 | Date date = new Date(); 28 | ret += dateFormat.format(date); 29 | 30 | return ret; 31 | } 32 | 33 | /** 34 | * Returns a Dated file name using the specified prefix and extension with 35 | * the separator after the prefix and before the date 36 | * 37 | * Example: prefix-20151021132402.txt 38 | * 39 | * @param prefix 40 | * @param separator 41 | * @param extension Not including the . 42 | * @return 43 | */ 44 | public static String getDatedFileName(String prefix, String separator, String extension) { 45 | String ret = ""; 46 | 47 | ret += prefix; 48 | ret += separator; 49 | ret += FileNameFormatter.getDateString(); 50 | ret += '.'; 51 | ret += extension; 52 | 53 | return ret; 54 | } 55 | 56 | /** 57 | * Returns a Dated file name using the specified prefix and extension with 58 | * a - after the prefix and before the date 59 | * 60 | * Example: prefix-20151021132402.txt 61 | * 62 | * @param prefix 63 | * @param extension Not including the . 64 | * @return 65 | */ 66 | public static String getDatedFileName(String prefix, String extension) { 67 | return FileNameFormatter.getDatedFileName(prefix, "-", extension); 68 | } 69 | 70 | public static String getExtension(String fileName) { 71 | String ret = ""; 72 | 73 | int lastDot = fileName.lastIndexOf("."); 74 | 75 | if (lastDot < fileName.length()) 76 | ret = fileName.substring(lastDot + 1, fileName.length()); 77 | 78 | return ret; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/file/SimpleFileIO.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.file; 5 | 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.util.Scanner; 12 | 13 | /** 14 | * @author Mikel 15 | * 16 | */ 17 | public class SimpleFileIO { 18 | 19 | public static void writeStringToFile(String fileName, String s) throws IOException { 20 | writeStringToFile(new File(fileName), s); 21 | } 22 | 23 | public static void writeStringToFile(File file, String s) throws IOException { 24 | BufferedWriter bw = null; 25 | 26 | bw = new BufferedWriter(new FileWriter(file)); 27 | bw.write(s); 28 | bw.close(); 29 | } 30 | 31 | public static String loadFileToString(String fileName) throws FileNotFoundException { 32 | return loadFileToString(new File(fileName)); 33 | } 34 | 35 | public static String loadFileToString(File file) throws FileNotFoundException { 36 | StringBuilder sb = new StringBuilder(); 37 | Scanner sc = new Scanner(file); 38 | 39 | while (sc.hasNext()) { 40 | sb.append(sc.nextLine()).append("\n"); 41 | } 42 | sc.close(); 43 | 44 | return sb.toString(); 45 | } 46 | 47 | public static void appendStringToFile(String fileName, String s) throws IOException, FileNotFoundException { 48 | appendStringToFile(new File(fileName), s); 49 | } 50 | 51 | public static void appendStringToFile(File file, String s) throws IOException, FileNotFoundException { 52 | String fileContents = loadFileToString(file); 53 | 54 | if (!fileContents.endsWith("\n")) fileContents += "\n"; 55 | fileContents += s; 56 | 57 | writeStringToFile(file, fileContents); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/gui/MenuBarHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.gui; 5 | 6 | import java.awt.event.ActionListener; 7 | 8 | import javax.swing.JMenu; 9 | import javax.swing.JMenuBar; 10 | import javax.swing.JMenuItem; 11 | 12 | /** 13 | * @author Mikel 14 | * 15 | * Class to help with adding Menu Items and Menu Bar options to a menu 16 | * 17 | */ 18 | public class MenuBarHelper { 19 | /** 20 | * Initializes a JMenu choice and adds it to the menu bar 21 | * 22 | * @param menu 23 | * @param menuOption 24 | * @param optionName 25 | * @param optionMnemonic 26 | * @param desc 27 | */ 28 | public static JMenu addNewMenuOption(JMenuBar menu, String optionName, int optionMnemonic, String desc) { 29 | JMenu menuOption = new JMenu(optionName); 30 | 31 | if (optionMnemonic != 0) 32 | menuOption.setMnemonic(optionMnemonic); 33 | 34 | if (desc != null && !desc.equals("")) 35 | menuOption.getAccessibleContext().setAccessibleDescription(desc); 36 | 37 | if (menu != null) menu.add(menuOption); 38 | 39 | return menuOption; 40 | } 41 | 42 | /** 43 | * Initializes a JMenu choice and adds it to the menu bar 44 | * 45 | * @param menu 46 | * @param optionName 47 | * @return 48 | */ 49 | public static JMenu addNewMenuOption(JMenuBar menu, String optionName) { 50 | return MenuBarHelper.addNewMenuOption(menu, optionName, 0, optionName); 51 | } 52 | 53 | /** 54 | * Initializes and adds a new menu item to the menu option on the menu bar 55 | * 56 | * @param menuOption 57 | * @param newItem 58 | * @param itemName 59 | * @param itemShortcut 60 | * @param itemDesc 61 | * @param actionListener 62 | */ 63 | public static JMenuItem addNewMenuItem(JMenu menuOption, String itemName, int itemShortcut, String itemDesc, ActionListener actionListener) { 64 | JMenuItem newItem = null; 65 | 66 | if (itemShortcut != 0) 67 | newItem = new JMenuItem(itemName, itemShortcut); 68 | else newItem = new JMenuItem(itemName); 69 | 70 | //quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK)); 71 | 72 | if (itemDesc != null && !itemDesc.equals("")) 73 | newItem.getAccessibleContext().setAccessibleDescription(itemDesc); 74 | 75 | if (actionListener != null) 76 | newItem.addActionListener(actionListener); 77 | 78 | if (menuOption != null) menuOption.add(newItem); 79 | 80 | return newItem; 81 | } 82 | 83 | /** 84 | * Initializes and adds a new menu item to the menu option on the menu bar 85 | * 86 | * @param menuOption 87 | * @param itemName 88 | * @param actionListener 89 | * @return 90 | */ 91 | public static JMenuItem addNewMenuItem(JMenu menuOption, String itemName, ActionListener actionListener) { 92 | return MenuBarHelper.addNewMenuItem(menuOption, itemName, 0, itemName, actionListener); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/misc/MapUtil.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.misc; 2 | 3 | import java.util.Collections; 4 | import java.util.Comparator; 5 | import java.util.LinkedHashMap; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class MapUtil 11 | { 12 | public static > Map sortByValue( Map map ) 13 | { 14 | List> list = 15 | new LinkedList>( map.entrySet() ); 16 | Collections.sort( list, new Comparator>() 17 | { 18 | public int compare( Map.Entry o1, Map.Entry o2 ) 19 | { 20 | return (o1.getValue()).compareTo( o2.getValue() ); 21 | } 22 | } ); 23 | 24 | Map result = new LinkedHashMap(); 25 | for (Map.Entry entry : list) 26 | { 27 | result.put( entry.getKey(), entry.getValue() ); 28 | } 29 | return result; 30 | } 31 | 32 | public static String mapToMultilineString(Map map) { 33 | if (map == null) { 34 | return "Map is null"; 35 | } 36 | 37 | if (map.isEmpty()) { 38 | return "Map is empty"; 39 | } 40 | 41 | StringBuilder sb = new StringBuilder(); 42 | 43 | for (K key : map.keySet()) { 44 | sb.append(key + ": " + map.get(key)); 45 | sb.append("\n"); 46 | } 47 | 48 | return sb.toString(); 49 | } 50 | } -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/misc/ObjectNotInitializedException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.misc; 5 | 6 | /** 7 | * Custom exception to be thrown when a required object was not intialized 8 | * 9 | * @author Mikel 10 | * 11 | */ 12 | public class ObjectNotInitializedException extends Exception { 13 | 14 | private static final long serialVersionUID = 2993512881656200086L; 15 | 16 | public ObjectNotInitializedException() { 17 | super(); 18 | } 19 | 20 | /** 21 | * @param message 22 | */ 23 | public ObjectNotInitializedException(String message) { 24 | super(message); 25 | } 26 | 27 | /** 28 | * @param cause 29 | */ 30 | public ObjectNotInitializedException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | /** 35 | * @param message 36 | * @param cause 37 | */ 38 | public ObjectNotInitializedException(String message, Throwable cause) { 39 | super(message, cause); 40 | } 41 | 42 | /** 43 | * @param message 44 | * @param cause 45 | * @param enableSuppression 46 | * @param writableStackTrace 47 | */ 48 | public ObjectNotInitializedException(String message, Throwable cause, 49 | boolean enableSuppression, boolean writableStackTrace) { 50 | super(message, cause, enableSuppression, writableStackTrace); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/settings/CmdLineProperties.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.settings; 2 | 3 | import java.io.IOException; 4 | import java.io.StringReader; 5 | import java.util.Properties; 6 | 7 | public class CmdLineProperties { 8 | 9 | private CmdLineProperties() { } 10 | 11 | public static Properties toProperties(String[] args) throws IOException { 12 | Properties p = new Properties(); 13 | 14 | StringBuilder sb = new StringBuilder(); 15 | for (String arg : args) { 16 | sb.append(arg).append("\n"); 17 | } 18 | 19 | String cmdLineProps = sb.toString(); 20 | 21 | p.load(new StringReader(cmdLineProps)); 22 | 23 | return p; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/settings/Settings.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.settings; 5 | 6 | 7 | /** 8 | * @author Mikel 9 | * 10 | */ 11 | public abstract class Settings { 12 | /** 13 | * Loads the settings to the static variables using the mdp3_Util 14 | * Settings methods 15 | * 16 | * Currently hardcoded to use filename of settings.txt 17 | */ 18 | public static void loadSettings(Class clazz) { 19 | loadSettings(clazz, "settings.txt"); 20 | } 21 | 22 | /** 23 | * Loads the settings to the static variables using the mdp3_Util 24 | * Settings methods 25 | * 26 | * @param class 27 | * @param fileName 28 | */ 29 | public static void loadSettings(Class clazz, String fileName) { 30 | SettingsLoader set = new SettingsLoader(clazz, false); 31 | 32 | set.loadSettings(fileName); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/settings/SettingsLoader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.settings; 5 | 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.Modifier; 13 | import java.util.HashMap; 14 | import java.util.Iterator; 15 | import java.util.Map; 16 | import java.util.Map.Entry; 17 | import java.util.Scanner; 18 | 19 | import net.mdp3.java.util.test.SettingsTest; 20 | 21 | /** 22 | * Settings 23 | * 24 | * Java package used to make loading various settings from a text file onto an 25 | * object easier. 26 | * 27 | * To use instantiate this Settings class using either an Object or a Class 28 | * definition, depending on whether the destination class is static or not. 29 | * 30 | * After loadSettings is called with either a File object or String file name, 31 | * the class looks up properties of the class that was passed in earlier, and 32 | * attempts to load values from the text file onto it. 33 | * 34 | * Supported property types are: int, long, double, bool, and String. 35 | * 36 | * Settings Text File usage: 37 | * # or // denotes a comment line, lines beginning with these symbols are ignored 38 | * Key Value pairs should be denoted use property name: value using either : or = 39 | * Values are trimmed of whitespace 40 | * Example: 41 | * #this is an example 42 | * enableSomeSetting: true 43 | * someSettingValue = 500 44 | * 45 | * @author Mikel 46 | * @see SettingsTest.java 47 | */ 48 | public class SettingsLoader { 49 | private HashMap settingsMap = new HashMap(); 50 | private Object o = null; 51 | private Class settingsClass; 52 | @SuppressWarnings("unused") 53 | private boolean staticB = true; 54 | private boolean debug = true; 55 | private String saveDivider = ":"; 56 | 57 | public SettingsLoader(Class c) { 58 | this(c, false); 59 | } 60 | 61 | public SettingsLoader(Class c, boolean debug) { 62 | this(null, c, debug); 63 | } 64 | 65 | public SettingsLoader(Object o, boolean debug) { 66 | this(o, o.getClass(), debug); 67 | } 68 | 69 | public SettingsLoader(Object o, Class c, boolean debug) { 70 | this.o = o; 71 | this.settingsClass = c; 72 | this.debug = debug; 73 | if (o == null) staticB = false; 74 | 75 | if (debug) { 76 | System.out.println("c: " + c); 77 | System.out.println("getClass: " + c.getClass().getSimpleName()); 78 | } 79 | } 80 | 81 | public void loadSettings(String fileName) { 82 | File file = new File(fileName); 83 | loadSettings(file); 84 | } 85 | 86 | public void loadSettings(File file) { 87 | if (debug) System.out.println("loadSettings: " + file.getName()); 88 | 89 | settingsMap.clear(); 90 | 91 | try { 92 | Scanner sc = new Scanner(file); 93 | String input = ""; 94 | 95 | while (sc.hasNext()) input += sc.nextLine() + "\n"; 96 | if (debug) System.out.println(input); 97 | sc.close(); 98 | 99 | loadToHashMap(input); 100 | hashMapToObject(); 101 | } catch (FileNotFoundException e) { 102 | System.out.println("Settings File Not Found: " + file.getAbsolutePath()); 103 | //e.printStackTrace(); 104 | } 105 | } 106 | 107 | private void loadToHashMap(String str) { 108 | String line[] = str.split("\n"); 109 | for (int i = 0; i < line.length; i++) { 110 | if (line[i].length() < 1) continue; //Skip blank lines 111 | if (line[i].charAt(0) == '#') { //Skip lines starting with # 112 | if (debug) System.out.println(line[i]); 113 | continue; 114 | } 115 | if (line[i].startsWith("//")) { 116 | if (debug) System.out.println(line[i]); 117 | continue; 118 | } 119 | 120 | String sp[] = null; 121 | if (line[i].indexOf(':') > -1) 122 | sp = line[i].trim().split(":", 2); 123 | else if (line[i].indexOf('=') > -1) 124 | sp = line[i].trim().split("=", 2); 125 | else { 126 | System.out.println("Error loading line #" + i); 127 | continue; 128 | } 129 | 130 | if (sp.length < 2) continue; 131 | String key = sp[0].trim(); 132 | String val = sp[1].trim(); 133 | if (debug) System.out.println("Key: " + key + " Val: " + val); 134 | 135 | if (key.length() > 0 && val.length() > 0) { 136 | settingsMap.put(key, val); 137 | } 138 | } 139 | } 140 | 141 | private void hashMapToObject() { 142 | if (settingsMap.size() > 0) { 143 | Iterator> it = settingsMap.entrySet().iterator(); 144 | while (it.hasNext()) { 145 | Map.Entry pairs = (Map.Entry)it.next(); 146 | 147 | loadPairToObject(pairs.getKey(), pairs.getValue()); 148 | } 149 | } 150 | } 151 | 152 | /** 153 | * Currently supports parsing int, long, double, bool, and string types 154 | * @param key 155 | * @param val 156 | */ 157 | private void loadPairToObject(String key, String val) { 158 | try { 159 | Field f = settingsClass.getDeclaredField(key); 160 | f.setAccessible(true); 161 | 162 | if (debug) { 163 | System.out.println("Name: " + f.getName() + " FieldClass: " + f.getType()); 164 | } 165 | 166 | try { 167 | if (f.getType().equals(int.class)) { 168 | if (o != null && !Modifier.isStatic(f.getModifiers())) { 169 | f.setInt(o, Integer.parseInt(val)); 170 | } else if (Modifier.isStatic(f.getModifiers())) { 171 | f.setInt(null, Integer.parseInt(val)); 172 | } 173 | } else if (f.getType().equals(long.class)) { 174 | if (o != null && !Modifier.isStatic(f.getModifiers())) { 175 | f.setLong(o, Long.parseLong(val)); 176 | } else if (Modifier.isStatic(f.getModifiers())) { 177 | f.setLong(null, Long.parseLong(val)); 178 | } 179 | } else if (f.getType().equals(double.class)) { 180 | if (o != null && !Modifier.isStatic(f.getModifiers())) { 181 | f.setDouble(o, Double.parseDouble(val)); 182 | } else if (Modifier.isStatic(f.getModifiers())) { 183 | f.setDouble(null, Double.parseDouble(val)); 184 | } 185 | } else if (f.getType().equals(boolean.class)) { 186 | if (o != null && !Modifier.isStatic(f.getModifiers())) { 187 | f.setBoolean(o, val.trim().equalsIgnoreCase("true")); 188 | } else if (Modifier.isStatic(f.getModifiers())) { 189 | f.setBoolean(null, val.trim().equalsIgnoreCase("true")); 190 | } 191 | } else { 192 | if (o != null && !Modifier.isStatic(f.getModifiers())) { 193 | f.set(o, val); 194 | } else if (Modifier.isStatic(f.getModifiers())) { 195 | f.set(null, val); 196 | } 197 | } 198 | } catch (IllegalArgumentException | IllegalAccessException e) { 199 | System.out.println("Access not permitted: " + e); 200 | e.printStackTrace(); 201 | } 202 | } catch (NoSuchFieldException e) { 203 | /*System.out.println("Error No Such Field " + key + "; " + e); 204 | e.printStackTrace();*/ 205 | } catch (SecurityException e) { 206 | System.out.println("Error: Security Exception: " + e); 207 | e.printStackTrace(); 208 | } 209 | } 210 | 211 | public void saveSettings(String fileName) { 212 | saveSettings(new File(fileName)); 213 | } 214 | 215 | public void saveSettings(File file) { 216 | if (debug) System.out.println("Saving Settings to " + file.getAbsolutePath()); 217 | 218 | String outString = ""; 219 | outString += '#' + this.settingsClass.getSimpleName() + '\n'; 220 | 221 | Field fields[] = this.settingsClass.getFields(); 222 | for (int i = 0; i < fields.length; i++) { 223 | String fieldStr = getSaveString(fields[i]); 224 | if (fieldStr != "") outString += fieldStr + '\n'; 225 | } 226 | 227 | writeString(file, outString); 228 | 229 | if (debug) System.out.println("Done"); 230 | } 231 | 232 | private void writeString(File file, String s) { 233 | BufferedWriter bw = null; 234 | 235 | try { 236 | bw = new BufferedWriter(new FileWriter(file)); 237 | bw.write(s); 238 | bw.close(); 239 | } catch (IOException e) { 240 | System.out.println("Error saving file: " + e); 241 | e.printStackTrace(); 242 | } 243 | } 244 | 245 | private String getSaveString(Field f) { 246 | String retStr = ""; 247 | 248 | if (Modifier.isPublic(f.getModifiers())) { 249 | if (Modifier.isStatic(f.getModifiers())) { 250 | try { 251 | retStr += f.getName(); 252 | retStr += saveDivider + " "; 253 | retStr += f.get(this.settingsClass); 254 | } catch (IllegalArgumentException e) { 255 | System.out.println("Illegal Argument: " + e); 256 | e.printStackTrace(); 257 | } catch (IllegalAccessException e) { 258 | System.out.println("Illegal Access: " + e); 259 | e.printStackTrace(); 260 | } 261 | } else if (o != null) { 262 | try { 263 | retStr += f.getName(); 264 | retStr += saveDivider + " "; 265 | retStr += f.get(o); 266 | } catch (IllegalArgumentException e) { 267 | System.out.println("Illegal Argument: " + e); 268 | e.printStackTrace(); 269 | } catch (IllegalAccessException e) { 270 | System.out.println("Illegal Access: " + e); 271 | e.printStackTrace(); 272 | } 273 | } 274 | } 275 | return retStr; 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/string/StringUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.string; 5 | 6 | /** 7 | * @author Mikel 8 | * 9 | */ 10 | public class StringUtils { 11 | public static int tryParseInt(String str) throws Exception { 12 | int ret = 0; 13 | 14 | try { 15 | ret = Integer.parseInt(str); 16 | } catch (NumberFormatException nfe) { 17 | throw new Exception("Invalid String " + str); 18 | } 19 | 20 | return ret; 21 | } 22 | 23 | public static > String[] enumToString(Class enumData) { 24 | E[] enumAr = enumData.getEnumConstants(); 25 | String namesAr[] = new String[enumAr.length]; 26 | 27 | for (int i = 0; i < enumAr.length; i++) { 28 | namesAr[i] = enumAr[i].name(); 29 | } 30 | 31 | return namesAr; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/BatchTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.io.File; 7 | import java.net.URL; 8 | 9 | import net.mdp3.java.util.console.ConsoleReader; 10 | 11 | /** 12 | * @author Mikel 13 | * 14 | */ 15 | public class BatchTest { 16 | 17 | private ConsoleReader cr; 18 | 19 | /** 20 | * Main entry point for Util package when testing. 21 | * 22 | * @param args 23 | */ 24 | @SuppressWarnings("unused") 25 | public static void main(String[] args) { 26 | BatchTest b = new BatchTest(); 27 | } 28 | 29 | public BatchTest() { 30 | cr = new ConsoleReader("Batch", this); 31 | 32 | URL url = getClass().getResource("BatchTest.txt"); 33 | File file = new File(url.getPath()); 34 | cr.openBatch(file); 35 | cr.startBatch(); 36 | } 37 | 38 | public void consoleTest() { 39 | System.out.println("ConsoleTest!"); 40 | } 41 | 42 | public void consoleTest2(String s) { 43 | System.out.println("ConsoleTest2: " + s); 44 | } 45 | 46 | public void quit() { 47 | cr.quit(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/BatchTest.txt: -------------------------------------------------------------------------------- 1 | help 1000 2 | asdf 100 3 | asdfdsf 1000 4 | help 500 5 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/ConsoleArgumentHandlerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | 9 | import net.mdp3.java.util.console.ConsoleArgumentHandler; 10 | 11 | /** 12 | * @author Mikel 13 | * 14 | */ 15 | public class ConsoleArgumentHandlerTest { 16 | 17 | /** 18 | * 19 | */ 20 | public ConsoleArgumentHandlerTest() { 21 | 22 | } 23 | 24 | public void method1() { 25 | System.out.println("run method 1"); 26 | } 27 | 28 | public void method2(String value) { 29 | System.out.println("run method 2: " + value); 30 | } 31 | 32 | public void setTest1() { 33 | System.out.println("setTest1 test"); 34 | } 35 | 36 | public void setTest2(String t) { 37 | System.out.println("setTest2 test " + t); 38 | } 39 | 40 | public void setATest3() { 41 | System.out.println("setATest3"); 42 | } 43 | 44 | public void setTest4(Object o) { 45 | System.out.println("setTest4"); 46 | } 47 | 48 | /** 49 | * @param args 50 | */ 51 | public static void main(String[] args) { 52 | System.out.println("ConsoleArgumentHandler Test Start"); 53 | ConsoleArgumentHandlerTest caht = new ConsoleArgumentHandlerTest(); 54 | ConsoleArgumentHandler cah = new ConsoleArgumentHandler(caht, args); 55 | 56 | HashMap map = new HashMap(); 57 | map.put("m", "method1"); 58 | map.put("m2", "method2"); 59 | cah.setShortCutMap(map); 60 | 61 | try { 62 | cah.addShortcut("m1", "method1"); 63 | cah.addShortcut("m22", "method2"); 64 | cah.addShortcut("m3", "method3"); //Should throw an exception 65 | } catch (NoSuchMethodException e1) { 66 | e1.printStackTrace(); 67 | System.out.println("Error: Method not found or wrong param types: " + e1); 68 | } 69 | 70 | try { 71 | List failedCmds = cah.runArgs(); 72 | 73 | for (String cmd : failedCmds) 74 | System.out.println("Failed: " + cmd); 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | 79 | //Test autoshortcut 80 | cah.clearShortcuts(); 81 | cah.autoCreateShortCuts(); 82 | System.out.println(cah.getShortcutMap()); 83 | //should have {test1=setTest1, atest3=setATest3, t=setTest1, a=setATest3, test2=setTest2} 84 | //methods that start with set, have 0 or 1 string param, and 1 letter shortcuts for the first new letter found 85 | 86 | System.out.println("ConsoleArgumentHandler Test End"); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/SettingsSaveTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.io.File; 7 | 8 | import net.mdp3.java.util.settings.SettingsLoader; 9 | 10 | /** 11 | * @author Mikel 12 | * 13 | */ 14 | public class SettingsSaveTest { 15 | public static int staticIntParm = 0; 16 | public static String staticStringParm = "STATIC"; 17 | public static boolean staticBoolParm = false; 18 | public static long staticLongParm = 123456789; 19 | public static double staticDoubleParm = 1.55; 20 | 21 | public int intParm = 0; 22 | public String stringParm = "String"; 23 | public boolean boolParm = false; 24 | public long longParm = 123456789; 25 | public double doubleParm = 1.55; 26 | public int newVal = 100; 27 | 28 | public static void main(String[] args) { 29 | System.out.println("Static Test"); 30 | SettingsLoader set = new SettingsLoader(SettingsSaveTest.class, true); 31 | 32 | File file = new File("SettingsStaticSaveTest.txt"); 33 | set.saveSettings(file); 34 | 35 | System.out.println("Object Test"); 36 | @SuppressWarnings("unused") 37 | SettingsSaveTest sst = new SettingsSaveTest(); 38 | } 39 | 40 | public SettingsSaveTest() { 41 | SettingsLoader set = new SettingsLoader(this, true); 42 | 43 | File file = new File("SettingsSaveTest.txt"); 44 | set.saveSettings(file); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/SettingsTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.io.File; 7 | import java.net.URL; 8 | 9 | import net.mdp3.java.util.settings.SettingsLoader; 10 | 11 | /** 12 | * @author Mikel 13 | * 14 | */ 15 | public class SettingsTest { 16 | 17 | /** 18 | * @param args 19 | */ 20 | 21 | public static int staticIntParm = 0; 22 | public static String staticStringParm = "STATIC"; 23 | public static boolean staticBoolParm = false; 24 | public static long staticLongParm = 123456789; 25 | public static double staticDoubleParm = 1.55; 26 | 27 | public int intParm = 0; 28 | public String stringParm = "String"; 29 | public boolean boolParm = false; 30 | public long longParm = 123456789; 31 | public double doubleParm = 1.55; 32 | public int newVal = 100; 33 | 34 | @SuppressWarnings("unused") 35 | public static void main(String[] args) { 36 | System.out.println("Static Test: "); 37 | SettingsLoader set = new SettingsLoader(SettingsTest.class, true); 38 | 39 | URL url = SettingsTest.class.getResource("SettingsTest.txt"); 40 | File file = new File(url.getPath()); 41 | set.loadSettings(file); 42 | showStaticSettings(); 43 | 44 | System.out.println("\nObject Test:"); 45 | SettingsTest st = new SettingsTest(); 46 | } 47 | 48 | public SettingsTest() { 49 | SettingsLoader set = new SettingsLoader(this, true); 50 | 51 | URL url = SettingsTest.class.getResource("SettingsTest.txt"); 52 | File file = new File(url.getPath()); 53 | set.loadSettings(file); 54 | showSettings(); 55 | } 56 | 57 | public static void showStaticSettings() { 58 | System.out.println("Settings after load:"); 59 | System.out.println("staticIntParm: " + staticIntParm); 60 | System.out.println("staticStringParm: " + staticStringParm); 61 | System.out.println("staticBoolParm: " + staticBoolParm); 62 | System.out.println("staticLongParm: " + staticLongParm); 63 | System.out.println("staticDoubleParm: " + staticDoubleParm); 64 | } 65 | 66 | public void showSettings() { 67 | System.out.println("Settings after load:"); 68 | System.out.println("intParm: " + intParm); 69 | System.out.println("stringParm: " + stringParm); 70 | System.out.println("boolParm: " + boolParm); 71 | System.out.println("longParm: " + longParm); 72 | System.out.println("doubleParm: " + doubleParm); 73 | System.out.println("newVal: " + newVal); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/SettingsTest.txt: -------------------------------------------------------------------------------- 1 | #Settings Test file 2 | intParm: 500 3 | stringParm: sgdfgdfg 4 | boolParm: true 5 | longParm: 999999999 6 | doubleParm: 3.14 7 | 8 | staticIntParm: 650 9 | staticStringParm: 123452345345 10 | staticBoolParm: true 11 | staticLongParm: 888888888 12 | staticDoubleParm: 2.255 13 | 14 | //new Comment!! 15 | newVal = 500 16 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/SimpleFileIOTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.io.FileNotFoundException; 7 | import java.io.IOException; 8 | 9 | import net.mdp3.java.util.file.SimpleFileIO; 10 | 11 | /** 12 | * Test script for the SimpleFileIO class. 13 | * 14 | * Writes a string to a file, loads the file, then appends a string to file 15 | * and reloads the contents. 16 | * 17 | * @author Mikel 18 | * 19 | */ 20 | public class SimpleFileIOTest { 21 | 22 | /** 23 | * @param args 24 | */ 25 | public static void main(String[] args) { 26 | String text = "Test String!!@RWSF"; 27 | try { 28 | SimpleFileIO.writeStringToFile("test.txt", text); 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | } 32 | 33 | try { 34 | System.out.println(SimpleFileIO.loadFileToString("test.txt")); 35 | } catch (FileNotFoundException e) { 36 | e.printStackTrace(); 37 | } 38 | 39 | try { 40 | SimpleFileIO.appendStringToFile("test.txt", "Appending!"); 41 | } catch (FileNotFoundException e) { 42 | e.printStackTrace(); 43 | } catch (IOException e) { 44 | e.printStackTrace(); 45 | } 46 | 47 | try { 48 | System.out.println(SimpleFileIO.loadFileToString("test.txt")); 49 | } catch (FileNotFoundException e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/Util_Test.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.test; 2 | 3 | import net.mdp3.java.util.console.ConsoleReader; 4 | 5 | /** 6 | * util 7 | * @author Mikel 8 | * 9 | * Utils Test class 10 | */ 11 | public class Util_Test { 12 | 13 | private ConsoleReader cr; 14 | 15 | /** 16 | * Main entry point for Util package when testing. 17 | * 18 | * @param args 19 | */ 20 | @SuppressWarnings("unused") 21 | public static void main(String[] args) { 22 | Util_Test u = new Util_Test(); 23 | } 24 | 25 | public Util_Test() { 26 | cr = new ConsoleReader("Utils", this); 27 | } 28 | 29 | public void consoleTest() { 30 | System.out.println("ConsoleTest!"); 31 | } 32 | 33 | public void consoleTest2(String s) { 34 | System.out.println("ConsoleTest2: " + s); 35 | } 36 | 37 | public void quit() { 38 | cr.quit(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/test/WebserviceTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.test; 5 | 6 | import java.io.IOException; 7 | import java.net.BindException; 8 | import java.util.Iterator; 9 | import java.util.Map; 10 | import java.util.Map.Entry; 11 | 12 | import net.mdp3.java.util.webservice.Webservice; 13 | import net.mdp3.java.util.webservice.WebserviceListener; 14 | 15 | /** 16 | * Test/Example class for using the Webservice class 17 | * Creates a webserver at localhost:83/test which returns the URL parameters 18 | * to the page 19 | * 20 | * @author Mikel 21 | * 22 | */ 23 | public class WebserviceTest implements WebserviceListener { 24 | 25 | Webservice ws; 26 | 27 | /** 28 | * @param args 29 | */ 30 | @SuppressWarnings("unused") 31 | public static void main(String[] args) { 32 | WebserviceTest test = new WebserviceTest(83, "/test"); 33 | } 34 | 35 | public WebserviceTest(int port, String name) { 36 | try { 37 | ws = new Webservice(port, name, this); 38 | } catch (BindException e) { 39 | System.out.println("Error opening port: " + port); 40 | } catch (IOException e) { 41 | System.out.println("Error starting webservice: " + e); 42 | e.printStackTrace(); 43 | } 44 | 45 | } 46 | 47 | 48 | /** 49 | * wsAccess Override Required by the WebserviceListener interface 50 | * 51 | * It gets passed a HashMap containing the parameters and values used in 52 | * the Webservice URL. 53 | * 54 | * @param params HashMap containing the parameters and values used in the URL 55 | * @return String with the parameters and values from the URL 56 | */ 57 | @Override 58 | public String wsAccess(Map params) { 59 | String returnValue = ""; 60 | 61 | if (params.size() > 0) { 62 | returnValue = "Has Params! " + params.size() + '\n'; 63 | Iterator> it = params.entrySet().iterator(); 64 | while (it.hasNext()) { 65 | Map.Entry pairs = (Map.Entry)it.next(); 66 | returnValue += "Key: " + pairs.getKey() + " = " + pairs.getValue() + '\n'; 67 | } 68 | } 69 | else returnValue = "Invalid Params!"; 70 | System.out.println("RetVal: " + returnValue); 71 | 72 | return returnValue; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WSResponse.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.webservice; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class WSResponse { 9 | private int responseCode = 200; 10 | private byte[] responseBody; 11 | private Map> headersMap = null; 12 | 13 | private static final String DEFAULT_CHARSET = "UTF-8"; 14 | 15 | public WSResponse() { 16 | this(200); 17 | } 18 | 19 | public WSResponse(int responseCode) { 20 | this(responseCode, (byte[]) null); 21 | } 22 | 23 | public WSResponse(int responseCode, String responseBody) throws UnsupportedEncodingException { 24 | this(responseCode, responseBody, DEFAULT_CHARSET); 25 | } 26 | 27 | public WSResponse(int responseCode, String responseBody, String charset) throws UnsupportedEncodingException { 28 | this(responseCode, responseBody.getBytes(charset)); 29 | } 30 | 31 | public WSResponse(int responseCode, byte[] responseBody) { 32 | this(responseCode, responseBody, new HashMap>()); 33 | } 34 | 35 | public WSResponse(int responseCode, byte[] responseBody, Map> headersMap) { 36 | setResponseCode(responseCode); 37 | setResponseBody(responseBody); 38 | setHeadersMap(headersMap); 39 | } 40 | 41 | public int getResponseCode() { 42 | return responseCode; 43 | } 44 | public void setResponseCode(int responseCode) { 45 | this.responseCode = responseCode; 46 | } 47 | public byte[] getResponseBody() { 48 | return responseBody; 49 | } 50 | public void setResponseBody(byte[] responseBody) { 51 | this.responseBody = responseBody; 52 | } 53 | public void setResponseBody(String responseBody) throws UnsupportedEncodingException { 54 | this.responseBody = responseBody.getBytes(DEFAULT_CHARSET); 55 | } 56 | public Map> getHeadersMap() { 57 | return headersMap; 58 | } 59 | public void setHeadersMap(Map> headersMap) { 60 | this.headersMap = headersMap; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/Webservice.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.webservice; 5 | 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | import java.net.BindException; 9 | import java.util.Map; 10 | import java.util.logging.Logger; 11 | 12 | //These imports require a sun/oracle jvm 13 | //http://stackoverflow.com/questions/9579970/can-not-use-the-com-sun-net-httpserver-httpserver 14 | import com.sun.net.httpserver.HttpExchange; 15 | import com.sun.net.httpserver.HttpHandler; 16 | 17 | /** 18 | * Webservice 19 | * 20 | * Simple Java Webservice using the Sun HTTP Server implementation. The 21 | * necessary packages may not be included in all JVMs. 22 | * 23 | * This class creates a webserver at the specified port and context, which 24 | * listens for connections, builds the access URL parameters into a HashMap 25 | * and finally calls the wsAccess callback specified by the WebserviceListener 26 | * interface. The String returned by wsAccess is returned back to the browser. 27 | * 28 | * @author Mikel 29 | * @see http://stackoverflow.com/questions/9579970/can-not-use-the-com-sun-net-httpserver-httpserver 30 | * @see http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html 31 | */ 32 | @SuppressWarnings("restriction") 33 | public class Webservice extends WebserviceBase { 34 | private final static String CLAZZ = Webservice.class.getName(); 35 | private final static Logger LOG = Logger.getLogger(CLAZZ); 36 | 37 | /** 38 | * Starts the SUN class webservice with service name on specified port 39 | * 40 | * @param port Port to use, must not be in use 41 | * @param name Webservice Name, this will be in the URL 42 | * @param listener Class implementing WebserviceListener for callbacks 43 | * @throws BindException 44 | * @throws IOException 45 | */ 46 | public Webservice(int port, String name, WebserviceListener listener) throws BindException, IOException { 47 | super(port, name, new GetHandler(listener)); 48 | } 49 | 50 | /** 51 | * called by http://ip/name/~ 52 | * parses url to get user info and file to send 53 | * 54 | * @author Mikel 55 | * 56 | */ 57 | static class GetHandler implements HttpHandler { 58 | //TODO Add sending files, can set file serve folder on init and serve files from it based on URL 59 | HttpExchange t; 60 | WebserviceListener wsl; 61 | 62 | public GetHandler(WebserviceListener listener) { 63 | this.wsl = listener; 64 | } 65 | 66 | /** 67 | * 68 | */ 69 | public void handle(HttpExchange t) throws IOException { 70 | LOG.entering(CLAZZ, "handle", "t: " + t); 71 | 72 | this.t = t; 73 | LOG.finer("Server: Get handler Called"); 74 | 75 | Map map = WebserviceUtil.getParamsMap(t); 76 | 77 | //Headers h = t.getResponseHeaders(); 78 | String response = wsl.wsAccess(map); 79 | LOG.finer(response); 80 | 81 | t.sendResponseHeaders(200, response.length()); 82 | OutputStream os = t.getResponseBody(); 83 | os.write(response.getBytes()); 84 | os.close(); 85 | 86 | LOG.exiting(CLAZZ, "handle"); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WebserviceBase.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.webservice; 2 | 3 | import java.io.IOException; 4 | import java.net.BindException; 5 | import java.net.InetSocketAddress; 6 | import java.util.logging.Logger; 7 | 8 | import com.sun.net.httpserver.HttpHandler; 9 | import com.sun.net.httpserver.HttpServer; 10 | 11 | @SuppressWarnings("restriction") 12 | public class WebserviceBase { 13 | private final static String CLAZZ = WebserviceBase.class.getName(); 14 | private final static Logger LOG = Logger.getLogger(CLAZZ); 15 | 16 | //private boolean running = true; 17 | protected int port; 18 | protected String name = "ws"; 19 | 20 | protected HttpServer server; 21 | 22 | protected HttpHandler handler; 23 | 24 | public WebserviceBase(int port, String name, HttpHandler listener) throws BindException, IOException { 25 | LOG.entering(CLAZZ, "Webservice", "port:" + port + " name:" + name); 26 | if (name.charAt(0) != '/') name = "/" + name; //HttpServer.createContext arg0 is required to begin with / 27 | 28 | this.port = port; 29 | this.name = name; 30 | this.handler = listener; 31 | 32 | startServer(); 33 | 34 | LOG.exiting(CLAZZ, "Webservice"); 35 | } 36 | 37 | public void startServer() throws BindException, IOException { 38 | LOG.entering(CLAZZ, "startServer"); 39 | 40 | server = HttpServer.create(new InetSocketAddress(this.port), 0); 41 | server.createContext(this.name, handler); 42 | server.setExecutor(null); 43 | server.start(); 44 | 45 | LOG.exiting(CLAZZ, "startServer"); 46 | } 47 | 48 | /** 49 | * Stops the webservice 50 | * 51 | * @param delay 52 | * @throws Exception 53 | */ 54 | public void stopServer(int delay) throws Exception { 55 | LOG.entering(CLAZZ, "stopServer"); 56 | 57 | server.stop(delay); 58 | 59 | LOG.exiting(CLAZZ, "stopServer"); 60 | } 61 | 62 | /** 63 | * Restarts the service and can change the port 64 | * 65 | * @param delay 66 | * @param newPort 67 | * @throws Exception 68 | */ 69 | public void restart(int delay, int newPort) throws Exception { 70 | LOG.entering(CLAZZ, "restart"); 71 | 72 | stopServer(delay); 73 | this.port = newPort; 74 | startServer(); 75 | 76 | LOG.exiting(CLAZZ, "restart"); 77 | } 78 | 79 | public HttpHandler getHandler() { 80 | return handler; 81 | } 82 | 83 | public void setHandler(HttpHandler handler) { 84 | this.handler = handler; 85 | } 86 | 87 | public int getPort() { 88 | return port; 89 | } 90 | 91 | public void setPort(int port) { 92 | this.port = port; 93 | } 94 | 95 | public String getName() { 96 | return name; 97 | } 98 | 99 | public void setName(String name) { 100 | this.name = name; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WebserviceClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.webservice; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.DataOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStreamReader; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | import java.net.URLConnection; 13 | import java.util.logging.Logger; 14 | 15 | /** 16 | * @author Mikel 17 | * 18 | */ 19 | public class WebserviceClient { 20 | private final static Logger LOG = Logger.getLogger(WebserviceClient.class.getName()); 21 | private final static String NAME = "Util-WebserviceClient"; 22 | 23 | /** 24 | * Opens an HTTP Connection to the specified URL and returns the result 25 | * 26 | * @param urlStr 27 | * @return 28 | * @throws IOException 29 | */ 30 | public static String webserviceCall(String urlStr) throws IOException { 31 | URL url = new URL(urlStr); 32 | return webserviceCall(url); 33 | } 34 | 35 | /** 36 | * Opens an HTTP Connection to the specified URL and returns the result 37 | * 38 | * @param url 39 | * @return response from web server 40 | * @throws IOException 41 | */ 42 | public static String webserviceCall(URL url) throws IOException { 43 | LOG.entering(WebserviceClient.NAME, "webserviceCall"); 44 | 45 | URLConnection urlc = url.openConnection(); 46 | urlc.connect(); 47 | 48 | BufferedReader in = new BufferedReader(new InputStreamReader( 49 | urlc.getInputStream())); 50 | 51 | String inputLine; 52 | String resp = ""; 53 | while ((inputLine = in.readLine()) != null) { 54 | resp += inputLine + '\n'; 55 | } 56 | LOG.finer("Response: " + resp); 57 | in.close(); 58 | 59 | LOG.exiting(WebserviceClient.NAME, "webserviceCall", "ret=" + resp); 60 | return resp; 61 | } 62 | 63 | public static String webservicePost(String urlStr, String data, boolean waitForResult) throws IOException { 64 | URL url = new URL(urlStr); 65 | return webservicePost(url, data, waitForResult); 66 | } 67 | 68 | public static String webservicePost(URL url, String data, boolean waitForResult) throws IOException { 69 | LOG.entering(WebserviceClient.NAME, "webservicePost", new Object[] 70 | {"url: " + url + "data: " + data, "waitForResult: " + waitForResult}); 71 | 72 | String ret = ""; 73 | 74 | HttpURLConnection con = (HttpURLConnection) url.openConnection(); 75 | con.setRequestMethod("POST"); 76 | 77 | con.setDoOutput(true); 78 | DataOutputStream out = new DataOutputStream(con.getOutputStream()); 79 | out.writeBytes(data); 80 | out.flush(); 81 | out.close(); 82 | 83 | int responseCode = con.getResponseCode(); 84 | LOG.fine("Response Code: " + responseCode); 85 | 86 | if (waitForResult) { 87 | BufferedReader in = new BufferedReader( 88 | new InputStreamReader(con.getInputStream())); 89 | String inputLine; 90 | 91 | while ((inputLine = in.readLine()) != null) { 92 | ret += "\n" + inputLine; 93 | } 94 | in.close(); 95 | } else { 96 | ret += responseCode; 97 | } 98 | 99 | LOG.fine(ret); 100 | 101 | LOG.exiting(WebserviceClient.NAME, "webservicePost", "Response Code: " + responseCode + "ret=" + ret); 102 | return ret; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WebserviceConstants.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.webservice; 2 | 3 | public class WebserviceConstants { 4 | 5 | public static final String HTTP_GET = "GET"; 6 | 7 | public static final String HTTP_POST = "POST"; 8 | 9 | 10 | public static final int HTTP_OK = 200; 11 | 12 | public static final int HTTP_NOT_FOUND = 404; 13 | 14 | public static final int HTTP_UNAUTHORIZED = 401; 15 | 16 | public static final int HTTP_INTERNAL_ERROR = 500; 17 | } 18 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WebserviceListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.webservice; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * This interface is used to define the callback for the Webservice Class. 10 | * 11 | * @author Mikel 12 | * 13 | */ 14 | public interface WebserviceListener { 15 | 16 | /** 17 | * Callback for calls to the Webservice 18 | * 19 | * It gets the params in a hashmap, using the ¶m=value form and 20 | * returns the String to be sent back to the browser 21 | * 22 | * Example url: http://localhost:80/context&parm1=aaa&parm2=bbb 23 | * Would get passed a hashmap with 24 | * Key: parm1 Value: aaa 25 | * Key: parm2 Value: bbb 26 | * 27 | * @param params HashMap containing the parameters and values used in the URL 28 | * @return String to be send back to the browser 29 | */ 30 | public abstract String wsAccess(Map params); 31 | } 32 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/webservice/WebserviceUtil.java: -------------------------------------------------------------------------------- 1 | package net.mdp3.java.util.webservice; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.logging.Logger; 9 | 10 | import com.sun.net.httpserver.HttpExchange; 11 | 12 | @SuppressWarnings("restriction") 13 | public class WebserviceUtil { 14 | private final static String CLAZZ = WebserviceUtil.class.getName(); 15 | private final static Logger LOG = Logger.getLogger(CLAZZ); 16 | 17 | private WebserviceUtil() { } 18 | 19 | /** 20 | * Splits the requestURI to a hashmap after the ? by splitting on = 21 | * 22 | * @param t 23 | * @return 24 | */ 25 | public static Map getParamsMap(HttpExchange t) { 26 | LOG.fine("Method: " + t.getRequestMethod()); 27 | 28 | Map map = new HashMap(); 29 | 30 | //get request url /get/command info 31 | String command = t.getRequestURI().toString(); 32 | LOG.fine("Command: " + command); 33 | 34 | String params = command.substring(command.indexOf("?") + 1); 35 | 36 | if (params.length() > 0) { 37 | String[] vars = params.split("&"); 38 | for (int i = 0; i < vars.length; i++) { 39 | LOG.finer("var " + i + ": " + vars[i]); 40 | 41 | String[] parmPair = vars[i].split("="); 42 | if (parmPair.length == 2) { 43 | LOG.finer("Key: " + parmPair[0] + " Value: " + parmPair[1]); 44 | 45 | map.put(parmPair[0], parmPair[1]); 46 | } 47 | } 48 | } 49 | 50 | return map; 51 | } 52 | 53 | /** 54 | * Util method to write the WSResponse object, headers, code, and body to a httpExchange 55 | * 56 | * @param httpExchange 57 | * @param response 58 | * @throws IOException 59 | */ 60 | public static void writeResponse(HttpExchange httpExchange, WSResponse response) throws IOException { 61 | Map> headers = response.getHeadersMap(); 62 | for (String header: headers.keySet()) { 63 | for (String value: headers.get(header)) { 64 | httpExchange.getResponseHeaders().add(header, value); 65 | } 66 | } 67 | 68 | httpExchange.sendResponseHeaders(response.getResponseCode(), response.getResponseBody().length); 69 | 70 | OutputStream os = httpExchange.getResponseBody(); 71 | os.write(response.getResponseBody()); 72 | 73 | os.close(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/xml/DomXml.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.xml; 5 | 6 | import org.w3c.dom.Document; 7 | import org.w3c.dom.Element; 8 | 9 | /** 10 | * @author Mikel 11 | * 12 | */ 13 | public interface DomXml { 14 | public Element toXml(Document doc); 15 | public void fromXml(Element e) throws Exception; 16 | } 17 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/src/net/mdp3/java/util/xml/XmlHelper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package net.mdp3.java.util.xml; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.StringWriter; 9 | 10 | import javax.xml.parsers.DocumentBuilder; 11 | import javax.xml.parsers.DocumentBuilderFactory; 12 | import javax.xml.parsers.ParserConfigurationException; 13 | import javax.xml.transform.OutputKeys; 14 | import javax.xml.transform.Transformer; 15 | import javax.xml.transform.TransformerException; 16 | import javax.xml.transform.TransformerFactory; 17 | import javax.xml.transform.TransformerFactoryConfigurationError; 18 | import javax.xml.transform.dom.DOMSource; 19 | import javax.xml.transform.stream.StreamResult; 20 | 21 | import org.w3c.dom.Document; 22 | import org.w3c.dom.Element; 23 | import org.xml.sax.SAXException; 24 | 25 | /** 26 | * @author Mikel 27 | * 28 | */ 29 | public class XmlHelper { 30 | 31 | /** 32 | * Method to make adding repetitive text nodes to an element easier. 33 | * 34 | * @param doc Java DOM Doc which is the items get added to 35 | * @param name Name of the new element 36 | * @param val Text Value of the new element 37 | * @return Element containing a value ready to append to another Element 38 | */ 39 | public static Element newTextElement(Document doc, String name, Object val) { 40 | Element e = doc.createElement(name); 41 | e.appendChild(doc.createTextNode(val.toString())); 42 | return e; 43 | } 44 | 45 | /** 46 | * Converts a Java DOM Xml Element to a String for simple output to 47 | * console, logs, or files. 48 | * 49 | * @param e Element to convert 50 | * @return String representation of element 51 | * @throws TransformerFactoryConfigurationError 52 | * @throws TransformerException 53 | */ 54 | public static String elementToString(Element e) throws TransformerFactoryConfigurationError, TransformerException { 55 | String ret = ""; 56 | Transformer transformer; 57 | 58 | transformer = TransformerFactory.newInstance().newTransformer(); 59 | transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 60 | 61 | StreamResult result = new StreamResult(new StringWriter()); 62 | DOMSource source = new DOMSource(e); 63 | transformer.transform(source, result); 64 | 65 | ret = result.getWriter().toString(); 66 | 67 | return ret; 68 | } 69 | 70 | /** 71 | * Returns a new Java DOM Doc object for use with elements. This doc should 72 | * not be used for saving it is just used for internal copy/move/load type 73 | * functions. 74 | * 75 | * @return 76 | */ 77 | public static Document getNewDoc() { 78 | DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); 79 | DocumentBuilder docBuilder; 80 | 81 | try { 82 | docBuilder = docFactory.newDocumentBuilder(); 83 | 84 | // root elements 85 | Document doc = docBuilder.newDocument(); 86 | //Element rootElement = doc.createElement(rootElementName); 87 | //doc.appendChild(rootElement); 88 | 89 | return doc; 90 | } catch (ParserConfigurationException e) { 91 | e.printStackTrace(); 92 | } 93 | 94 | return null; 95 | } 96 | 97 | public static void saveDocument(Document doc, File file) throws TransformerException { 98 | TransformerFactory transformerFactory = TransformerFactory.newInstance(); 99 | Transformer transformer = transformerFactory.newTransformer(); 100 | DOMSource source = new DOMSource(doc); 101 | StreamResult result = new StreamResult(file); 102 | 103 | transformer.transform(source, result); 104 | } 105 | 106 | /** 107 | * Reads in an xml file and returns the root element 108 | * 109 | * @param fileLocation 110 | * @return 111 | * @throws ParserConfigurationException 112 | * @throws SAXException 113 | * @throws IOException 114 | */ 115 | public static Element readXmlFile(String fileLocation) throws ParserConfigurationException, SAXException, IOException { 116 | File f = new File(fileLocation); 117 | return XmlHelper.readXmlFile(f); 118 | } 119 | 120 | /** 121 | * Reads in an xml file and returns the root Element 122 | * 123 | * @param f 124 | * @return 125 | * @throws ParserConfigurationException 126 | * @throws SAXException 127 | * @throws IOException 128 | */ 129 | public static Element readXmlFile(File f) throws ParserConfigurationException, SAXException, IOException { 130 | Element retE = null; 131 | 132 | DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 133 | DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 134 | Document doc = dBuilder.parse(f); 135 | 136 | doc.getDocumentElement().normalize(); 137 | 138 | retE = doc.getDocumentElement(); 139 | 140 | return retE; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation/001.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation/001.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation/002.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation/002.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation/003.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation/003.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation/004.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation/004.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation2/ChristmasTree.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation2/ChristmasTree.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testAnimation2/HOHOHO.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testAnimation2/HOHOHO.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/ChristmasTree.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/ChristmasTree.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/HI.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/HI.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/HOHOHO.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/HOHOHO.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/test.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/test.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/testScale1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/testScale1.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/testImages/test_vert.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikelduke/LedTable/849ee4259652a0a1783444375f882bcd718a8ea9/RPi-Java-LedTable/testImages/test_vert.bmp -------------------------------------------------------------------------------- /RPi-Java-LedTable/www/LedTable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Led Table Controller 4 | 5 | 6 | 7 |

Led Table Controller

8 |

WS Version 1

9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 |

17 |
18 |
19 |
20 |
21 |
22 | 23 | --------------------------------------------------------------------------------