11#include " PPUC.h"
22
33#include < algorithm>
4+ #include < cctype>
45#include < cstring>
56#include < set>
67#include < unordered_map>
@@ -174,38 +175,102 @@ bool PPUC::AbortConfigurationEarly() const {
174175 return m_pRS485Comm->ShouldAbortConfigurationEarly ();
175176}
176177
177- void PPUC::SendTriggerConfigBlock (const YAML::Node& items, uint32_t type,
178- uint8_t board, uint32_t port) {
179- if (items) {
180- for (YAML::Node n_item : items) {
181- if (AbortConfigurationEarly ()) {
182- return ;
183- }
184- uint8_t index = 0 ;
185- m_pRS485Comm->SendConfigEvent (
186- new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER, index++,
187- (uint8_t )CONFIG_TOPIC_PORT, port));
188- m_pRS485Comm->SendConfigEvent (
189- new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER, index++,
190- (uint8_t )CONFIG_TOPIC_TYPE, type));
191- std::string c_source = n_item[" source" ].as <std::string>();
192- uint32_t source = EVENT_SOURCE_SWITCH;
193- if (strcmp (c_source.c_str (), " S" ) == 0 ) {
194- source = EVENT_SOURCE_SOLENOID;
195- } else if (strcmp (c_source.c_str (), " L" ) == 0 ) {
196- source = EVENT_SOURCE_LIGHT;
197- }
198- m_pRS485Comm->SendConfigEvent (
199- new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER, index++,
200- (uint8_t )CONFIG_TOPIC_SOURCE, source));
201- m_pRS485Comm->SendConfigEvent (new ConfigEvent (
202- board, (uint8_t )CONFIG_TOPIC_TRIGGER, index++,
203- (uint8_t )CONFIG_TOPIC_NUMBER, n_item[" number" ].as <uint32_t >()));
204- m_pRS485Comm->SendConfigEvent (new ConfigEvent (
205- board, (uint8_t )CONFIG_TOPIC_LAMPS, index++,
206- (uint8_t )CONFIG_TOPIC_VALUE, n_item[" value" ].as <uint32_t >()));
207- }
178+ namespace {
179+ uint32_t ResolvePwmType (const std::string& type) {
180+ if (type == " flasher" ) {
181+ return PWM_TYPE_FLASHER;
182+ }
183+ if (type == " lamp" ) {
184+ return PWM_TYPE_LAMP;
208185 }
186+ if (type == " motor" ) {
187+ return PWM_TYPE_MOTOR;
188+ }
189+ if (type == " shaker" ) {
190+ return PWM_TYPE_SHAKER;
191+ }
192+ return PWM_TYPE_SOLENOID;
193+ }
194+
195+ bool IsDecimalScalar (const std::string& value) {
196+ return !value.empty () &&
197+ std::all_of (value.begin (), value.end (), [](unsigned char c) {
198+ return std::isdigit (c) != 0 ;
199+ });
200+ }
201+
202+ uint32_t ResolveLedEffectMode (const YAML::Node& node) {
203+ const std::string value = node.as <std::string>();
204+ if (IsDecimalScalar (value)) {
205+ return node.as <uint32_t >();
206+ }
207+
208+ static const std::unordered_map<std::string, uint32_t > kModes = {
209+ {" static" , 0 }, {" blink" , 1 }, {" breath" , 2 },
210+ {" color_wipe" , 3 }, {" scan" , 13 }, {" running_lights" , 18 },
211+ {" twinkle_fade_random" , 22 }, {" sparkle" , 23 },
212+ {" strobe" , 26 }, {" chase_rainbow" , 33 }, {" running_color" , 40 },
213+ {" running_random" , 42 }, {" larson_scanner" , 43 },{" comet" , 44 },
214+ {" fireworks" , 45 }, {" fire_flicker" , 48 }, {" tricolor_chase" , 54 },
215+ {" twinklefox" , 55 }, {" rain" , 56 }, {" heartbeat" , 64 },
216+ {" multi_comet" , 66 }, {" popcorn" , 68 }, {" oscillator" , 69 },
217+ };
218+
219+ const auto it = kModes .find (value);
220+ if (it == kModes .end ()) {
221+ throw YAML::Exception (node.Mark (), " unknown LED effect '" + value + " '" );
222+ }
223+ return it->second ;
224+ }
225+
226+ uint32_t ResolvePwmEffectMode (const YAML::Node& node) {
227+ const std::string value = node.as <std::string>();
228+ if (IsDecimalScalar (value)) {
229+ return node.as <uint32_t >();
230+ }
231+
232+ static const std::unordered_map<std::string, uint32_t > kModes = {
233+ {" sine" , PWM_EFFECT_SINE},
234+ {" ramp_down_stop" , PWM_EFFECT_RAMP_DOWN_STOP},
235+ {" impulse" , PWM_EFFECT_IMPULSE},
236+ };
237+
238+ const auto it = kModes .find (value);
239+ if (it == kModes .end ()) {
240+ throw YAML::Exception (node.Mark (), " unknown PWM effect '" + value + " '" );
241+ }
242+ return it->second ;
243+ }
244+ } // namespace
245+
246+ void SendNamedEffectTriggerConfig (RS485Comm* comm, const YAML::Node& effectNode,
247+ uint32_t type, uint8_t board,
248+ uint32_t port) {
249+ if (!comm || !effectNode || !effectNode[" name" ]) {
250+ return ;
251+ }
252+
253+ const uint32_t value = effectNode[" value" ] ? effectNode[" value" ].as <uint32_t >()
254+ : 1u ;
255+ const uint32_t number =
256+ HashNamedTriggerId (effectNode[" name" ].as <std::string>().c_str ());
257+
258+ uint8_t index = 0 ;
259+ comm->SendConfigEvent (new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER,
260+ index++, (uint8_t )CONFIG_TOPIC_PORT,
261+ port));
262+ comm->SendConfigEvent (new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER,
263+ index++, (uint8_t )CONFIG_TOPIC_TYPE,
264+ type));
265+ comm->SendConfigEvent (new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER,
266+ index++, (uint8_t )CONFIG_TOPIC_SOURCE,
267+ EVENT_SOURCE_EFFECT));
268+ comm->SendConfigEvent (new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER,
269+ index++, (uint8_t )CONFIG_TOPIC_NUMBER,
270+ number));
271+ comm->SendConfigEvent (new ConfigEvent (board, (uint8_t )CONFIG_TOPIC_TRIGGER,
272+ index++, (uint8_t )CONFIG_TOPIC_VALUE,
273+ value));
209274}
210275
211276void PPUC::SendLedConfigBlock (const YAML::Node& items, uint32_t type,
@@ -534,14 +599,7 @@ bool PPUC::Connect() {
534599 n_pwmOutput[" board" ].as <uint8_t >(), (uint8_t )CONFIG_TOPIC_PWM,
535600 index++, (uint8_t )CONFIG_TOPIC_FAST_SWITCH, fastSwitch));
536601 std::string c_type = n_pwmOutput[" type" ].as <std::string>();
537- uint32_t type = PWM_TYPE_SOLENOID; // "coil"
538- if (strcmp (c_type.c_str (), " flasher" ) == 0 ) {
539- type = PWM_TYPE_FLASHER;
540- } else if (strcmp (c_type.c_str (), " lamp" ) == 0 ) {
541- type = PWM_TYPE_LAMP;
542- } else if (strcmp (c_type.c_str (), " motor" ) == 0 ) {
543- type = PWM_TYPE_MOTOR;
544- }
602+ uint32_t type = ResolvePwmType (c_type);
545603 m_pRS485Comm->SendConfigEvent (new ConfigEvent (
546604 n_pwmOutput[" board" ].as <uint8_t >(), (uint8_t )CONFIG_TOPIC_PWM,
547605 index++, (uint8_t )CONFIG_TOPIC_TYPE, type));
@@ -564,7 +622,7 @@ bool PPUC::Connect() {
564622 new ConfigEvent (n_pwmOutput[" board" ].as <uint8_t >(),
565623 (uint8_t )CONFIG_TOPIC_PWM_EFFECT, index++,
566624 (uint8_t )CONFIG_TOPIC_EFFECT,
567- n_pwm_effect[" effect" ]. as < uint32_t >( )));
625+ ResolvePwmEffectMode ( n_pwm_effect[" effect" ])));
568626 m_pRS485Comm->SendConfigEvent (
569627 new ConfigEvent (n_pwmOutput[" board" ].as <uint8_t >(),
570628 (uint8_t )CONFIG_TOPIC_PWM_EFFECT, index++,
@@ -598,10 +656,10 @@ bool PPUC::Connect() {
598656 ? 255
599657 : n_pwm_effect[" repeat" ].as <uint32_t >()));
600658
601- SendTriggerConfigBlock (n_pwm_effect[ " trigger " ],
602- CONFIG_TOPIC_PWM_EFFECT,
603- n_pwmOutput[" board" ].as <uint8_t >(),
604- n_pwmOutput[" port" ].as <uint32_t >());
659+ SendNamedEffectTriggerConfig (
660+ m_pRS485Comm, n_pwm_effect, CONFIG_TOPIC_PWM_EFFECT,
661+ n_pwmOutput[" board" ].as <uint8_t >(),
662+ n_pwmOutput[" port" ].as <uint32_t >());
605663 }
606664 }
607665
@@ -709,7 +767,7 @@ bool PPUC::Connect() {
709767 new ConfigEvent (n_ledStripe[" board" ].as <uint8_t >(),
710768 (uint8_t )CONFIG_TOPIC_LED_EFFECT, index++,
711769 (uint8_t )CONFIG_TOPIC_EFFECT,
712- n_led_effect[" effect" ]. as < uint32_t >( )));
770+ ResolveLedEffectMode ( n_led_effect[" effect" ])));
713771 m_pRS485Comm->SendConfigEvent (
714772 new ConfigEvent (n_ledStripe[" board" ].as <uint8_t >(),
715773 (uint8_t )CONFIG_TOPIC_LED_EFFECT, index++,
@@ -738,10 +796,10 @@ bool PPUC::Connect() {
738796 ? 255
739797 : n_led_effect[" repeat" ].as <uint32_t >()));
740798
741- SendTriggerConfigBlock (n_led_effect[ " trigger " ],
742- CONFIG_TOPIC_LED_EFFECT,
743- n_ledStripe[" board" ].as <uint8_t >(),
744- n_ledStripe[" port" ].as <uint32_t >());
799+ SendNamedEffectTriggerConfig (
800+ m_pRS485Comm, n_led_effect, CONFIG_TOPIC_LED_EFFECT,
801+ n_ledStripe[" board" ].as <uint8_t >(),
802+ n_ledStripe[" port" ].as <uint32_t >());
745803 }
746804 }
747805
@@ -912,6 +970,11 @@ void PPUC::SetSwitchState(int number, int state) {
912970 state == 0 ? 0 : 1 );
913971}
914972
973+ void PPUC::TriggerEvent (uint8_t source, int number, int value) {
974+ m_pRS485Comm->QueueEvent (new Event (source, static_cast <uint16_t >(number),
975+ static_cast <uint8_t >(value)));
976+ }
977+
915978bool PPUC::IsSwitchVirtualized (int number) {
916979 return m_pRS485Comm->IsSwitchVirtualized (static_cast <uint16_t >(number));
917980}
0 commit comments