kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			New flexible usermod for seven segment displays (#2409)
* add first version * added max/min brightness to autoldr functionality * added more information to the readmepull/2415/head
							rodzic
							
								
									fb338c0728
								
							
						
					
					
						commit
						d3f35955d6
					
				|  | @ -0,0 +1,129 @@ | ||||||
|  | # Seven Segment Display Reloaded | ||||||
|  | 
 | ||||||
|  | Usermod that uses the overlay feature to create a configurable seven segment display. | ||||||
|  | Optimized for maximum configurability and use with seven segment clocks by parallyze (https://www.instructables.com/member/parallyze/instructables/) | ||||||
|  | Very loosely based on the existing usermod "seven segment display". | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## Installation | ||||||
|  | 
 | ||||||
|  | Add the compile-time option `-D USERMOD_SSDR` to your `platformio.ini` (or `platformio_override.ini`) or use `#define USERMOD_SSDR` in `my_config.h`. | ||||||
|  | 
 | ||||||
|  | For the auto brightness option, the usermod SN_Photoresistor has to be installed as well. See SN_Photoresistor/readme.md for instructions. | ||||||
|  | 
 | ||||||
|  | ## Settings | ||||||
|  | All settings can be controlled the usermod setting page. | ||||||
|  | Part of the settings can be controlled through MQTT with a raw payload or through a json request to /json/state. | ||||||
|  | 
 | ||||||
|  | ### enabled | ||||||
|  | Enables/disables this overlay usermod | ||||||
|  | 
 | ||||||
|  | ### inverted | ||||||
|  | Enables the inverted mode in which the background should be enabled and the digits should be black (leds off) | ||||||
|  | 
 | ||||||
|  | ### Colon-blinking | ||||||
|  | Enables the blinking colon(s) if they are defined | ||||||
|  | 
 | ||||||
|  | ### enable-auto-brightness | ||||||
|  | Enables the auto brightness feature. Can be only used with the usermod SN_Photoresistor installed. | ||||||
|  | 
 | ||||||
|  | ### auto-brightness-min / auto-brightness-max | ||||||
|  | The lux value calculated from usermod SN_Photoresistor will be mapped to the values defined here. | ||||||
|  | The mapping is 0 - 1000 lux will be mapped to auto-brightness-min - auto-brightness-max | ||||||
|  | 
 | ||||||
|  | The mA current protection of WLED will override the calculated value if it is too high. | ||||||
|  | 
 | ||||||
|  | ### Display-Mask | ||||||
|  | Defines the type of the time/date display.  | ||||||
|  | For example "H:m" (default) | ||||||
|  | - H - 00-23 hours | ||||||
|  | - h - 01-12 hours | ||||||
|  | - k - 01-24 hours | ||||||
|  | - m - 00-59 minutes | ||||||
|  | - s - 00-59 seconds | ||||||
|  | - d - 01-31 day of month | ||||||
|  | - M - 01-12 month | ||||||
|  | - y - 21 last two positions of year | ||||||
|  | - Y - 2021 year | ||||||
|  | - : for a colon | ||||||
|  | 
 | ||||||
|  | ### LED-Numbers | ||||||
|  | - LED-Numbers-Hours | ||||||
|  | - LED-Numbers-Minutes | ||||||
|  | - LED-Numbers-Seconds | ||||||
|  | - LED-Numbers-Colons | ||||||
|  | - LED-Numbers-Day | ||||||
|  | - LED-Numbers-Month | ||||||
|  | - LED-Numbers-Year | ||||||
|  | 
 | ||||||
|  | See following example for usage. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## Example | ||||||
|  | 
 | ||||||
|  | Example for Leds definition | ||||||
|  | ``` | ||||||
|  |   <  A  > | ||||||
|  | /\       /\ | ||||||
|  | F        B | ||||||
|  | \/       \/ | ||||||
|  |   <  G  > | ||||||
|  | /\       /\ | ||||||
|  | E        C | ||||||
|  | \/       \/ | ||||||
|  |   <  D  > | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Leds or Range of Leds are seperated by a comma "," | ||||||
|  | 
 | ||||||
|  | Segments are seperated by a semicolon ";" and are read as A;B;C;D;E;F;G | ||||||
|  | 
 | ||||||
|  | Digits are seperated by colon ":" -> A;B;C;D;E;F;G:A;B;C;D;E;F;G | ||||||
|  | 
 | ||||||
|  | Ranges are defined as lower to higher (lower first) | ||||||
|  | 
 | ||||||
|  | For example, an clock definition for the following clock (https://www.instructables.com/Lazy-7-Quick-Build-Edition/) is | ||||||
|  | 
 | ||||||
|  | - hour "59,46;47-48;50-51;52-53;54-55;57-58;49,56:0,13;1-2;4-5;6-7;8-9;11-12;3,10" | ||||||
|  | 
 | ||||||
|  | - minute "37-38;39-40;42-43;44,31;32-33;35-36;34,41:21-22;23-24;26-27;28,15;16-17;19-20;18,25" | ||||||
|  | 
 | ||||||
|  | or | ||||||
|  | 
 | ||||||
|  | - hour "6,7;8,9;11,12;13,0;1,2;4,5;3,10:52,53;54,55;57,58;59,46;47,48;50,51;49,56" | ||||||
|  | 
 | ||||||
|  | - minute "15,28;16,17;19,20;21,22;23,24;26,27;18,25:31,44;32,33;35,36;37,38;39,40;42,43;34,41" | ||||||
|  | 
 | ||||||
|  | depending on the orientation. | ||||||
|  | 
 | ||||||
|  | # The example detailed: | ||||||
|  | hour "59,46;47-48;50-51;52-53;54-55;57-58;49,56:0,13;1-2;4-5;6-7;8-9;11-12;3,10" | ||||||
|  | 
 | ||||||
|  | there are two digits seperated by ":" | ||||||
|  | 
 | ||||||
|  | - 59,46;47-48;50-51;52-53;54-55;57-58;49,56 | ||||||
|  | - 0,13;1-2;4-5;6-7;8-9;11-12;3,10 | ||||||
|  | 
 | ||||||
|  | In the first digit,  | ||||||
|  | the **segment A** consists of the leds number **59 and 46**., **segment B** consists of the leds number **47, 48** and so on | ||||||
|  | 
 | ||||||
|  | The second digit starts again with **segment A** and leds **0 and 13**, **segment B** consists of the leds number **1 and 2** and so on | ||||||
|  | 
 | ||||||
|  | ### first digit of the hour | ||||||
|  | - Segment A: 59, 46 | ||||||
|  | - Segment B: 47, 48 | ||||||
|  | - Segment C: 50, 51 | ||||||
|  | - Segment D: 52, 53 | ||||||
|  | - Segment E: 54, 55 | ||||||
|  | - Segment F: 57, 58 | ||||||
|  | - Segment G: 49, 56 | ||||||
|  | 
 | ||||||
|  | ### second digit of the hour | ||||||
|  | 
 | ||||||
|  | - Segment A: 0, 13 | ||||||
|  | - Segment B: 1, 2 | ||||||
|  | - Segment C: 4, 5 | ||||||
|  | - Segment D: 6, 7 | ||||||
|  | - Segment E: 8, 9 | ||||||
|  | - Segment F: 11, 12 | ||||||
|  | - Segment G: 3, 10 | ||||||
|  | @ -0,0 +1,544 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "wled.h" | ||||||
|  | 
 | ||||||
|  | class UsermodSSDR : public Usermod { | ||||||
|  | 
 | ||||||
|  | //#define REFRESHTIME 497
 | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   //Runtime variables.
 | ||||||
|  |   unsigned long umSSDRLastRefresh = 0; | ||||||
|  |   unsigned long umSSDRResfreshTime = 3000; | ||||||
|  |   bool umSSDRDisplayTime = false; | ||||||
|  |   bool umSSDRInverted = false; | ||||||
|  |   bool umSSDRColonblink = true; | ||||||
|  |   bool umSSDREnableLDR = false; | ||||||
|  |   String umSSDRHours = ""; | ||||||
|  |   String umSSDRMinutes = ""; | ||||||
|  |   String umSSDRSeconds = ""; | ||||||
|  |   String umSSDRColons = ""; | ||||||
|  |   String umSSDRDays = ""; | ||||||
|  |   String umSSDRMonths = ""; | ||||||
|  |   String umSSDRYears = ""; | ||||||
|  |   uint16_t umSSDRLength = 0; | ||||||
|  |   uint16_t umSSDRBrightnessMin = 0; | ||||||
|  |   uint16_t umSSDRBrightnessMax = 255; | ||||||
|  | 
 | ||||||
|  |   bool* umSSDRMask = 0; | ||||||
|  | 
 | ||||||
|  |   /*//  H - 00-23 hours
 | ||||||
|  |     //  h - 01-12 hours
 | ||||||
|  |     //  k - 01-24 hours
 | ||||||
|  |     //  m - 00-59 minutes
 | ||||||
|  |     //  s - 00-59 seconds
 | ||||||
|  |     //  d - 01-31 day of month
 | ||||||
|  |     //  M - 01-12 month
 | ||||||
|  |     //  y - 21 last two positions of year
 | ||||||
|  |     //  Y - 2021 year
 | ||||||
|  |     //  : for a colon
 | ||||||
|  |     */ | ||||||
|  |   String umSSDRDisplayMask = "H:m"; //This should reflect physical equipment.
 | ||||||
|  | 
 | ||||||
|  |   /* Segment order, seen from the front:
 | ||||||
|  | 
 | ||||||
|  |       <  A  > | ||||||
|  |     /\       /\ | ||||||
|  |     F        B | ||||||
|  |     \/       \/ | ||||||
|  |       <  G  > | ||||||
|  |     /\       /\ | ||||||
|  |     E        C | ||||||
|  |     \/       \/ | ||||||
|  |       <  D  > | ||||||
|  | 
 | ||||||
|  |   */ | ||||||
|  | 
 | ||||||
|  |   uint8_t umSSDRNumbers[11][7] = { | ||||||
|  |     //  A    B    C    D    E    F    G
 | ||||||
|  |     {   1,   1,   1,   1,   1,   1,   0 },  // 0
 | ||||||
|  |     {   0,   1,   1,   0,   0,   0,   0 },  // 1
 | ||||||
|  |     {   1,   1,   0,   1,   1,   0,   1 },  // 2
 | ||||||
|  |     {   1,   1,   1,   1,   0,   0,   1 },  // 3
 | ||||||
|  |     {   0,   1,   1,   0,   0,   1,   1 },  // 4
 | ||||||
|  |     {   1,   0,   1,   1,   0,   1,   1 },  // 5
 | ||||||
|  |     {   1,   0,   1,   1,   1,   1,   1 },  // 6
 | ||||||
|  |     {   1,   1,   1,   0,   0,   0,   0 },  // 7
 | ||||||
|  |     {   1,   1,   1,   1,   1,   1,   1 },  // 8
 | ||||||
|  |     {   1,   1,   1,   1,   0,   1,   1 }   // 9
 | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   //String to reduce flash memory usage
 | ||||||
|  |   static const char _str_name[]; | ||||||
|  |   static const char _str_ldrEnabled[]; | ||||||
|  |   static const char _str_timeEnabled[]; | ||||||
|  |   static const char _str_inverted[]; | ||||||
|  |   static const char _str_colonblink[]; | ||||||
|  |   static const char _str_displayMask[]; | ||||||
|  |   static const char _str_hours[]; | ||||||
|  |   static const char _str_minutes[]; | ||||||
|  |   static const char _str_seconds[]; | ||||||
|  |   static const char _str_colons[]; | ||||||
|  |   static const char _str_days[]; | ||||||
|  |   static const char _str_months[]; | ||||||
|  |   static const char _str_years[]; | ||||||
|  |   static const char _str_minBrightness[]; | ||||||
|  |   static const char _str_maxBrightness[]; | ||||||
|  | 
 | ||||||
|  | #ifdef USERMOD_ID_SN_PHOTORESISTOR | ||||||
|  |   Usermod_SN_Photoresistor *ptr; | ||||||
|  | #else | ||||||
|  |   void* ptr = nullptr; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   void _overlaySevenSegmentDraw() { | ||||||
|  |     int displayMaskLen = static_cast<int>(umSSDRDisplayMask.length()); | ||||||
|  |     bool colonsDone = false; | ||||||
|  |     _setAllFalse(); | ||||||
|  |     for (int index = 0; index < displayMaskLen; index++) { | ||||||
|  |       int timeVar = 0; | ||||||
|  |       switch (umSSDRDisplayMask[index]) { | ||||||
|  |         case 'h': | ||||||
|  |           timeVar = hourFormat12(localTime); | ||||||
|  |           _showElements(&umSSDRHours, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'H': | ||||||
|  |           timeVar = hour(localTime); | ||||||
|  |           _showElements(&umSSDRHours, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'k': | ||||||
|  |           timeVar = hour(localTime) + 1; | ||||||
|  |           _showElements(&umSSDRHours, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'm': | ||||||
|  |           timeVar = minute(localTime); | ||||||
|  |           _showElements(&umSSDRMinutes, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 's': | ||||||
|  |           timeVar = second(localTime); | ||||||
|  |           _showElements(&umSSDRSeconds, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'd': | ||||||
|  |           timeVar = day(localTime); | ||||||
|  |           _showElements(&umSSDRDays, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'M': | ||||||
|  |           timeVar = month(localTime); | ||||||
|  |           _showElements(&umSSDRMonths, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'y': | ||||||
|  |           timeVar = second(localTime); | ||||||
|  |           _showElements(&umSSDRYears, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case 'Y': | ||||||
|  |           timeVar = year(localTime); | ||||||
|  |           _showElements(&umSSDRYears, timeVar, 0); | ||||||
|  |           break; | ||||||
|  |         case ':': | ||||||
|  |           if (!colonsDone) { // only call _setColons once as all colons are printed when the first colon is found
 | ||||||
|  |             _setColons(); | ||||||
|  |             colonsDone = true; | ||||||
|  |           } | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     _setMaskToLeds(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _setColons() { | ||||||
|  |     if ( umSSDRColonblink ) { | ||||||
|  |       if ( second(localTime) % 2 == 0 ) { | ||||||
|  |         _showElements(&umSSDRColons, 0, 1); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       _showElements(&umSSDRColons, 0, 1); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _showElements(String *map, int timevar, bool isColon) { | ||||||
|  |     if (!(*map).equals("") && !(*map) == NULL) { | ||||||
|  |       int length = String(timevar).length(); | ||||||
|  |       bool addZero = false; | ||||||
|  |       if (length == 1) { | ||||||
|  |         length = 2; | ||||||
|  |         addZero = true; | ||||||
|  |       } | ||||||
|  |       int timeArr[length]; | ||||||
|  |       if(addZero) { | ||||||
|  |         timeArr[1] = 0; | ||||||
|  |         timeArr[0] = timevar; | ||||||
|  |       } else { | ||||||
|  |         int count = 0; | ||||||
|  |         while (timevar) { | ||||||
|  |           timeArr[count] = timevar%10; | ||||||
|  |           timevar /= 10; | ||||||
|  |           count++; | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       int colonsLen = static_cast<int>((*map).length()); | ||||||
|  |       int count = 0; | ||||||
|  |       int countSegments = 0; | ||||||
|  |       int countDigit = 0; | ||||||
|  |       bool range = false; | ||||||
|  |       int lastSeenLedNr = 0; | ||||||
|  | 
 | ||||||
|  |       for (int index = 0; index < colonsLen; index++) { | ||||||
|  |         switch ((*map)[index]) { | ||||||
|  |           case '-': | ||||||
|  |             lastSeenLedNr = _checkForNumber(count, index, map); | ||||||
|  |             count = 0; | ||||||
|  |             range = true; | ||||||
|  |             break; | ||||||
|  |           case ':': | ||||||
|  |             _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); | ||||||
|  |             count = 0; | ||||||
|  |             range = false; | ||||||
|  |             countDigit++; | ||||||
|  |             countSegments = 0; | ||||||
|  |             break; | ||||||
|  |           case ';': | ||||||
|  |             _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); | ||||||
|  |             count = 0; | ||||||
|  |             range = false; | ||||||
|  |             countSegments++; | ||||||
|  |             break; | ||||||
|  |           case ',': | ||||||
|  |             _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); | ||||||
|  |             count = 0; | ||||||
|  |             range = false; | ||||||
|  |             break; | ||||||
|  |           default: | ||||||
|  |             count++; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       _setLeds(_checkForNumber(count, colonsLen, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _setLeds(int lednr, int lastSeenLedNr, bool range, int countSegments, int number, bool colon) { | ||||||
|  | 
 | ||||||
|  |     if ((colon && umSSDRColonblink) || umSSDRNumbers[number][countSegments]) { | ||||||
|  |        | ||||||
|  |       if (range) { | ||||||
|  |         for(int i = lastSeenLedNr; i <= lednr; i++) { | ||||||
|  |           umSSDRMask[i] = true; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         umSSDRMask[lednr] = true; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _setMaskToLeds() { | ||||||
|  |     for(int i = 0; i <= umSSDRLength; i++) { | ||||||
|  |       if ((!umSSDRInverted && !umSSDRMask[i]) || (umSSDRInverted && umSSDRMask[i])) { | ||||||
|  |         strip.setPixelColor(i, 0x000000); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _setAllFalse() { | ||||||
|  |     for(int i = 0; i <= umSSDRLength; i++) { | ||||||
|  |       umSSDRMask[i] = false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   int _checkForNumber(int count, int index, String *map) { | ||||||
|  |     String number = (*map).substring(index - count, index); | ||||||
|  |     return number.toInt(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _publishMQTTint_P(const char *subTopic, int value) | ||||||
|  |   { | ||||||
|  |     if(mqtt == NULL) return; | ||||||
|  |        | ||||||
|  |     char buffer[64]; | ||||||
|  |     char valBuffer[12]; | ||||||
|  |     sprintf_P(buffer, PSTR("%s/%S/%S"), mqttDeviceTopic, _str_name, subTopic); | ||||||
|  |     sprintf_P(valBuffer, PSTR("%d"), value); | ||||||
|  |     mqtt->publish(buffer, 2, true, valBuffer); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _publishMQTTstr_P(const char *subTopic, String Value) | ||||||
|  |   { | ||||||
|  |     if(mqtt == NULL) return; | ||||||
|  |     char buffer[64]; | ||||||
|  |     sprintf_P(buffer, PSTR("%s/%S/%S"), mqttDeviceTopic, _str_name, subTopic); | ||||||
|  |     mqtt->publish(buffer, 2, true, Value.c_str(), Value.length()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool _cmpIntSetting_P(char *topic, char *payload, const char *setting, void *value) | ||||||
|  |   { | ||||||
|  |     if (strcmp_P(topic, setting) == 0) | ||||||
|  |     { | ||||||
|  |       *((int *)value) = strtol(payload, NULL, 10); | ||||||
|  |       _publishMQTTint_P(setting, *((int *)value)); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool _handleSetting(char *topic, char *payload) { | ||||||
|  |     if (_cmpIntSetting_P(topic, payload, _str_timeEnabled, &umSSDRDisplayTime)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     if (_cmpIntSetting_P(topic, payload, _str_ldrEnabled, &umSSDREnableLDR)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     if (_cmpIntSetting_P(topic, payload, _str_inverted, &umSSDRInverted)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     if (_cmpIntSetting_P(topic, payload, _str_colonblink, &umSSDRColonblink)) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     if (strcmp_P(topic, _str_displayMask) == 0) { | ||||||
|  |       umSSDRDisplayMask = String(payload); | ||||||
|  |       _publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _updateMQTT() | ||||||
|  |   { | ||||||
|  |     _publishMQTTint_P(_str_timeEnabled, umSSDRDisplayTime); | ||||||
|  |     _publishMQTTint_P(_str_ldrEnabled, umSSDREnableLDR); | ||||||
|  |     _publishMQTTint_P(_str_inverted, umSSDRInverted); | ||||||
|  |     _publishMQTTint_P(_str_colonblink, umSSDRColonblink); | ||||||
|  | 
 | ||||||
|  |     _publishMQTTstr_P(_str_hours, umSSDRHours); | ||||||
|  |     _publishMQTTstr_P(_str_minutes, umSSDRMinutes); | ||||||
|  |     _publishMQTTstr_P(_str_seconds, umSSDRSeconds); | ||||||
|  |     _publishMQTTstr_P(_str_colons, umSSDRColons); | ||||||
|  |     _publishMQTTstr_P(_str_days, umSSDRDays); | ||||||
|  |     _publishMQTTstr_P(_str_months, umSSDRMonths); | ||||||
|  |     _publishMQTTstr_P(_str_years, umSSDRYears); | ||||||
|  |     _publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask); | ||||||
|  | 
 | ||||||
|  |     _publishMQTTint_P(_str_minBrightness, umSSDRBrightnessMin); | ||||||
|  |     _publishMQTTint_P(_str_maxBrightness, umSSDRBrightnessMax); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _addJSONObject(JsonObject& root) { | ||||||
|  |     JsonObject ssdrObj = root[FPSTR(_str_name)]; | ||||||
|  |     if (ssdrObj.isNull()) { | ||||||
|  |       ssdrObj = root.createNestedObject(FPSTR(_str_name)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ssdrObj[FPSTR(_str_timeEnabled)] = umSSDRDisplayTime; | ||||||
|  |     ssdrObj[FPSTR(_str_ldrEnabled)] = umSSDREnableLDR; | ||||||
|  |     ssdrObj[FPSTR(_str_inverted)] = umSSDRInverted; | ||||||
|  |     ssdrObj[FPSTR(_str_colonblink)] = umSSDRColonblink; | ||||||
|  |     ssdrObj[FPSTR(_str_displayMask)] = umSSDRDisplayMask; | ||||||
|  |     ssdrObj[FPSTR(_str_hours)] = umSSDRHours; | ||||||
|  |     ssdrObj[FPSTR(_str_minutes)] = umSSDRMinutes; | ||||||
|  |     ssdrObj[FPSTR(_str_seconds)] = umSSDRSeconds; | ||||||
|  |     ssdrObj[FPSTR(_str_colons)] = umSSDRColons; | ||||||
|  |     ssdrObj[FPSTR(_str_days)] = umSSDRDays; | ||||||
|  |     ssdrObj[FPSTR(_str_months)] = umSSDRMonths; | ||||||
|  |     ssdrObj[FPSTR(_str_years)] = umSSDRYears; | ||||||
|  |     ssdrObj[FPSTR(_str_minBrightness)] = umSSDRBrightnessMin; | ||||||
|  |     ssdrObj[FPSTR(_str_maxBrightness)] = umSSDRBrightnessMax; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |   //Functions called by WLED
 | ||||||
|  | 
 | ||||||
|  |   /*
 | ||||||
|  |      * setup() is called once at boot. WiFi is not yet connected at this point. | ||||||
|  |      * You can use it to initialize variables, sensors or similar. | ||||||
|  |      */ | ||||||
|  |   void setup() { | ||||||
|  |     umSSDRLength = strip.getLengthTotal(); | ||||||
|  |     if (umSSDRMask != 0) { | ||||||
|  |       umSSDRMask = (bool*) realloc(umSSDRMask, umSSDRLength * sizeof(bool)); | ||||||
|  |     } else { | ||||||
|  |       umSSDRMask = (bool*) malloc(umSSDRLength * sizeof(bool)); | ||||||
|  |     } | ||||||
|  |     _setAllFalse(); | ||||||
|  | 
 | ||||||
|  |     #ifdef USERMOD_ID_SN_PHOTORESISTOR | ||||||
|  |       ptr = (Usermod_SN_Photoresistor*) usermods.lookup(USERMOD_ID_SN_PHOTORESISTOR); | ||||||
|  |     #endif | ||||||
|  |     DEBUG_PRINTLN(F("Setup done")); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /*
 | ||||||
|  |      * loop() is called continuously. Here you can check for events, read sensors, etc. | ||||||
|  |      */ | ||||||
|  |   void loop() { | ||||||
|  |     if (!umSSDRDisplayTime || strip.isUpdating()) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     #ifdef USERMOD_ID_SN_PHOTORESISTOR | ||||||
|  |       if(bri != 0 && umSSDREnableLDR && (millis() - umSSDRLastRefresh > umSSDRResfreshTime)) { | ||||||
|  |         if (ptr != nullptr) { | ||||||
|  |           uint16_t lux = ptr->getLastLDRValue(); | ||||||
|  |           uint16_t brightness = map(lux, 0, 1000, umSSDRBrightnessMin, umSSDRBrightnessMax); | ||||||
|  |           if (bri != brightness) { | ||||||
|  |             bri = brightness; | ||||||
|  |             colorUpdated(1); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         umSSDRLastRefresh = millis(); | ||||||
|  |       } | ||||||
|  |     #endif | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void handleOverlayDraw() { | ||||||
|  |     if (umSSDRDisplayTime) { | ||||||
|  |       _overlaySevenSegmentDraw(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |   * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. | ||||||
|  |   * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. | ||||||
|  |   * Below it is shown how this could be used for e.g. a light sensor | ||||||
|  |   */ | ||||||
|  |   void addToJsonInfo(JsonObject& root) { | ||||||
|  |     JsonObject user = root[F("u")]; | ||||||
|  |     if (user.isNull()) { | ||||||
|  |       user = root.createNestedObject(F("u")); | ||||||
|  |     } | ||||||
|  |     JsonArray enabled = user.createNestedArray("Time enabled"); | ||||||
|  |     enabled.add(umSSDRDisplayTime); | ||||||
|  |     JsonArray invert = user.createNestedArray("Time inverted"); | ||||||
|  |     invert.add(umSSDRInverted); | ||||||
|  |     JsonArray blink = user.createNestedArray("Blinking colon"); | ||||||
|  |     blink.add(umSSDRColonblink); | ||||||
|  |     JsonArray ldrEnable = user.createNestedArray("Auto Brightness enabled"); | ||||||
|  |     ldrEnable.add(umSSDREnableLDR); | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |  /*
 | ||||||
|  |   * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). | ||||||
|  |   * Values in the state object may be modified by connected clients | ||||||
|  |   */ | ||||||
|  |   void addToJsonState(JsonObject& root) { | ||||||
|  |     JsonObject user = root[F("u")]; | ||||||
|  |     if (user.isNull()) { | ||||||
|  |       user = root.createNestedObject(F("u")); | ||||||
|  |     } | ||||||
|  |     _addJSONObject(user); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |  /*
 | ||||||
|  |   * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). | ||||||
|  |   * Values in the state object may be modified by connected clients | ||||||
|  |   */ | ||||||
|  |   void readFromJsonState(JsonObject& root) { | ||||||
|  |     JsonObject user = root[F("u")]; | ||||||
|  |     if (!user.isNull()) { | ||||||
|  |       JsonObject ssdrObj = user[FPSTR(_str_name)]; | ||||||
|  |       umSSDRDisplayTime = ssdrObj[FPSTR(_str_timeEnabled)] | umSSDRDisplayTime; | ||||||
|  |       umSSDREnableLDR = ssdrObj[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR; | ||||||
|  |       umSSDRInverted = ssdrObj[FPSTR(_str_inverted)] | umSSDRInverted; | ||||||
|  |       umSSDRColonblink = ssdrObj[FPSTR(_str_colonblink)] | umSSDRColonblink; | ||||||
|  |       umSSDRDisplayMask = ssdrObj[FPSTR(_str_displayMask)] | umSSDRDisplayMask; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void onMqttConnect(bool sessionPresent) { | ||||||
|  |     char subBuffer[48]; | ||||||
|  |     if (mqttDeviceTopic[0] != 0) | ||||||
|  |     { | ||||||
|  |       _updateMQTT(); | ||||||
|  |       //subscribe for sevenseg messages on the device topic
 | ||||||
|  |       sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttDeviceTopic, _str_name); | ||||||
|  |       mqtt->subscribe(subBuffer, 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (mqttGroupTopic[0] != 0) | ||||||
|  |     { | ||||||
|  |       //subcribe for sevenseg messages on the group topic
 | ||||||
|  |       sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttGroupTopic, _str_name); | ||||||
|  |       mqtt->subscribe(subBuffer, 2); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool onMqttMessage(char *topic, char *payload) { | ||||||
|  |     //If topic beings iwth sevenSeg cut it off, otherwise not our message.
 | ||||||
|  |     size_t topicPrefixLen = strlen_P(PSTR("/wledSS/")); | ||||||
|  |     if (strncmp_P(topic, PSTR("/wledSS/"), topicPrefixLen) == 0) { | ||||||
|  |       topic += topicPrefixLen; | ||||||
|  |     } else { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |     //We only care if the topic ends with /set
 | ||||||
|  |     size_t topicLen = strlen(topic); | ||||||
|  |     if (topicLen > 4 && | ||||||
|  |         topic[topicLen - 4] == '/' && | ||||||
|  |         topic[topicLen - 3] == 's' && | ||||||
|  |         topic[topicLen - 2] == 'e' && | ||||||
|  |         topic[topicLen - 1] == 't') | ||||||
|  |     { | ||||||
|  |       //Trim /set and handle it
 | ||||||
|  |       topic[topicLen - 4] = '\0'; | ||||||
|  |       _handleSetting(topic, payload); | ||||||
|  |     } | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void addToConfig(JsonObject &root) { | ||||||
|  |      _addJSONObject(root); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool readFromConfig(JsonObject &root) { | ||||||
|  |     JsonObject top = root[FPSTR(_str_name)]; | ||||||
|  | 
 | ||||||
|  |     if (top.isNull()) { | ||||||
|  |       DEBUG_PRINT(FPSTR(_str_name)); | ||||||
|  |       DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     umSSDRDisplayTime      = (top[FPSTR(_str_timeEnabled)] | umSSDRDisplayTime); | ||||||
|  |     umSSDREnableLDR        = (top[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR); | ||||||
|  |     umSSDRInverted         = (top[FPSTR(_str_inverted)] | umSSDRInverted); | ||||||
|  |     umSSDRColonblink       = (top[FPSTR(_str_colonblink)] | umSSDRColonblink); | ||||||
|  | 
 | ||||||
|  |     umSSDRDisplayMask      = top[FPSTR(_str_displayMask)] | umSSDRDisplayMask; | ||||||
|  |     umSSDRHours            = top[FPSTR(_str_hours)] | umSSDRHours; | ||||||
|  |     umSSDRMinutes          = top[FPSTR(_str_minutes)] | umSSDRMinutes; | ||||||
|  |     umSSDRSeconds          = top[FPSTR(_str_seconds)] | umSSDRSeconds; | ||||||
|  |     umSSDRColons           = top[FPSTR(_str_colons)] | umSSDRColons; | ||||||
|  |     umSSDRDays             = top[FPSTR(_str_days)] | umSSDRDays; | ||||||
|  |     umSSDRMonths           = top[FPSTR(_str_months)] | umSSDRMonths; | ||||||
|  |     umSSDRYears            = top[FPSTR(_str_years)] | umSSDRYears; | ||||||
|  |     umSSDRBrightnessMin    = top[FPSTR(_str_minBrightness)] | umSSDRBrightnessMin; | ||||||
|  |     umSSDRBrightnessMax    = top[FPSTR(_str_maxBrightness)] | umSSDRBrightnessMax; | ||||||
|  | 
 | ||||||
|  |     DEBUG_PRINT(FPSTR(_str_name)); | ||||||
|  |     DEBUG_PRINTLN(F(" config (re)loaded.")); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |   /*
 | ||||||
|  |      * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). | ||||||
|  |      * This could be used in the future for the system to determine whether your usermod is installed. | ||||||
|  |      */ | ||||||
|  |   uint16_t getId() { | ||||||
|  |     return USERMOD_ID_SSDR; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const char UsermodSSDR::_str_name[]        PROGMEM = "UsermodSSDR"; | ||||||
|  | const char UsermodSSDR::_str_timeEnabled[] PROGMEM = "enabled"; | ||||||
|  | const char UsermodSSDR::_str_inverted[]    PROGMEM = "inverted"; | ||||||
|  | const char UsermodSSDR::_str_colonblink[]  PROGMEM = "Colon-blinking"; | ||||||
|  | const char UsermodSSDR::_str_displayMask[] PROGMEM = "Display-Mask"; | ||||||
|  | const char UsermodSSDR::_str_hours[]       PROGMEM = "LED-Numbers-Hours"; | ||||||
|  | const char UsermodSSDR::_str_minutes[]     PROGMEM = "LED-Numbers-Minutes"; | ||||||
|  | const char UsermodSSDR::_str_seconds[]     PROGMEM = "LED-Numbers-Seconds"; | ||||||
|  | const char UsermodSSDR::_str_colons[]      PROGMEM = "LED-Numbers-Colons"; | ||||||
|  | const char UsermodSSDR::_str_days[]        PROGMEM = "LED-Numbers-Day"; | ||||||
|  | const char UsermodSSDR::_str_months[]      PROGMEM = "LED-Numbers-Month"; | ||||||
|  | const char UsermodSSDR::_str_years[]       PROGMEM = "LED-Numbers-Year"; | ||||||
|  | const char UsermodSSDR::_str_ldrEnabled[]  PROGMEM = "enable-auto-brightness"; | ||||||
|  | const char UsermodSSDR::_str_minBrightness[]  PROGMEM = "auto-brightness-min"; | ||||||
|  | const char UsermodSSDR::_str_maxBrightness[]  PROGMEM = "auto-brightness-max"; | ||||||
|  | @ -64,6 +64,7 @@ | ||||||
| #define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21     //Usermod "usermod_v2_seven_segment_display.h"
 | #define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21     //Usermod "usermod_v2_seven_segment_display.h"
 | ||||||
| #define USERMOD_RGB_ROTARY_ENCODER       22     //Usermod "rgb-rotary-encoder.h"
 | #define USERMOD_RGB_ROTARY_ENCODER       22     //Usermod "rgb-rotary-encoder.h"
 | ||||||
| #define USERMOD_ID_QUINLED_AN_PENTA      23     //Usermod "quinled-an-penta.h"
 | #define USERMOD_ID_QUINLED_AN_PENTA      23     //Usermod "quinled-an-penta.h"
 | ||||||
|  | #define USERMOD_ID_SSDR                  24     //Usermod "usermod_v2_seven_segment_display_reloaded.h"
 | ||||||
| 
 | 
 | ||||||
| //Access point behavior
 | //Access point behavior
 | ||||||
| #define AP_BEHAVIOR_BOOT_NO_CONN          0     //Open AP when no connection after boot
 | #define AP_BEHAVIOR_BOOT_NO_CONN          0     //Open AP when no connection after boot
 | ||||||
|  |  | ||||||
|  | @ -100,6 +100,10 @@ | ||||||
| #include "../usermods/seven_segment_display/usermod_v2_seven_segment_display.h" | #include "../usermods/seven_segment_display/usermod_v2_seven_segment_display.h" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef USERMOD_SSDR | ||||||
|  | #include "../usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef QUINLED_AN_PENTA | #ifdef QUINLED_AN_PENTA | ||||||
| #include "../usermods/quinled-an-penta/quinled-an-penta.h" | #include "../usermods/quinled-an-penta/quinled-an-penta.h" | ||||||
| #endif | #endif | ||||||
|  | @ -192,6 +196,10 @@ void registerUsermods() | ||||||
|   usermods.add(new SevenSegmentDisplay()); |   usermods.add(new SevenSegmentDisplay()); | ||||||
|   #endif |   #endif | ||||||
| 
 | 
 | ||||||
|  |   #ifdef USERMOD_SSDR | ||||||
|  |   usermods.add(new UsermodSSDR()); | ||||||
|  |   #endif | ||||||
|  | 
 | ||||||
|   #ifdef QUINLED_AN_PENTA |   #ifdef QUINLED_AN_PENTA | ||||||
|   usermods.add(new QuinLEDAnPentaUsermod()); |   usermods.add(new QuinLEDAnPentaUsermod()); | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
		Ładowanie…
	
		Reference in New Issue
	
	 Roman Reitschmied
						Roman Reitschmied