mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	improve serial hotplug (#389)
* - disable device when error indecates that the problem is not solvable on reconnect
- introduce a preOpenDelay of 2 seconds (currently value is hardcoded)
* rs232:
- make preOpenDelay available via webui
- fix preOpenDelay
- add basic usb serial detection
* - revert 3819ae7
- fix schema files
* make json checks compat with utf8+bom
* make shutdown effect a bit more flexible
			
			
This commit is contained in:
		| @@ -4,7 +4,7 @@ | ||||
|  | ||||
| ``` | ||||
| sudo apt-get update | ||||
| sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev python-simplejson | ||||
| sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev | ||||
| ``` | ||||
|  | ||||
| **ATTENTION Win10LinuxSubsystem** we do not (/we can't) support using hyperion in linux subsystem of MS Windows 10, albeit some users tested it with success. Keep in mind to disable | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|  | ||||
| #define INITIAL_LED_TEST_ENABLED true | ||||
| #define INITIAL_LED_TEST_BRIGHTNESS 32  // 0..255 | ||||
| #define INITIAL_LED_TEST_TIME_MS 500  // 10.. | ||||
|  | ||||
| // Number of leds in your strip. set to "1" and ANALOG_OUTPUT_ENABLED to "true" to activate analog only | ||||
| // As of 26/1/2017: | ||||
| @@ -137,7 +138,6 @@ void setup() { | ||||
|     pinMode(ANALOG_GREEN_PIN, OUTPUT); | ||||
|   } | ||||
|  | ||||
|   // Uncomment/edit one of the following lines for your leds arrangement. | ||||
|   int ledCount = MAX_LEDS; | ||||
|   if (ANALOG_MODE == ANALOG_MODE_LAST_LED) { | ||||
|     ledCount--; | ||||
| @@ -155,10 +155,17 @@ void setup() { | ||||
|  | ||||
|   // initial RGB flash | ||||
|   #if INITIAL_LED_TEST_ENABLED == true | ||||
|   Serial.println("initial test"); | ||||
|   showColor(CRGB(INITIAL_LED_TEST_BRIGHTNESS, 0, 0));  delay(400); | ||||
|   showColor(CRGB(0, INITIAL_LED_TEST_BRIGHTNESS, 0));  delay(400); | ||||
|   showColor(CRGB(0, 0, INITIAL_LED_TEST_BRIGHTNESS ));  delay(400); | ||||
|   for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++) | ||||
|   { | ||||
|     showColor(CRGB(v,v,v);   | ||||
|     delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS); | ||||
|   } | ||||
|   | ||||
|   for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++) | ||||
|   { | ||||
|     showColor(CRGB(v,v,v);   | ||||
|     delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS); | ||||
|   } | ||||
|   #endif | ||||
|   showColor(CRGB(0, 0, 0)); | ||||
|  | ||||
|   | ||||
| @@ -1,133 +1,447 @@ | ||||
| /** | ||||
|  * This is a demo implemention how to use tpm2 protovol on arduino | ||||
|  *  | ||||
|  * code is taken from: https://github.com/JonasVanGool/TPM2-ARDUINO | ||||
|  */ | ||||
| #include <pt.h> | ||||
| #include "FastLED.h" | ||||
|  | ||||
| #define ANALOG_MODE_AVERAGE  0 | ||||
| #define ANALOG_MODE_LAST_LED 1 | ||||
|  | ||||
|  | ||||
| #include <FastLED.h> | ||||
| /*==============================================================================*/ | ||||
| /* LED und Arduino Variablen */ | ||||
| /*==============================================================================*/ | ||||
| #define INITIAL_LED_TEST_ENABLED true | ||||
| #define INITIAL_LED_TEST_BRIGHTNESS 32  // 0..255 | ||||
| #define INITIAL_LED_TEST_TIME_MS 500  // 0..255 | ||||
|  | ||||
| #define START_BYTE  0xC9 | ||||
| #define STOP_BYTE   0x36 | ||||
| #define DATA_FRAME  0xDA | ||||
| #define COMMAND     0xC0 | ||||
| #define REQ_RESP    0xAA | ||||
| #define MAX_LEDS             400                // Number of LEDs | ||||
| #define MAX_ARGS             10                 // Max Number of command arguments | ||||
| #define BAUDRATE             460800             // Baudrate | ||||
| #define SERIAL               Serial            // Serial port for communication | ||||
| #define NUM_LEDS_PER_STRIP 20 | ||||
|  | ||||
| #define BAUDRATE    115200 | ||||
| // type of your led controller, possible values, see below | ||||
| #define LED_TYPE WS2812B  | ||||
|  | ||||
| #define DATA_PIN    12 | ||||
| #define MAX_NR_LEDS 200 | ||||
| // 3 wire (pwm): NEOPIXEL BTM1829 TM1812 TM1809 TM1804 TM1803 UCS1903 UCS1903B UCS1904 UCS2903 WS2812 WS2852 | ||||
| //               S2812B SK6812 SK6822 APA106 PL9823 WS2811 WS2813 APA104 WS2811_40 GW6205 GW6205_40 LPD1886 LPD1886_8BIT  | ||||
| // 4 wire (spi): LPD8806 WS2801 WS2803 SM16716 P9813 APA102 SK9822 DOTSTAR | ||||
|  | ||||
| CRGB leds[MAX_NR_LEDS]; | ||||
| // For 3 wire led stripes line Neopixel/Ws2812, which have a data line, ground, and power, you just need to define DATA_PIN. | ||||
| // For led chipsets that are SPI based (four wires - data, clock, ground, and power), both defines DATA_PIN and CLOCK_PIN are needed | ||||
|  | ||||
| enum States { | ||||
|   ST_START, | ||||
|   ST_PACKET_TYPE, | ||||
|   ST_PAYLOAD_SIZE, | ||||
|   ST_USER_DATA, | ||||
|   ST_END | ||||
| // DATA_PIN, or DATA_PIN, CLOCK_PIN | ||||
| #define LED_PINS 6        // 3 wire leds | ||||
| //#define LED_PINS 6, 13  // 4 wire leds | ||||
|  | ||||
| #define COLOR_ORDER GRB  // colororder of the stripe, set RGB in hyperion | ||||
|  | ||||
| #define OFF_TIMEOUT 15000    // ms to switch off after no data was received, set 0 to deactivate | ||||
|  | ||||
| // analog rgb uni color led stripe - using of hyperion smoothing is recommended | ||||
| // ATTENTION  this pin config is default for atmega328 based arduinos, others might work to | ||||
| //            if you have flickering analog leds this might be caused by unsynced pwm signals | ||||
| //            try other pins is more or less the only thing that helps | ||||
| #define ANALOG_OUTPUT_ENABLED false | ||||
| #define ANALOG_MODE           ANALOG_MODE_LAST_LED  // use ANALOG_MODE_AVERAGE or ANALOG_MODE_LAST_LED | ||||
| #define ANALOG_GROUND_PIN     8                     // additional ground pin to make wiring a bit easier | ||||
| #define ANALOG_RED_PIN        9 | ||||
| #define ANALOG_GREEN_PIN      10 | ||||
| #define ANALOG_BLUE_PIN       11 | ||||
|  | ||||
| // overall color adjustments | ||||
| #define ANALOG_BRIGHTNESS_RED   255              // maximum brightness for analog 0-255 | ||||
| #define ANALOG_BRIGHTNESS_GREEN 255              // maximum brightness for analog 0-255 | ||||
| #define ANALOG_BRIGHTNESS_BLUE  255              // maximum brightness for analog 0-255 | ||||
|  | ||||
| #define BRIGHTNESS 255                      // maximum brightness 0-255 | ||||
| #define DITHER_MODE BINARY_DITHER           // BINARY_DITHER or DISABLE_DITHER | ||||
| #define COLOR_TEMPERATURE CRGB(255,255,255) // RGB value describing the color temperature | ||||
| #define COLOR_CORRECTION  TypicalLEDStrip   // predefined fastled color correction | ||||
| //#define COLOR_CORRECTION  CRGB(255,255,255) // or RGB value describing the color correction | ||||
|  | ||||
| // Baudrate, higher rate allows faster refresh rate and more LEDs | ||||
| //#define serialRate 460800      // use 115200 for ftdi based boards | ||||
| #define serialRate 115200      // use 115200 for ftdi based boards | ||||
| //#define serialRate 500000         // use 115200 for ftdi based boards | ||||
|  | ||||
|  | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* TPM2 Variablen */ | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| enum Protocol | ||||
| { | ||||
|    // positions | ||||
|    posStart      = 0, | ||||
|    posType       = 1, | ||||
|    posFsHigh     = 2, | ||||
|    posFsLow      = 3, | ||||
|    posData       = 4, | ||||
|  | ||||
|    // bytes  | ||||
|    tpm2Start     = 0xc9, | ||||
|    tpm2DataFrame = 0xda, | ||||
|    tpm2Command   = 0xc0, | ||||
|    tpm2Answer    = 0xaa, | ||||
|    tpm2End       = 0x36, | ||||
|    tpm2Ack       = 0xAC | ||||
| }; | ||||
|  | ||||
| States activeState = ST_START; | ||||
| uint8_t byteRead = 0; | ||||
| uint8_t payloadHighByte = 0; | ||||
| uint8_t payloadLowByte = 0; | ||||
| int payloadSize = 0; | ||||
| int bytesRead = 0; | ||||
| int nrOfLeds = 0; | ||||
| enum Mode | ||||
| { | ||||
|    mNone, | ||||
|    mCommunication, | ||||
|    mProgram | ||||
| }; | ||||
|  | ||||
| boolean flag = false; | ||||
| void setup() { | ||||
|   // Init leds | ||||
|   for (int i = 0; i < MAX_NR_LEDS; i++) | ||||
|     leds[i] = 0; | ||||
|   // Start serial device | ||||
|   Serial.begin(BAUDRATE); | ||||
|   // Set time out for readBytes function | ||||
|   Serial.setTimeout(100); | ||||
|   // init fastLED Library | ||||
|   LEDS.addLeds<WS2812B, DATA_PIN, RGB>(leds, MAX_NR_LEDS); | ||||
|   // setting brightness to 50% brightness | ||||
|   LEDS.setBrightness(128); | ||||
|   // debug led | ||||
|   pinMode(13, OUTPUT); | ||||
| struct Data | ||||
| { | ||||
|    int pos; | ||||
|    uint8_t type; | ||||
|    uint16_t fs; | ||||
|    uint16_t maxSize; | ||||
|    uint8_t command; | ||||
|    CRGB rgb[MAX_LEDS]; | ||||
| } data; | ||||
|  | ||||
| byte args[MAX_ARGS]; | ||||
| unsigned long lastDataAt = 0; | ||||
| int program = 0; | ||||
| int mode = mNone; | ||||
| int effectDelay = 100; | ||||
| static struct pt pt1; | ||||
|  | ||||
|  | ||||
|   for(;;) { | ||||
|     if (Serial.available() > 0) { | ||||
|       // process TPM2 protocol | ||||
|       switch (activeState) { | ||||
|         //------------------------------// | ||||
|         //         START                // | ||||
|         //------------------------------// | ||||
|         case ST_START: | ||||
|           // read incomming byte | ||||
|           byteRead = Serial.read(); | ||||
|           if (byteRead == START_BYTE) { | ||||
|             activeState = ST_PACKET_TYPE; | ||||
|           } | ||||
|           break; | ||||
|         //------------------------------// | ||||
|         //         PACKET_TYPE          // | ||||
|         //------------------------------// | ||||
|         case ST_PACKET_TYPE: | ||||
|           // read incomming byte | ||||
|           byteRead = Serial.read(); | ||||
|           if (byteRead == DATA_FRAME) { | ||||
|             activeState = ST_PAYLOAD_SIZE; | ||||
|           } else { | ||||
|             activeState = ST_START; | ||||
|             Serial.flush(); | ||||
|           } | ||||
|           break; | ||||
|         //------------------------------// | ||||
|         //         PAYLOAD_SIZE         // | ||||
|         //------------------------------// | ||||
|         case ST_PAYLOAD_SIZE: | ||||
|           payloadHighByte = Serial.read(); | ||||
|           while (Serial.available() == 0) {} | ||||
|           payloadLowByte = Serial.read(); | ||||
|           payloadSize = (payloadHighByte << 8) + payloadLowByte; | ||||
|           nrOfLeds = payloadSize / 3; | ||||
|           if (nrOfLeds <= MAX_NR_LEDS) { | ||||
|             activeState = ST_USER_DATA; | ||||
|           } else { | ||||
|             activeState = ST_START; | ||||
|             Serial.flush(); | ||||
|           } | ||||
|           break; | ||||
|         //------------------------------// | ||||
|         //         USER_DATA            // | ||||
|         //------------------------------// | ||||
|         case ST_USER_DATA: | ||||
|           bytesRead = Serial.readBytes((char *)leds, payloadSize); | ||||
|           LEDS.show(); | ||||
|           if (bytesRead == payloadSize) { | ||||
|             activeState = ST_END; | ||||
|           } else { | ||||
|             activeState = ST_START; | ||||
|             Serial.flush(); | ||||
|           } | ||||
|           break; | ||||
|         //------------------------------// | ||||
|         //         END                  // | ||||
|         //------------------------------// | ||||
|         case ST_END: | ||||
|           // read incomming byte | ||||
|           byteRead = Serial.read(); | ||||
|           if (byteRead == STOP_BYTE) { | ||||
|             activeState = ST_START; | ||||
|           } else { | ||||
|             activeState = ST_START; | ||||
|             Serial.flush(); | ||||
|           } | ||||
|           break; | ||||
|         default: break; | ||||
|       } | ||||
|     } | ||||
| // int freeRam()  | ||||
| // { | ||||
| //    extern int __heap_start, *__brkval;  | ||||
| //    int v;  | ||||
| //    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);  | ||||
| // } | ||||
|  | ||||
| void setup() | ||||
| { | ||||
|   SERIAL.begin(BAUDRATE); | ||||
|  | ||||
|   delay(1000);   | ||||
|   int ledCount = MAX_LEDS; | ||||
|  | ||||
|   if (ANALOG_MODE == ANALOG_MODE_LAST_LED) { | ||||
|     ledCount--; | ||||
|   } | ||||
|  | ||||
|   memset(data.rgb, 0, sizeof(struct CRGB) * ledCount);  | ||||
|  | ||||
|   FastLED.addLeds<LED_TYPE, LED_PINS, COLOR_ORDER>(data.rgb, ledCount); | ||||
|  | ||||
|   // color adjustments | ||||
|   FastLED.setBrightness ( BRIGHTNESS ); | ||||
|   FastLED.setTemperature( COLOR_TEMPERATURE ); | ||||
|   FastLED.setCorrection ( COLOR_CORRECTION ); | ||||
|   FastLED.setDither     ( DITHER_MODE ); | ||||
|  | ||||
| #ifdef INITIAL_LED_TEST_ENABLED | ||||
|   for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++) | ||||
|   { | ||||
|     oneColorAll(v,v,v); | ||||
|     delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS); | ||||
|   } | ||||
|   | ||||
|   for (int v=0;v<INITIAL_LED_TEST_BRIGHTNESS;v++) | ||||
|   { | ||||
|     oneColorAll(INITIAL_LED_TEST_BRIGHTNESS-v,INITIAL_LED_TEST_BRIGHTNESS-v,INITIAL_LED_TEST_BRIGHTNESS-v); | ||||
|     delay(INITIAL_LED_TEST_TIME_MS/2/INITIAL_LED_TEST_BRIGHTNESS); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   #define BRIGHT    127     //max led intensity (1-500) | ||||
| #define INHALE    1250    //Inhalation time in milliseconds. | ||||
| #define PULSE     INHALE*1000/BRIGHT | ||||
| #define REST      1000    //Rest Between Inhalations. | ||||
|  | ||||
| while(true) | ||||
| { | ||||
| 	  //ramp increasing intensity, Inhalation:  | ||||
|   for (int i=1;i<BRIGHT;i++){ | ||||
| 	   oneColorAll(i,i,i); | ||||
|     delayMicroseconds(PULSE-i*10);   // wait | ||||
|     delay(0);                        //to prevent watchdog firing. | ||||
|   } | ||||
|   //ramp decreasing intensity, Exhalation (half time): | ||||
|   for (int i=BRIGHT-1;i>0;i--){ | ||||
| 	   oneColorAll(i,i,i); | ||||
|     delayMicroseconds(PULSE-i*10);   // wait | ||||
|     i--; | ||||
|     delay(0);                        //to prevent watchdog firing. | ||||
|   } | ||||
|   delay(REST);                       //take a rest... | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   oneColorAll(0,0,0); | ||||
|  | ||||
|   memset(args, 0, MAX_ARGS); | ||||
|   resetVars(); | ||||
|   PT_INIT(&pt1); | ||||
|   while (!SERIAL) { | ||||
|     ; // wait for serial port to connect. Needed for native USB | ||||
|   } | ||||
| } | ||||
|  | ||||
| void loop() { | ||||
| /*==============================================================================*/ | ||||
| /* Thread für Programm/Effekte | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| static int playProgramThread(struct pt *pt)  | ||||
| { | ||||
|    static unsigned long timestamp = 0; | ||||
|    PT_BEGIN(pt); | ||||
|    while(1)  | ||||
|    { | ||||
|       PT_WAIT_UNTIL(pt, millis() - timestamp > effectDelay); | ||||
|       playProgram(); | ||||
|       timestamp = millis(); | ||||
|    } | ||||
|    PT_END(pt); | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* loop | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void loop() | ||||
| { | ||||
|   while (1) | ||||
|   { | ||||
|    // if data available switch to communication mode | ||||
|    if (SERIAL.available() > 0) | ||||
|    { | ||||
|       if (mode != mCommunication) | ||||
|       { | ||||
|          mode = mCommunication; | ||||
|          resetVars(); | ||||
|       } | ||||
|       doCommunication(); | ||||
|    } | ||||
|    else | ||||
|    // communication timeout after 0.5 seconds | ||||
|    while (SERIAL.available() == 0 && millis()-lastDataAt > 1000) | ||||
|    { | ||||
|       if (mode != mProgram) | ||||
|       { | ||||
|          mode = mProgram; | ||||
|          resetVars(); | ||||
|       } | ||||
|       else | ||||
|         playProgramThread(&pt1); | ||||
|    } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* do communication | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void doCommunication() | ||||
| { | ||||
|    // read ... | ||||
|    while (SERIAL.available() > 0) | ||||
|    { | ||||
|       | ||||
|       byte val = SERIAL.read(); | ||||
|       lastDataAt = millis(); | ||||
|  | ||||
|       if (data.pos == posStart && val == tpm2Start)                                    // Startbyte | ||||
|          resetVars(); | ||||
|  | ||||
|       else if (data.pos == posType && (val == tpm2DataFrame || val == tpm2Command))    // Block-Art | ||||
|          data.type = val; | ||||
|  | ||||
|       else if (data.pos == posFsHigh)                                                  // Framesize (High Bit) | ||||
|       { | ||||
|          data.fs = (val << 8) & 0xFF00; | ||||
| 		 data.maxSize = data.fs; | ||||
|       } | ||||
|       else if (data.pos == posFsLow)                                                   // Framesize (Low byte) | ||||
|       { | ||||
|          data.fs += val & 0x00FF; | ||||
| 		 data.maxSize = data.fs; | ||||
|          if (data.fs > MAX_LEDS*3) // framsize too high | ||||
|          { | ||||
| 			 data.fs = MAX_LEDS*3; | ||||
|          }  | ||||
|           | ||||
|       } | ||||
|       else if (data.pos == posData + data.maxSize && val == tpm2End)                        // End Byte | ||||
|          parsePacket(); | ||||
|  | ||||
|       else if (data.pos >= posData && data.pos < posData+data.fs)                      // Bytes zwischen Header und Ende lesen | ||||
|          evaluateData(val); | ||||
|  | ||||
|       else if (data.pos >= posData && data.pos < posData+data.maxSize)                 // Bytes zwischen Header und Ende lesen | ||||
|          continue; | ||||
|  | ||||
|       else                                                                             // protocol violation ... | ||||
|       { | ||||
|          resetVars(); | ||||
|          continue; | ||||
|       } | ||||
|       data.pos++; | ||||
|    } | ||||
|  | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* evaluate data | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void evaluateData(byte val) | ||||
| { | ||||
|    if (data.type == tpm2DataFrame)        // frame data | ||||
|    { | ||||
|       uint8_t* rgb = (uint8_t*)data.rgb; | ||||
|       rgb[data.pos-posData] = val; | ||||
|    } | ||||
|  | ||||
|    else                                  // command data | ||||
|    { | ||||
|       if (data.pos == posData) | ||||
|       { | ||||
|          data.command = val; | ||||
|          memset(args, 0, sizeof(args));   | ||||
|       } | ||||
|       else | ||||
|          args[data.pos-posData-1] = val; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* reset variables | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void resetVars() | ||||
| { | ||||
|    memset(&data, 0, sizeof(Data)); | ||||
|    //data.rgb = (struct CRGB*)FastSPI_LED.getRGBData(); | ||||
|    memset(data.rgb, 0,  MAX_LEDS * sizeof(struct CRGB)); | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* parse packet | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void parsePacket() | ||||
| { | ||||
|    switch (data.type) | ||||
|    { | ||||
|       case tpm2DataFrame: | ||||
|       { | ||||
|          showLeds(); | ||||
|          break; | ||||
|       } | ||||
|       case tpm2Command:  | ||||
|       { | ||||
|          setProgram(); | ||||
|          break; | ||||
|       } | ||||
|       default:  | ||||
|          break; | ||||
|    } | ||||
|  | ||||
|    SERIAL.write(tpm2Ack); | ||||
|    resetVars(); | ||||
|    data.pos = -1; | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* set LED color | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void setLedColor(int led, uint8_t r, uint8_t g, uint8_t b) | ||||
| { | ||||
|    data.rgb[led].r = r;  | ||||
|    data.rgb[led].g = g;  | ||||
|    data.rgb[led].b = b;  | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* one Color All | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void oneColorAll(uint8_t r, uint8_t g, uint8_t b) | ||||
| { | ||||
|    memset(data.rgb, 0, MAX_LEDS * sizeof(struct CRGB)); | ||||
|  | ||||
|    for (int led = 0; led < MAX_LEDS; led++) | ||||
|       setLedColor(led, r, g, b); | ||||
|  | ||||
|    showLeds(); | ||||
|    effectDelay = 1000; | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* Output Leds | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void showLeds() | ||||
| { | ||||
|     FastLED.show(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void setProgram() | ||||
| { | ||||
|    program = data.command; | ||||
| } | ||||
|  | ||||
| void playProgram() | ||||
| { | ||||
|    switch (program) | ||||
|    { | ||||
|       case  0: oneColorAll(args[0],args[1],args[2]);   break; | ||||
|       case  1: rainbow_loop(20);                       break; | ||||
|       default: oneColorAll(0,0,0);        break; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* Set LED Color of given LED */ | ||||
|  | ||||
| void oneColorAllNOSHOW(int r, int g, int b) | ||||
| { | ||||
|    resetVars(); | ||||
|    for (int led = 0; led < MAX_LEDS; led++) | ||||
|    { | ||||
|       setLedColor(led, r, g, b); | ||||
|    } | ||||
|  | ||||
| } | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* Effect 0: Fixed color - Arguments RR GG BB | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| /*==============================================================================*/ | ||||
| /* Effect 1: Loops rainbow colors around the stripe | ||||
| /*==============================================================================*/ | ||||
|  | ||||
| void rainbow_loop(int idelay) { //-LOOP HSV RAINBOW | ||||
|    static double idex = 0; | ||||
|    static double ihue = 0; | ||||
|    double steps = (double)255/MAX_LEDS;  | ||||
|     | ||||
|    for(int led = 0 ; led < MAX_LEDS; led++ ) { | ||||
|       ihue = led * steps + idex; | ||||
|       if (ihue >= 255)  | ||||
|          ihue -= 255; | ||||
|  | ||||
|       data.rgb[led] = CHSV((int)ihue, 255, 255); | ||||
|  | ||||
|       if (led == 0) | ||||
|          idex += steps; | ||||
|       if (idex >= 255)  | ||||
|          idex = 0; | ||||
|    }   | ||||
|    showLeds(); | ||||
|    effectDelay = idelay; | ||||
| } | ||||
|   | ||||
| @@ -1,68 +1,68 @@ | ||||
| { | ||||
|     "type":"object", | ||||
|     "script" : "candle.py", | ||||
|     "title":"edt_eff_candle_header_title", | ||||
|     "required":true, | ||||
|     "properties":{ | ||||
| 	"candles": { | ||||
| 		"type": "string", | ||||
| 		"title":"edt_eff_whichleds_title", | ||||
| 		"enum" : ["all","all-together","list"], | ||||
| 		"default" : "all", | ||||
| 		"options" : { | ||||
| 			"enum_titles" : ["edt_eff_enum_all", "edt_eff_enum_all-together", "edt_eff_enum_list"] | ||||
| 	"type":"object", | ||||
| 	"script" : "candle.py", | ||||
| 	"title":"edt_eff_candle_header_title", | ||||
| 	"required":true, | ||||
| 	"properties":{ | ||||
| 		"candles": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_eff_whichleds_title", | ||||
| 			"enum" : ["all","all-together","list"], | ||||
| 			"default" : "all", | ||||
| 			"options" : { | ||||
| 				"enum_titles" : ["edt_eff_enum_all", "edt_eff_enum_all-together", "edt_eff_enum_list"] | ||||
| 			}, | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"propertyOrder" : 1 | ||||
| 		"ledlist": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_eff_ledlist_title", | ||||
| 			"default" : "1,11,21", | ||||
| 			"propertyOrder" : 2 | ||||
| 		}, | ||||
| 		"color": { | ||||
| 		"type": "array", | ||||
| 		"title":"edt_eff_color_title", | ||||
| 		"format":"colorpicker", | ||||
| 			"default": [255,138,0], | ||||
| 			"items" : { | ||||
| 				"type": "integer", | ||||
| 				"minimum": 0, | ||||
| 				"maximum": 255 | ||||
| 			}, | ||||
| 			"minItems": 3, | ||||
| 			"maxItems": 3, | ||||
| 			"propertyOrder" : 3 | ||||
| 		}, | ||||
| 		"colorShift": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_colorshift_title", | ||||
| 			"default": 1, | ||||
| 			"minimum" : 0, | ||||
| 			"maximum": 30, | ||||
| 			"append" : "edt_append_percent", | ||||
| 			"propertyOrder" : 4 | ||||
| 		}, | ||||
| 		"brightness": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_brightness_title", | ||||
| 			"default": 100, | ||||
| 			"minimum" : 1, | ||||
| 			"maximum": 100, | ||||
| 			"step" : 10, | ||||
| 			"append" : "edt_append_percent", | ||||
| 			"propertyOrder" : 5 | ||||
| 		}, | ||||
| 		"sleepTime": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_sleeptime_title", | ||||
| 			"default": 0.15, | ||||
| 			"minimum" : 0.01, | ||||
| 			"maximum": 1, | ||||
| 			"step": 0.01, | ||||
| 			"append" : "edt_append_s", | ||||
| 			"propertyOrder" : 6 | ||||
| 		} | ||||
| 	}, | ||||
| 	"ledlist": { | ||||
| 		"type": "string", | ||||
| 		"title":"edt_eff_ledlist_title", | ||||
| 		"default" : "1,11,21", | ||||
| 		"propertyOrder" : 2 | ||||
| 	}, | ||||
|         "color": { | ||||
|             "type": "array", | ||||
|             "title":"edt_eff_color_title", | ||||
|             "format":"colorpicker", | ||||
|             "default": [255,138,0], | ||||
|             "items" : { | ||||
|                 "type": "integer", | ||||
|                 "minimum": 0, | ||||
|                 "maximum": 255 | ||||
|             }, | ||||
|             "minItems": 3, | ||||
|             "maxItems": 3, | ||||
|             "propertyOrder" : 3 | ||||
|         }, | ||||
| 	"colorShift": { | ||||
| 		"type": "number", | ||||
| 		"title":"edt_eff_colorshift_title", | ||||
| 		"default": 1, | ||||
| 		"minimum" : 0, | ||||
|         "maximum": 30, | ||||
| 		"append" : "edt_append_percent", | ||||
| 		"propertyOrder" : 4 | ||||
| 	}, | ||||
| 	"brightness": { | ||||
| 		"type": "number", | ||||
| 		"title":"edt_eff_brightness_title", | ||||
| 		"default": 100, | ||||
| 		"minimum" : 1, | ||||
| 		"maximum": 100, | ||||
| 		"step" : 10, | ||||
| 		"append" : "edt_append_percent", | ||||
| 		"propertyOrder" : 5 | ||||
| 	}, | ||||
| 	"sleepTime": { | ||||
| 		"type": "number", | ||||
| 		"title":"edt_eff_sleeptime_title", | ||||
| 		"default": 0.15, | ||||
| 		"minimum" : 0.01, | ||||
| 		"maximum": 1, | ||||
| 		"step": 0.01, | ||||
| 		"append" : "edt_append_s", | ||||
| 		"propertyOrder" : 6 | ||||
| 	} | ||||
|     }, | ||||
|     "additionalProperties": false | ||||
| 	"additionalProperties": false | ||||
| } | ||||
|   | ||||
| @@ -1,78 +1,78 @@ | ||||
| { | ||||
| 	"type":"object", | ||||
| 	"script" : "clock.py", | ||||
| 	"title":"edt_eff_clock_header_title", | ||||
| 	"required":true, | ||||
| 	"properties":{ | ||||
| { | ||||
| 	"type": "object", | ||||
| 	"script": "clock.py", | ||||
| 	"title": "edt_eff_clock_header_title", | ||||
| 	"required": true, | ||||
| 	"properties": { | ||||
| 		"offset": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_offset_title", | ||||
| 			"title": "edt_eff_offset_title", | ||||
| 			"default": 0, | ||||
| 			"append" : "edt_append_leds", | ||||
| 			"propertyOrder" : 1 | ||||
| 			"append": "edt_append_leds", | ||||
| 			"propertyOrder": 1 | ||||
| 		}, | ||||
| 		"hour-color": { | ||||
| 			"type": "array", | ||||
| 			"title":"edt_eff_colorHour_title", | ||||
| 			"format":"colorpicker", | ||||
| 			"default": [255,0,0], | ||||
| 			"items" : { | ||||
| 			"title": "edt_eff_colorHour_title", | ||||
| 			"format": "colorpicker", | ||||
| 			"default": [255, 0, 0], | ||||
| 			"items": { | ||||
| 				"type": "integer", | ||||
| 				"minimum": 0, | ||||
| 				"maximum": 255 | ||||
| 			}, | ||||
| 			"minItems": 3, | ||||
| 			"maxItems": 3, | ||||
| 			"propertyOrder" : 2 | ||||
| 			"propertyOrder": 2 | ||||
| 		}, | ||||
| 		"minute-color": { | ||||
| 			"type": "array", | ||||
| 			"title":"edt_eff_colorMinute_title", | ||||
| 			"format":"colorpicker", | ||||
| 			"default": [0,255,0], | ||||
| 			"items" : { | ||||
| 			"title": "edt_eff_colorMinute_title", | ||||
| 			"format": "colorpicker", | ||||
| 			"default": [0, 255, 0], | ||||
| 			"items": { | ||||
| 				"type": "integer", | ||||
| 				"minimum": 0, | ||||
| 				"maximum": 255 | ||||
| 			}, | ||||
| 			"minItems": 3, | ||||
| 			"maxItems": 3, | ||||
| 			"propertyOrder" : 3 | ||||
| 			"propertyOrder": 3 | ||||
| 		}, | ||||
| 		"second-color": { | ||||
| 			"type": "array", | ||||
| 			"title":"edt_eff_colorSecond_title", | ||||
| 			"format":"colorpicker", | ||||
| 			"default": [0,0,255], | ||||
| 			"items" : { | ||||
| 			"title": "edt_eff_colorSecond_title", | ||||
| 			"format": "colorpicker", | ||||
| 			"default": [0, 0, 255], | ||||
| 			"items": { | ||||
| 				"type": "integer", | ||||
| 				"minimum": 0, | ||||
| 				"maximum": 255 | ||||
| 			}, | ||||
| 			"minItems": 3, | ||||
| 			"maxItems": 3, | ||||
| 			"propertyOrder" : 4 | ||||
| 			"propertyOrder": 4 | ||||
| 		}, | ||||
| 		"hour-margin": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_hourMargin_title", | ||||
| 			"title": "edt_eff_hourMargin_title", | ||||
| 			"default": 2, | ||||
| 			"append" : "edt_append_leds", | ||||
| 			"propertyOrder" : 5 | ||||
| 			"append": "edt_append_leds", | ||||
| 			"propertyOrder": 5 | ||||
| 		}, | ||||
| 		"minute-margin": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_minuteMargin_title", | ||||
| 			"title": "edt_eff_minuteMargin_title", | ||||
| 			"default": 1, | ||||
| 			"append" : "edt_append_leds", | ||||
| 			"propertyOrder" : 6 | ||||
| 			"append": "edt_append_leds", | ||||
| 			"propertyOrder": 6 | ||||
| 		}, | ||||
| 		"second-margin": { | ||||
| 			"type": "number", | ||||
| 			"title":"edt_eff_secondMargin_title", | ||||
| 			"title": "edt_eff_secondMargin_title", | ||||
| 			"default": 0, | ||||
| 			"append" : "edt_append_leds", | ||||
| 			"propertyOrder" : 7 | ||||
| 			"append": "edt_append_leds", | ||||
| 			"propertyOrder": 7 | ||||
| 		} | ||||
| 	}, | ||||
| 	"additionalProperties": false | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| { | ||||
| { | ||||
| 	"type":"object", | ||||
| 	"script" : "pacman.py", | ||||
| 	"title":"edt_eff_pacman_header_title", | ||||
|   | ||||
| @@ -40,11 +40,23 @@ | ||||
| 			"maxItems": 3, | ||||
| 			"propertyOrder" : 3 | ||||
| 		}, | ||||
| 		"initial-blink": { | ||||
| 			"type": "boolean", | ||||
| 			"title":"edt_eff_initial_blink_title", | ||||
| 			"default": true, | ||||
| 			"propertyOrder" : 4 | ||||
| 		}, | ||||
| 		"set-post-color": { | ||||
| 			"type": "boolean", | ||||
| 			"title":"edt_eff_set_post_color_title", | ||||
| 			"default": true, | ||||
| 			"propertyOrder" : 5 | ||||
| 		}, | ||||
| 		"shutdown-enabled": { | ||||
| 			"type": "boolean", | ||||
| 			"title":"edt_eff_enableshutdown_title", | ||||
| 			"default": false, | ||||
| 			"propertyOrder" : 4 | ||||
| 			"propertyOrder" : 6 | ||||
| 		} | ||||
| 	}, | ||||
| 	"additionalProperties": false | ||||
|   | ||||
| @@ -6,6 +6,8 @@ | ||||
| 		"speed"            : 1.2, | ||||
| 		"alarm-color"      : [255,0,0], | ||||
| 		"post-color"       : [255,174,11], | ||||
| 		"shutdown-enabled" : false | ||||
| 		"shutdown-enabled" : false, | ||||
| 		"initial-blink"    : true, | ||||
| 		"set-post-color"   : true | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -13,21 +13,25 @@ sleepTime      = float(hyperion.args.get('speed', 1.0))*0.5 | ||||
| alarmColor     = hyperion.args.get('alarm-color', (255,0,0)) | ||||
| postColor      = hyperion.args.get('post-color', (255,174,11)) | ||||
| off            = bool(hyperion.args.get('shutdown-enabled', False)) | ||||
| initialBlink   = bool(hyperion.args.get('initial-blink', True)) | ||||
| setPostColor   = bool(hyperion.args.get('set-post-color', True)) | ||||
|  | ||||
| width          = 12 | ||||
| height         = 10 | ||||
|  | ||||
| imageData      = bytearray(height * width * (0,0,0)) | ||||
|  | ||||
| # Start the write data loop | ||||
| for i in range(6): | ||||
| 	if hyperion.abort(): | ||||
| 		off = False | ||||
| 		break | ||||
| 	if i % 2: | ||||
| 		hyperion.setColor(alarmColor[0], alarmColor[1], alarmColor[2]) | ||||
| 	else: | ||||
| 		hyperion.setColor(0, 0, 0) | ||||
| 	time.sleep(sleepTime) | ||||
| if initialBlink: | ||||
| 	for i in range(6): | ||||
| 		if hyperion.abort(): | ||||
| 			off = False | ||||
| 			break | ||||
| 		if i % 2: | ||||
| 			hyperion.setColor(alarmColor[0], alarmColor[1], alarmColor[2]) | ||||
| 		else: | ||||
| 			hyperion.setColor(0, 0, 0) | ||||
| 		time.sleep(sleepTime) | ||||
|  | ||||
| for y in range(height,0,-1): | ||||
| 	if hyperion.abort(): | ||||
| @@ -39,11 +43,12 @@ for y in range(height,0,-1): | ||||
| 	time.sleep(sleepTime) | ||||
| time.sleep(1) | ||||
|  | ||||
| for y in range(height): | ||||
| 	for x in range(width): | ||||
| 		setPixel(x, y, postColor) | ||||
| hyperion.setImage(width, height, imageData) | ||||
| time.sleep(2) | ||||
| if setPostColor: | ||||
| 	for y in range(height): | ||||
| 		for x in range(width): | ||||
| 			setPixel(x, y, postColor) | ||||
| 	hyperion.setImage(width, height, imageData) | ||||
| 	time.sleep(2) | ||||
|  | ||||
| if off and not hyperion.abort(): | ||||
| 	subprocess.call("halt") | ||||
|   | ||||
| @@ -6,6 +6,7 @@ LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig) | ||||
| 	, _ligthBerryAPA102Mode(false) | ||||
| { | ||||
| 	_deviceReady = init(deviceConfig); | ||||
| 	connect(this,SIGNAL(receivedData(QByteArray)),this,SLOT(receivedData(QByteArray))); | ||||
| } | ||||
|  | ||||
| LedDevice* LedDeviceAdalight::construct(const QJsonObject &deviceConfig) | ||||
| @@ -74,3 +75,7 @@ int LedDeviceAdalight::write(const std::vector<ColorRgb> & ledValues) | ||||
| 	return writeBytes(_ledBuffer.size(), _ledBuffer.data()); | ||||
| } | ||||
|  | ||||
| void LedDeviceAdalight::receivedData(QByteArray data) | ||||
| { | ||||
| 	Debug(_log, ">>received %d bytes data", data.size()); | ||||
| } | ||||
|   | ||||
| @@ -22,6 +22,9 @@ public: | ||||
|  | ||||
| 	virtual bool init(const QJsonObject &deviceConfig); | ||||
|  | ||||
| public slots: | ||||
| 	void receivedData(QByteArray data); | ||||
|  | ||||
| private: | ||||
| 	/// | ||||
| 	/// Writes the led color values to the led-device | ||||
| @@ -32,6 +35,6 @@ private: | ||||
| 	virtual int write(const std::vector<ColorRgb> & ledValues); | ||||
| 	 | ||||
| 	const short _headerSize; | ||||
| 	bool _ligthBerryAPA102Mode; | ||||
| 	bool        _ligthBerryAPA102Mode; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,14 @@ LedDeviceDMX::LedDeviceDMX(const QJsonObject &deviceConfig) | ||||
| 	, _dmxSlotsPerLed(3) | ||||
| 	, _dmxLedCount(0) | ||||
| 	, _dmxChannelCount(0) | ||||
| { | ||||
| 	_deviceReady = init(deviceConfig); | ||||
| } | ||||
|  | ||||
| bool LedDeviceDMX::init(const QJsonObject &deviceConfig) | ||||
| { | ||||
| 	ProviderRs232::init(deviceConfig); | ||||
|  | ||||
| 	std::string _dmxString = deviceConfig["dmxdevice"].toString("invalid").toStdString(); | ||||
| 	if (_dmxString == "raw") | ||||
| 	{ | ||||
| @@ -40,6 +46,8 @@ LedDeviceDMX::LedDeviceDMX(const QJsonObject &deviceConfig) | ||||
|  | ||||
| 	_ledBuffer.resize(_dmxChannelCount, 0); | ||||
| 	_ledBuffer[0] = 0x00;	// NULL START code | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| LedDevice* LedDeviceDMX::construct(const QJsonObject &deviceConfig) | ||||
|   | ||||
| @@ -18,6 +18,8 @@ public: | ||||
|  | ||||
| 	/// constructs leddevice | ||||
| 	static LedDevice* construct(const QJsonObject &deviceConfig); | ||||
| 	 | ||||
| 	virtual bool init(const QJsonObject &deviceConfig); | ||||
|  | ||||
| private: | ||||
| 	/// | ||||
|   | ||||
| @@ -51,9 +51,9 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig) | ||||
| 	const QJsonArray whitePointConfig = deviceConfig["whitePoint"].toArray(); | ||||
| 	if ( !whitePointConfig.isEmpty() && whitePointConfig.size() == 3 ) | ||||
| 	{ | ||||
| 		_whitePoint_r = whitePointConfig[0].toDouble(); | ||||
| 		_whitePoint_g = whitePointConfig[1].toDouble(); | ||||
| 		_whitePoint_b = whitePointConfig[2].toDouble(); | ||||
| 		_whitePoint_r = whitePointConfig[0].toDouble() / 255.0; | ||||
| 		_whitePoint_g = whitePointConfig[1].toDouble() / 255.0; | ||||
| 		_whitePoint_b = whitePointConfig[2].toDouble() / 255.0; | ||||
| 	} | ||||
|  | ||||
| 	_opc_data.resize( _ledRGBCount + OPC_HEADER_SIZE ); | ||||
|   | ||||
| @@ -20,7 +20,7 @@ LedDevice* LedDeviceSedu::construct(const QJsonObject &deviceConfig) | ||||
| bool LedDeviceSedu::init(const QJsonObject &deviceConfig) | ||||
| { | ||||
| 	ProviderRs232::init(deviceConfig); | ||||
| 	 | ||||
|  | ||||
| 	std::vector<FrameSpec> frameSpecs{{0xA1, 256}, {0xA2, 512}, {0xB0, 768}, {0xB1, 1536}, {0xB2, 3072} }; | ||||
|  | ||||
| 	for (const FrameSpec& frameSpec : frameSpecs) | ||||
|   | ||||
| @@ -5,6 +5,9 @@ | ||||
|  | ||||
| // Qt includes | ||||
| #include <QTimer> | ||||
| #include <QDateTime> | ||||
| #include <QFile> | ||||
| #include <QSerialPortInfo> | ||||
|  | ||||
| // Local Hyperion includes | ||||
| #include "ProviderRs232.h" | ||||
| @@ -17,6 +20,9 @@ ProviderRs232::ProviderRs232() | ||||
| 	, _bytesWritten(0) | ||||
| 	, _frameDropCounter(0) | ||||
| 	, _lastError(QSerialPort::NoError) | ||||
| 	, _preOpenDelayTimeOut(0) | ||||
| 	, _preOpenDelay(2000) | ||||
| 	, _enableAutoDeviceName(false) | ||||
| { | ||||
| 	connect(&_rs232Port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(error(QSerialPort::SerialPortError))); | ||||
| 	connect(&_rs232Port, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64))); | ||||
| @@ -29,13 +35,30 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig) | ||||
|  | ||||
| 	LedDevice::init(deviceConfig); | ||||
|  | ||||
| 	_deviceName           = deviceConfig["output"].toString().toStdString(); | ||||
| 	_deviceName           = deviceConfig["output"].toString("auto"); | ||||
| 	_enableAutoDeviceName = _deviceName == "auto"; | ||||
| 	_baudRate_Hz          = deviceConfig["rate"].toInt(); | ||||
| 	_delayAfterConnect_ms = deviceConfig["delayAfterConnect"].toInt(250); | ||||
| 	_delayAfterConnect_ms = deviceConfig["delayAfterConnect"].toInt(1500); | ||||
| 	_preOpenDelay         = deviceConfig["delayBeforeConnect"].toInt(1500); | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| QString ProviderRs232::findSerialDevice() | ||||
| { | ||||
| 	// take first available usb serial port - currently no probing! | ||||
| 	for( auto port : QSerialPortInfo::availablePorts()) | ||||
| 	{ | ||||
| 		if (port.hasProductIdentifier() && port.hasVendorIdentifier() && !port.isBusy()) | ||||
| 		{ | ||||
| 			Info(_log, "found serial device: %s", port.systemLocation().toLocal8Bit().constData()); | ||||
| 			return port.systemLocation(); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	return ""; | ||||
| } | ||||
|  | ||||
| void ProviderRs232::bytesWritten(qint64 bytes) | ||||
| { | ||||
| 	_bytesWritten += bytes; | ||||
| @@ -49,8 +72,8 @@ void ProviderRs232::bytesWritten(qint64 bytes) | ||||
|  | ||||
| void ProviderRs232::readyRead() | ||||
| { | ||||
| 	QByteArray data = _rs232Port.readAll(); | ||||
| 	Debug(_log, "received %d bytes data", data.size()); | ||||
| 	emit receivedData(_rs232Port.readAll()); | ||||
| 	Debug(_log, "received data"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -66,7 +89,9 @@ void ProviderRs232::error(QSerialPort::SerialPortError error) | ||||
| 			case QSerialPort::DeviceNotFoundError: | ||||
| 				Error(_log, "An error occurred while attempting to open an non-existing device."); break; | ||||
| 			case QSerialPort::PermissionError: | ||||
| 				Error(_log, "An error occurred while attempting to open an already opened device by another process or a user not having enough permission and credentials to open."); break; | ||||
| 				Error(_log, "An error occurred while attempting to open an already opened device by another process or a user not having enough permission and credentials to open. Device disabled."); | ||||
| 				_deviceReady = false; | ||||
| 				break; | ||||
| 			case QSerialPort::OpenError: | ||||
| 				Error(_log, "An error occurred while attempting to open an already opened device in this object."); break; | ||||
| 			case QSerialPort::NotOpenError: | ||||
| @@ -84,10 +109,14 @@ void ProviderRs232::error(QSerialPort::SerialPortError error) | ||||
| 			case QSerialPort::ResourceError: | ||||
| 				Error(_log, "An I/O error occurred when a resource becomes unavailable, e.g. when the device is unexpectedly removed from the system."); break; | ||||
| 			case QSerialPort::UnsupportedOperationError: | ||||
| 				Error(_log, "The requested device operation is not supported or prohibited by the running operating system."); break; | ||||
| 				Error(_log, "The requested device operation is not supported or prohibited by the running operating system. Device disabled."); | ||||
| 				_deviceReady = false; | ||||
| 				break; | ||||
| 			case QSerialPort::TimeoutError: | ||||
| 				Error(_log, "A timeout error occurred."); break; | ||||
| 			default: Error(_log,"An unidentified error occurred. (%d)", error); | ||||
| 			default:  | ||||
| 				Error(_log,"An unidentified error occurred. Device disabled. (%d)", error); | ||||
| 				_deviceReady = false; | ||||
| 			} | ||||
| 			_rs232Port.clearError(); | ||||
| 			closeDevice(); | ||||
| @@ -106,35 +135,60 @@ void ProviderRs232::closeDevice() | ||||
| 	if (_rs232Port.isOpen()) | ||||
| 	{ | ||||
| 		_rs232Port.close(); | ||||
| 		Debug(_log,"Close UART: %s", _deviceName.c_str()); | ||||
| 		Debug(_log,"Close UART: %s", _deviceName.toLocal8Bit().constData()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int ProviderRs232::open() | ||||
| { | ||||
| 	Info(_log, "Opening UART: %s", _deviceName.c_str()); | ||||
| 	_rs232Port.setPortName(_deviceName.c_str()); | ||||
|  | ||||
| 	return tryOpen(_delayAfterConnect_ms) ? 0 : -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool ProviderRs232::tryOpen(const int delayAfterConnect_ms) | ||||
| { | ||||
| 	if (_deviceName.isEmpty() || _rs232Port.portName().isEmpty()) | ||||
| 	{ | ||||
| 		if ( _enableAutoDeviceName ) | ||||
| 		{ | ||||
| 			_deviceName = findSerialDevice(); | ||||
| 			if ( _deviceName.isEmpty() ) | ||||
| 			{ | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 		Info(_log, "Opening UART: %s", _deviceName.toLocal8Bit().constData()); | ||||
| 		_rs232Port.setPortName(_deviceName); | ||||
| 	} | ||||
|  | ||||
| 	if ( ! _rs232Port.isOpen() ) | ||||
| 	{ | ||||
| 		if ( ! _rs232Port.open(QIODevice::ReadWrite) ) | ||||
| 		_frameDropCounter = 0; | ||||
| 		if (QFile::exists(_deviceName)) | ||||
| 		{ | ||||
| 			if ( _stateChanged ) | ||||
| 			if ( _preOpenDelayTimeOut > QDateTime::currentMSecsSinceEpoch() ) | ||||
| 			{ | ||||
| 				Error(_log, "Unable to open RS232 device (%s)", _deviceName.c_str()); | ||||
| 				_stateChanged = false; | ||||
| 				return false; | ||||
| 			} | ||||
| 			if ( ! _rs232Port.open(QIODevice::ReadWrite) ) | ||||
| 			{ | ||||
| 				if ( _stateChanged ) | ||||
| 				{ | ||||
| 					Error(_log, "Unable to open RS232 device (%s)", _deviceName.toLocal8Bit().constData()); | ||||
| 					_stateChanged = false; | ||||
| 				} | ||||
| 				return false; | ||||
| 			} | ||||
| 			Debug(_log, "Setting baud rate to %d", _baudRate_Hz); | ||||
| 			_rs232Port.setBaudRate(_baudRate_Hz); | ||||
| 			_stateChanged = true; | ||||
| 			_preOpenDelayTimeOut = 0; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			_preOpenDelayTimeOut = QDateTime::currentMSecsSinceEpoch() + _preOpenDelay; | ||||
| 			return false; | ||||
| 		} | ||||
| 		Debug(_log, "Setting baud rate to %d", _baudRate_Hz); | ||||
| 		_rs232Port.setBaudRate(_baudRate_Hz); | ||||
| 		_stateChanged = true; | ||||
| 	} | ||||
|  | ||||
| 	if (delayAfterConnect_ms > 0) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include <QObject> | ||||
| #include <QSerialPort> | ||||
| #include <QTimer> | ||||
| #include <QString> | ||||
|  | ||||
| // Leddevice includes | ||||
| #include <leddevice/LedDevice.h> | ||||
| @@ -39,6 +40,19 @@ public: | ||||
| 	/// | ||||
| 	int open(); | ||||
|  | ||||
| private slots: | ||||
| 	/// Write the last data to the leds again | ||||
| 	int rewriteLeds(); | ||||
|  | ||||
| 	/// Unblock the device after a connection delay | ||||
| 	void unblockAfterDelay(); | ||||
| 	void error(QSerialPort::SerialPortError error); | ||||
| 	void bytesWritten(qint64 bytes); | ||||
| 	void readyRead(); | ||||
|  | ||||
| signals: | ||||
| 	void receivedData(QByteArray data); | ||||
|  | ||||
| protected: | ||||
| 	/** | ||||
| 	 * Writes the given bytes to the RS232-device and | ||||
| @@ -52,22 +66,14 @@ protected: | ||||
|  | ||||
| 	void closeDevice(); | ||||
|  | ||||
| private slots: | ||||
| 	/// Write the last data to the leds again | ||||
| 	int rewriteLeds(); | ||||
| 	QString findSerialDevice(); | ||||
|  | ||||
| 	/// Unblock the device after a connection delay | ||||
| 	void unblockAfterDelay(); | ||||
| 	void error(QSerialPort::SerialPortError error); | ||||
| 	void bytesWritten(qint64 bytes); | ||||
| 	void readyRead(); | ||||
|  | ||||
| protected: | ||||
| 	// tries to open device if not opened | ||||
| 	bool tryOpen(const int delayAfterConnect_ms); | ||||
| 	 | ||||
|  | ||||
|  | ||||
| 	/// The name of the output device | ||||
| 	std::string _deviceName; | ||||
| 	QString _deviceName; | ||||
|  | ||||
| 	/// The used baudrate of the output device | ||||
| 	qint32 _baudRate_Hz; | ||||
| @@ -86,4 +92,7 @@ protected: | ||||
| 	qint64 _bytesWritten; | ||||
| 	qint64 _frameDropCounter; | ||||
| 	QSerialPort::SerialPortError _lastError; | ||||
| 	qint64                       _preOpenDelayTimeOut; | ||||
| 	int                          _preOpenDelay; | ||||
| 	bool                         _enableAutoDeviceName; | ||||
| }; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| 		"output": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_dev_spec_outputPath_title", | ||||
| 			"default":"/dev/ttyUSB0", | ||||
| 			"default":"/dev/ttyACM0", | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"rate": { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 		"output": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_dev_spec_outputPath_title", | ||||
| 			"default":"/dev/ttyUSB0", | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"rate": { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 		"output": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_dev_spec_outputPath_title", | ||||
| 			"default":"/dev/ttyUSB0", | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"rate": { | ||||
| @@ -18,13 +19,6 @@ | ||||
| 			"title":"edt_dev_spec_delayAfterConnect_title", | ||||
| 			"default": 250, | ||||
| 			"propertyOrder" : 3 | ||||
| 		}, | ||||
| 		"rewriteTime": { | ||||
| 			"type": "integer", | ||||
| 			"title":"edt_dev_spec_rewriteTime_title", | ||||
| 			"default": 5000, | ||||
| 			"append" : "ms", | ||||
| 			"propertyOrder" : 4 | ||||
| 		} | ||||
| 	}, | ||||
| 	"additionalProperties": true | ||||
|   | ||||
| @@ -55,15 +55,15 @@ | ||||
| 			"type" : "array", | ||||
| 			"title" : "edt_dev_spec_whitepoint_title", | ||||
| 			"propertyOrder" : 9, | ||||
| 			"default" : [1.0,1.0,1.0], | ||||
| 			"default" : [255,255,255], | ||||
| 			"maxItems" : 3, | ||||
| 			"minItems" : 3, | ||||
| 			"format" : "table", | ||||
| 			"format" : "colorpicker", | ||||
| 			"items" : { | ||||
| 				"type" : "number", | ||||
| 				"minimum" : 0.0, | ||||
| 				"maximum": 1.0, | ||||
| 				"default" : 1.0 | ||||
| 				"type" : "integer", | ||||
| 				"minimum" : 0, | ||||
| 				"maximum": 255, | ||||
| 				"default" : 255 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 		"output": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_dev_spec_outputPath_title", | ||||
| 			"default":"/dev/ttyACM0", | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"rate": { | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 		"output": { | ||||
| 			"type": "string", | ||||
| 			"title":"edt_dev_spec_outputPath_title", | ||||
| 			"default":"/dev/ttyACM0", | ||||
| 			"propertyOrder" : 1 | ||||
| 		}, | ||||
| 		"rate": { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #!/usr/bin/env python | ||||
| import simplejson, sys, glob | ||||
| import json, sys, glob | ||||
| from os import path | ||||
| from jsonschema import Draft3Validator | ||||
|  | ||||
| @@ -12,14 +12,14 @@ retval  = 0 | ||||
| total   = 0 | ||||
| errors  = 0 | ||||
| with open("libsrc/effectengine/EffectDefinition.schema.json") as baseSchemaFile: | ||||
| 	baseSchema = simplejson.load(baseSchemaFile) | ||||
| 	baseSchema = json.loads(baseSchemaFile.read().decode('utf-8-sig')) | ||||
| 	baseValidator = Draft3Validator(baseSchema) | ||||
| 	for filename in glob.glob(jsonFiles+'/*.json'): | ||||
| 		with open(filename) as f: | ||||
| 			total += 1 | ||||
| 			msg = "   check effect %s ... " % filename | ||||
| 			try: | ||||
| 				effect = simplejson.load(f) | ||||
| 				effect = json.loads(f.read().decode('utf-8-sig')) | ||||
| 				script = path.basename(effect['script']) | ||||
| 				if not path.exists(jsonFiles+'/'+script): | ||||
| 					raise ValueError('script file: '+script+' not found.') | ||||
| @@ -31,7 +31,7 @@ with open("libsrc/effectengine/EffectDefinition.schema.json") as baseSchemaFile: | ||||
| 				 | ||||
| 				# validate against schema | ||||
| 				with open(schema) as s: | ||||
| 					effectSchema = simplejson.load(s) | ||||
| 					effectSchema = json.loads(s.read().decode('utf-8-sig')) | ||||
| 					Draft3Validator.check_schema(effectSchema) | ||||
| 					validator = Draft3Validator(effectSchema) | ||||
| 					baseValidator.validate(effect) | ||||
|   | ||||
| @@ -11,10 +11,10 @@ for filename in sys.argv[1:]: | ||||
| 		total += 1 | ||||
| 		msg = "   check json %s ... " % filename | ||||
| 		try: | ||||
| 			json.load(f) | ||||
| 			json.loads(f.read().decode('utf-8-sig')) | ||||
| 			#print(msg + "ok") | ||||
| 		except ValueError as e: | ||||
| 			print(msg + 'invalid') | ||||
| 			print(msg + 'invalid ('+str(e)+')') | ||||
| 			retval = 1 | ||||
| 			errors += 1 | ||||
|  | ||||
|   | ||||
| @@ -11,10 +11,10 @@ schemaFileName = sys.argv[2] | ||||
| try: | ||||
| 	with open(schemaFileName) as schemaFile: | ||||
| 		with open(jsonFileName) as jsonFile: | ||||
| 			j = json.load(jsonFile) | ||||
| 			validator = Draft3Validator(json.load(schemaFile)) | ||||
| 			j = json.loads(jsonFile.read().decode('utf-8-sig')) | ||||
| 			validator = Draft3Validator(json.loads(schemaFile.read().decode('utf-8-sig'))) | ||||
| 			validator.validate(j) | ||||
| except Exception as  e: | ||||
| except Exception as e: | ||||
| 	print('validation error: '+jsonFileName + ' '+schemaFileName+' ('+str(e)+')') | ||||
| 	sys.exit(1) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user