GroupState.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include <GroupState.h>
  2. #include <Units.h>
  3. #include <MiLightRemoteConfig.h>
  4. #include <RGBConverter.h>
  5. const GroupState& GroupState::defaultState(MiLightRemoteType remoteType) {
  6. static GroupState instances[MiLightRemoteConfig::NUM_REMOTES];
  7. GroupState& state = instances[remoteType];
  8. switch (remoteType) {
  9. case REMOTE_TYPE_RGB:
  10. state.setBulbMode(BULB_MODE_COLOR);
  11. break;
  12. case REMOTE_TYPE_CCT:
  13. state.setBulbMode(BULB_MODE_WHITE);
  14. break;
  15. }
  16. return state;
  17. }
  18. GroupId::GroupId()
  19. : deviceId(0),
  20. groupId(0),
  21. deviceType(REMOTE_TYPE_UNKNOWN)
  22. { }
  23. GroupId::GroupId(const GroupId &other)
  24. : deviceId(other.deviceId),
  25. groupId(other.groupId),
  26. deviceType(other.deviceType)
  27. { }
  28. GroupId::GroupId(
  29. const uint16_t deviceId, const uint8_t groupId, const MiLightRemoteType deviceType
  30. )
  31. : deviceId(deviceId),
  32. groupId(groupId),
  33. deviceType(deviceType)
  34. { }
  35. void GroupId::operator=(const GroupId &other) {
  36. deviceId = other.deviceId;
  37. groupId = other.groupId;
  38. deviceType = other.deviceType;
  39. }
  40. bool GroupId::operator==(const GroupId &other) {
  41. return deviceId == other.deviceId
  42. && groupId == other.groupId
  43. && deviceType == other.deviceType;
  44. }
  45. GroupState::GroupState() {
  46. state.fields._state = 0;
  47. state.fields._brightness = 0;
  48. state.fields._brightnessColor = 0;
  49. state.fields._brightnessMode = 0;
  50. state.fields._hue = 0;
  51. state.fields._saturation = 0;
  52. state.fields._mode = 0;
  53. state.fields._bulbMode = 0;
  54. state.fields._kelvin = 0;
  55. state.fields._isSetState = 0;
  56. state.fields._isSetHue = 0;
  57. state.fields._isSetBrightness = 0;
  58. state.fields._isSetBrightnessColor = 0;
  59. state.fields._isSetBrightnessMode = 0;
  60. state.fields._isSetSaturation = 0;
  61. state.fields._isSetMode = 0;
  62. state.fields._isSetKelvin = 0;
  63. state.fields._isSetBulbMode = 0;
  64. state.fields._dirty = 1;
  65. }
  66. bool GroupState::isSetState() const { return state.fields._isSetState; }
  67. MiLightStatus GroupState::getState() const { return state.fields._state ? ON : OFF; }
  68. void GroupState::setState(const MiLightStatus status) {
  69. setDirty();
  70. state.fields._isSetState = 1;
  71. state.fields._state = status == ON ? 1 : 0;
  72. }
  73. bool GroupState::isSetBrightness() const {
  74. if (! state.fields._isSetBulbMode) {
  75. return state.fields._isSetBrightness;
  76. }
  77. switch (state.fields._bulbMode) {
  78. case BULB_MODE_WHITE:
  79. return state.fields._isSetBrightness;
  80. case BULB_MODE_COLOR:
  81. return state.fields._isSetBrightnessColor;
  82. case BULB_MODE_SCENE:
  83. return state.fields._isSetBrightnessMode;
  84. }
  85. return false;
  86. }
  87. uint8_t GroupState::getBrightness() const {
  88. switch (state.fields._bulbMode) {
  89. case BULB_MODE_WHITE:
  90. return state.fields._brightness;
  91. case BULB_MODE_COLOR:
  92. return state.fields._brightnessColor;
  93. case BULB_MODE_SCENE:
  94. return state.fields._brightnessMode;
  95. }
  96. return 0;
  97. }
  98. void GroupState::setBrightness(uint8_t brightness) {
  99. setDirty();
  100. uint8_t bulbMode = state.fields._bulbMode;
  101. if (! state.fields._isSetBulbMode) {
  102. bulbMode = BULB_MODE_WHITE;
  103. }
  104. switch (bulbMode) {
  105. case BULB_MODE_WHITE:
  106. state.fields._isSetBrightness = 1;
  107. state.fields._brightness = brightness;
  108. break;
  109. case BULB_MODE_COLOR:
  110. state.fields._isSetBrightnessColor = 1;
  111. state.fields._brightnessColor = brightness;
  112. break;
  113. case BULB_MODE_SCENE:
  114. state.fields._isSetBrightnessMode = 1;
  115. state.fields._brightnessMode = brightness;
  116. }
  117. }
  118. bool GroupState::isSetHue() const { return state.fields._isSetHue; }
  119. uint16_t GroupState::getHue() const {
  120. return Units::rescale<uint16_t, uint16_t>(state.fields._hue, 360, 255);
  121. }
  122. void GroupState::setHue(uint16_t hue) {
  123. setDirty();
  124. state.fields._isSetHue = 1;
  125. state.fields._hue = Units::rescale<uint16_t, uint16_t>(hue, 255, 360);
  126. }
  127. bool GroupState::isSetSaturation() const { return state.fields._isSetSaturation; }
  128. uint8_t GroupState::getSaturation() const { return state.fields._saturation; }
  129. void GroupState::setSaturation(uint8_t saturation) {
  130. setDirty();
  131. state.fields._isSetSaturation = 1;
  132. state.fields._saturation = saturation;
  133. }
  134. bool GroupState::isSetMode() const { return state.fields._isSetMode; }
  135. uint8_t GroupState::getMode() const { return state.fields._mode; }
  136. void GroupState::setMode(uint8_t mode) {
  137. setDirty();
  138. state.fields._isSetMode = 1;
  139. state.fields._mode = mode;
  140. }
  141. bool GroupState::isSetKelvin() const { return state.fields._isSetKelvin; }
  142. uint8_t GroupState::getKelvin() const { return state.fields._kelvin; }
  143. uint16_t GroupState::getMireds() const {
  144. return Units::whiteValToMireds(getKelvin(), 100);
  145. }
  146. void GroupState::setKelvin(uint8_t kelvin) {
  147. setDirty();
  148. state.fields._isSetKelvin = 1;
  149. state.fields._kelvin = kelvin;
  150. }
  151. void GroupState::setMireds(uint16_t mireds) {
  152. setKelvin(Units::miredsToWhiteVal(mireds, 100));
  153. }
  154. bool GroupState::isSetBulbMode() const { return state.fields._isSetBulbMode; }
  155. BulbMode GroupState::getBulbMode() const { return static_cast<BulbMode>(state.fields._bulbMode); }
  156. void GroupState::setBulbMode(BulbMode bulbMode) {
  157. setDirty();
  158. state.fields._isSetBulbMode = 1;
  159. state.fields._bulbMode = bulbMode;
  160. }
  161. bool GroupState::isDirty() const { return state.fields._dirty; }
  162. inline bool GroupState::setDirty() { state.fields._dirty = 1; }
  163. bool GroupState::clearDirty() { state.fields._dirty = 0; }
  164. void GroupState::load(Stream& stream) {
  165. for (size_t i = 0; i < DATA_BYTES; i++) {
  166. stream.readBytes(reinterpret_cast<uint8_t*>(&state.data[i]), 4);
  167. }
  168. clearDirty();
  169. }
  170. void GroupState::dump(Stream& stream) const {
  171. for (size_t i = 0; i < DATA_BYTES; i++) {
  172. stream.write(reinterpret_cast<const uint8_t*>(&state.data[i]), 4);
  173. }
  174. }
  175. void GroupState::patch(const JsonObject& state) {
  176. if (state.containsKey("state")) {
  177. setState(state["state"] == "ON" ? ON : OFF);
  178. }
  179. if (state.containsKey("brightness")) {
  180. setBrightness(Units::rescale(state.get<uint8_t>("brightness"), 100, 255));
  181. }
  182. if (state.containsKey("hue")) {
  183. setHue(state["hue"]);
  184. setBulbMode(BULB_MODE_COLOR);
  185. }
  186. if (state.containsKey("saturation")) {
  187. setSaturation(state["saturation"]);
  188. }
  189. if (state.containsKey("mode")) {
  190. setMode(state["mode"]);
  191. setBulbMode(BULB_MODE_SCENE);
  192. }
  193. if (state.containsKey("color_temp")) {
  194. setMireds(state["color_temp"]);
  195. setBulbMode(BULB_MODE_WHITE);
  196. }
  197. if (state.containsKey("command")) {
  198. const String& command = state["command"];
  199. if (command == "white_mode") {
  200. setBulbMode(BULB_MODE_WHITE);
  201. } else if (command == "night_mode") {
  202. setBulbMode(BULB_MODE_NIGHT);
  203. }
  204. }
  205. }
  206. void GroupState::applyState(JsonObject& partialState) {
  207. if (isSetState()) {
  208. partialState["state"] = getState() == ON ? "ON" : "OFF";
  209. }
  210. if (isSetBrightness()) {
  211. partialState["brightness"] = Units::rescale(getBrightness(), 255, 100);
  212. }
  213. if (isSetBulbMode()) {
  214. partialState["bulb_mode"] = BULB_MODE_NAMES[getBulbMode()];
  215. if (getBulbMode() == BULB_MODE_COLOR) {
  216. if (isSetHue() && isSetSaturation()) {
  217. uint8_t rgb[3];
  218. RGBConverter converter;
  219. converter.hsvToRgb(getHue()/360.0, getSaturation()/100.0, 1, rgb);
  220. JsonObject& color = partialState.createNestedObject("color");
  221. color["r"] = rgb[0];
  222. color["g"] = rgb[1];
  223. color["b"] = rgb[2];
  224. } else if (isSetHue()) {
  225. partialState["hue"] = getHue();
  226. } else if (isSetSaturation()) {
  227. partialState["saturation"] = getSaturation();
  228. }
  229. } else if (getBulbMode() == BULB_MODE_SCENE) {
  230. if (isSetMode()) {
  231. partialState["mode"] = getMode();
  232. }
  233. } else if (getBulbMode() == BULB_MODE_WHITE) {
  234. if (isSetKelvin()) {
  235. partialState["color_temp"] = getMireds();
  236. }
  237. }
  238. }
  239. }