|
@@ -1,4 +1,5 @@
|
|
|
#include <RgbCctPacketFormatter.h>
|
|
#include <RgbCctPacketFormatter.h>
|
|
|
|
|
+#include <Units.h>
|
|
|
|
|
|
|
|
#define V2_OFFSET(byte, key, jumpStart) ( \
|
|
#define V2_OFFSET(byte, key, jumpStart) ( \
|
|
|
pgm_read_byte(&V2_OFFSETS[byte-1][key%4]) \
|
|
pgm_read_byte(&V2_OFFSETS[byte-1][key%4]) \
|
|
@@ -76,24 +77,24 @@ void RgbCctPacketFormatter::previousMode() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RgbCctPacketFormatter::updateBrightness(uint8_t brightness) {
|
|
void RgbCctPacketFormatter::updateBrightness(uint8_t brightness) {
|
|
|
- command(RGB_CCT_BRIGHTNESS, 0x8F + brightness);
|
|
|
|
|
|
|
+ command(RGB_CCT_BRIGHTNESS, RGB_CCT_BRIGHTNESS_OFFSET + brightness);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RgbCctPacketFormatter::updateHue(uint16_t value) {
|
|
void RgbCctPacketFormatter::updateHue(uint16_t value) {
|
|
|
- uint8_t remapped = rescale(value, 255, 360);
|
|
|
|
|
|
|
+ uint8_t remapped = Units::rescale(value, 255, 360);
|
|
|
updateColorRaw(remapped);
|
|
updateColorRaw(remapped);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RgbCctPacketFormatter::updateColorRaw(uint8_t value) {
|
|
void RgbCctPacketFormatter::updateColorRaw(uint8_t value) {
|
|
|
- command(RGB_CCT_COLOR, 0x5F + value);
|
|
|
|
|
|
|
+ command(RGB_CCT_COLOR, RGB_CCT_COLOR_OFFSET + value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
|
|
void RgbCctPacketFormatter::updateTemperature(uint8_t value) {
|
|
|
- command(RGB_CCT_KELVIN, 0x94 - (value*2));
|
|
|
|
|
|
|
+ command(RGB_CCT_KELVIN, RGB_CCT_KELVIN_OFFSET - (value*2));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
|
|
void RgbCctPacketFormatter::updateSaturation(uint8_t value) {
|
|
|
- uint8_t remapped = value + 0xD;
|
|
|
|
|
|
|
+ uint8_t remapped = value + RGB_CCT_SATURATION_OFFSET;
|
|
|
command(RGB_CCT_SATURATION, remapped);
|
|
command(RGB_CCT_SATURATION, remapped);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -110,6 +111,60 @@ void RgbCctPacketFormatter::finalizePacket(uint8_t* packet) {
|
|
|
encodeV2Packet(packet);
|
|
encodeV2Packet(packet);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void RgbCctPacketFormatter::parsePacket(const uint8_t *packet, JsonObject& result) {
|
|
|
|
|
+ uint8_t packetCopy[RGB_CCT_PACKET_LEN];
|
|
|
|
|
+ memcpy(packetCopy, packet, RGB_CCT_PACKET_LEN);
|
|
|
|
|
+ decodeV2Packet(packetCopy);
|
|
|
|
|
+
|
|
|
|
|
+ result["device_id"] = (packetCopy[2] << 8) | packetCopy[3];
|
|
|
|
|
+ result["group_id"] = packetCopy[7];
|
|
|
|
|
+ result["device_type"] = "rgb_cct";
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t command = (packetCopy[RGB_CCT_COMMAND_INDEX] & 0x7F);
|
|
|
|
|
+ uint8_t arg = packetCopy[RGB_CCT_ARGUMENT_INDEX];
|
|
|
|
|
+
|
|
|
|
|
+ if (command == RGB_CCT_ON) {
|
|
|
|
|
+ // Group is not reliably encoded in group byte. Extract from arg byte
|
|
|
|
|
+ if (arg < 5) {
|
|
|
|
|
+ result["state"] = "ON";
|
|
|
|
|
+ result["group_id"] = arg;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result["state"] = "OFF";
|
|
|
|
|
+ result["group_id"] = arg-5;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (command == RGB_CCT_COLOR) {
|
|
|
|
|
+ uint8_t rescaledColor = (arg - RGB_CCT_COLOR_OFFSET) % 0x100;
|
|
|
|
|
+ uint16_t hue = Units::rescale<uint16_t, uint16_t>(rescaledColor, 360, 255.0);
|
|
|
|
|
+ result["hue"] = hue;
|
|
|
|
|
+ } else if (command == RGB_CCT_KELVIN) {
|
|
|
|
|
+ uint8_t temperature =
|
|
|
|
|
+ static_cast<uint8_t>(
|
|
|
|
|
+ // Range in packets is 180 - 220 or something like that. Shift to
|
|
|
|
|
+ // 0..224. Then strip out values out of range [0..24), and (224..255]
|
|
|
|
|
+ constrain(
|
|
|
|
|
+ static_cast<uint8_t>(arg + RGB_CCT_KELVIN_REMOTE_OFFSET),
|
|
|
|
|
+ 24,
|
|
|
|
|
+ 224
|
|
|
|
|
+ )
|
|
|
|
|
+ +
|
|
|
|
|
+ // Shift 24 down to 0
|
|
|
|
|
+ RGB_CCT_KELVIN_REMOTE_START
|
|
|
|
|
+ )/2; // values are in increments of 2
|
|
|
|
|
+
|
|
|
|
|
+ result["color_temp"] = Units::whiteValToMireds(temperature, 100);
|
|
|
|
|
+ // brightness == saturation
|
|
|
|
|
+ } else if (command == RGB_CCT_BRIGHTNESS && arg >= (RGB_CCT_BRIGHTNESS_OFFSET - 15)) {
|
|
|
|
|
+ uint8_t level = constrain(arg - RGB_CCT_BRIGHTNESS_OFFSET, 0, 100);
|
|
|
|
|
+ result["brightness"] = Units::rescale<uint8_t, uint8_t>(level, 255, 100);
|
|
|
|
|
+ } else if (command == RGB_CCT_SATURATION) {
|
|
|
|
|
+ result["saturation"] = constrain(arg - RGB_CCT_SATURATION_OFFSET, 0, 100);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (! result.containsKey("state")) {
|
|
|
|
|
+ result["state"] = "ON";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
uint8_t RgbCctPacketFormatter::xorKey(uint8_t key) {
|
|
uint8_t RgbCctPacketFormatter::xorKey(uint8_t key) {
|
|
|
// Generate most significant nibble
|
|
// Generate most significant nibble
|
|
|
const uint8_t shift = (key & 0x0F) < 0x04 ? 0 : 1;
|
|
const uint8_t shift = (key & 0x0F) < 0x04 ? 0 : 1;
|