ColorTransition.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include <ColorTransition.h>
  2. #include <Arduino.h>
  3. ColorTransition::Builder::Builder(size_t id, const BulbId& bulbId, TransitionFn callback, const ParsedColor& start, const ParsedColor& end)
  4. : Transition::Builder(id, bulbId, callback, calculateMaxDistance(start, end))
  5. , start(start)
  6. , end(end)
  7. { }
  8. std::shared_ptr<Transition> ColorTransition::Builder::_build() const {
  9. size_t duration = getOrComputeDuration();
  10. size_t numPeriods = getOrComputeNumPeriods();
  11. size_t period = getOrComputePeriod();
  12. int16_t dr = end.r - start.r
  13. , dg = end.g - start.g
  14. , db = end.b - start.b;
  15. RgbColor stepSizes(
  16. calculateStepSizePart(dr, duration, period),
  17. calculateStepSizePart(dg, duration, period),
  18. calculateStepSizePart(db, duration, period)
  19. );
  20. return std::make_shared<ColorTransition>(
  21. id,
  22. bulbId,
  23. start,
  24. end,
  25. stepSizes,
  26. duration,
  27. period,
  28. numPeriods,
  29. callback
  30. );
  31. }
  32. ColorTransition::RgbColor::RgbColor()
  33. : r(0)
  34. , g(0)
  35. , b(0)
  36. { }
  37. ColorTransition::RgbColor::RgbColor(const ParsedColor& color)
  38. : r(color.r)
  39. , g(color.g)
  40. , b(color.b)
  41. { }
  42. ColorTransition::RgbColor::RgbColor(int16_t r, int16_t g, int16_t b)
  43. : r(r)
  44. , g(g)
  45. , b(b)
  46. { }
  47. bool ColorTransition::RgbColor::operator==(const RgbColor& other) {
  48. return r == other.r && g == other.g && b == other.b;
  49. }
  50. ColorTransition::ColorTransition(
  51. size_t id,
  52. const BulbId& bulbId,
  53. const ParsedColor& startColor,
  54. const ParsedColor& endColor,
  55. RgbColor stepSizes,
  56. size_t duration,
  57. size_t period,
  58. size_t numPeriods,
  59. TransitionFn callback
  60. ) : Transition(id, bulbId, period, callback)
  61. , endColor(endColor)
  62. , currentColor(startColor)
  63. , stepSizes(stepSizes)
  64. , lastHue(400) // use impossible values to force a packet send
  65. , lastSaturation(200)
  66. , finished(false)
  67. {
  68. int16_t dr = endColor.r - startColor.r
  69. , dg = endColor.g - startColor.g
  70. , db = endColor.b - startColor.b;
  71. // Calculate step sizes in terms of the period
  72. stepSizes.r = calculateStepSizePart(dr, duration, period);
  73. stepSizes.g = calculateStepSizePart(dg, duration, period);
  74. stepSizes.b = calculateStepSizePart(db, duration, period);
  75. }
  76. size_t ColorTransition::calculateMaxDistance(const ParsedColor& start, const ParsedColor& end) {
  77. int16_t dr = end.r - start.r
  78. , dg = end.g - start.g
  79. , db = end.b - start.b;
  80. int16_t max = std::max(std::max(dr, dg), db);
  81. int16_t min = std::min(std::min(dr, dg), db);
  82. int16_t maxAbs = std::abs(min) > std::abs(max) ? min : max;
  83. return maxAbs;
  84. }
  85. size_t ColorTransition::calculateColorPeriod(ColorTransition* t, const ParsedColor& start, const ParsedColor& end, size_t stepSize, size_t duration) {
  86. return Transition::calculatePeriod(calculateMaxDistance(start, end), stepSize, duration);
  87. }
  88. int16_t ColorTransition::calculateStepSizePart(int16_t distance, size_t duration, size_t period) {
  89. double stepSize = (distance / static_cast<double>(duration)) * period;
  90. int16_t rounded = std::ceil(std::abs(stepSize));
  91. if (distance < 0) {
  92. rounded = -rounded;
  93. }
  94. return rounded;
  95. }
  96. void ColorTransition::step() {
  97. ParsedColor parsedColor = ParsedColor::fromRgb(currentColor.r, currentColor.g, currentColor.b);
  98. if (parsedColor.hue != lastHue) {
  99. callback(bulbId, GroupStateField::HUE, parsedColor.hue);
  100. lastHue = parsedColor.hue;
  101. }
  102. if (parsedColor.saturation != lastSaturation) {
  103. callback(bulbId, GroupStateField::SATURATION, parsedColor.saturation);
  104. lastSaturation = parsedColor.saturation;
  105. }
  106. if (currentColor == endColor) {
  107. finished = true;
  108. } else {
  109. Transition::stepValue(currentColor.r, endColor.r, stepSizes.r);
  110. Transition::stepValue(currentColor.g, endColor.g, stepSizes.g);
  111. Transition::stepValue(currentColor.b, endColor.b, stepSizes.b);
  112. }
  113. }
  114. bool ColorTransition::isFinished() {
  115. return finished;
  116. }
  117. void ColorTransition::childSerialize(JsonObject& json) {
  118. json[F("type")] = F("color");
  119. JsonArray currentColorArr = json.createNestedArray(F("current_color"));
  120. currentColorArr.add(currentColor.r);
  121. currentColorArr.add(currentColor.g);
  122. currentColorArr.add(currentColor.b);
  123. JsonArray endColorArr = json.createNestedArray(F("end_color"));
  124. endColorArr.add(endColor.r);
  125. endColorArr.add(endColor.g);
  126. endColorArr.add(endColor.b);
  127. JsonArray stepSizesArr = json.createNestedArray(F("step_sizes"));
  128. stepSizesArr.add(stepSizes.r);
  129. stepSizesArr.add(stepSizes.g);
  130. stepSizesArr.add(stepSizes.b);
  131. }