| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #include <CctPacketFormatter.h>
- static const uint8_t CCT_PROTOCOL_ID = 0x5A;
- bool CctPacketFormatter::canHandle(const uint8_t *packet, const size_t len) {
- return len == packetLength && packet[0] == CCT_PROTOCOL_ID;
- }
- void CctPacketFormatter::initializePacket(uint8_t* packet) {
- size_t packetPtr = 0;
- // Byte 0: Packet length = 7 bytes
- // Byte 1: CCT protocol
- packet[packetPtr++] = CCT_PROTOCOL_ID;
- // Byte 2 and 3: Device ID
- packet[packetPtr++] = deviceId >> 8;
- packet[packetPtr++] = deviceId & 0xFF;
- // Byte 4: Zone
- packet[packetPtr++] = groupId;
- // Byte 5: Bulb command, filled in later
- packet[packetPtr++] = 0;
- // Byte 6: Packet sequence number 0..255
- packet[packetPtr++] = sequenceNum++;
- // Byte 7: Checksum over previous bytes, including packet length = 7
- // The checksum will be calculated when setting the command field
- packet[packetPtr++] = 0;
- // Byte 8: CRC LSB
- // Byte 9: CRC MSB
- }
- void CctPacketFormatter::finalizePacket(uint8_t* packet) {
- uint8_t checksum;
- // Calculate checksum over packet length .. sequenceNum
- checksum = 7; // Packet length is not part of packet
- for (uint8_t i = 0; i < 6; i++) {
- checksum += currentPacket[i];
- }
- // Store the checksum in the sixth byte
- currentPacket[6] = checksum;
- }
- void CctPacketFormatter::updateBrightness(uint8_t value) {
- const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
- int8_t knownValue = (state != NULL && state->isSetBrightness()) ? state->getBrightness() : -1;
- valueByStepFunction(
- &PacketFormatter::increaseBrightness,
- &PacketFormatter::decreaseBrightness,
- CCT_INTERVALS,
- value / CCT_INTERVALS,
- knownValue / CCT_INTERVALS
- );
- }
- void CctPacketFormatter::updateTemperature(uint8_t value) {
- const GroupState* state = this->stateStore->get(deviceId, groupId, MiLightRemoteType::REMOTE_TYPE_CCT);
- int8_t knownValue = (state != NULL && state->isSetKelvin()) ? state->getKelvin() : -1;
- valueByStepFunction(
- &PacketFormatter::increaseTemperature,
- &PacketFormatter::decreaseTemperature,
- CCT_INTERVALS,
- value / CCT_INTERVALS,
- knownValue / CCT_INTERVALS
- );
- }
- void CctPacketFormatter::command(uint8_t command, uint8_t arg) {
- pushPacket();
- if (held) {
- command |= 0x80;
- }
- currentPacket[CCT_COMMAND_INDEX] = command;
- }
- void CctPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) {
- command(getCctStatusButton(groupId, status), 0);
- }
- void CctPacketFormatter::increaseTemperature() {
- command(CCT_TEMPERATURE_UP, 0);
- }
- void CctPacketFormatter::decreaseTemperature() {
- command(CCT_TEMPERATURE_DOWN, 0);
- }
- void CctPacketFormatter::increaseBrightness() {
- command(CCT_BRIGHTNESS_UP, 0);
- }
- void CctPacketFormatter::decreaseBrightness() {
- command(CCT_BRIGHTNESS_DOWN, 0);
- }
- void CctPacketFormatter::enableNightMode() {
- command(getCctStatusButton(groupId, OFF) | 0x10, 0);
- }
- uint8_t CctPacketFormatter::getCctStatusButton(uint8_t groupId, MiLightStatus status) {
- uint8_t button = 0;
- if (status == ON) {
- switch(groupId) {
- case 0:
- button = CCT_ALL_ON;
- break;
- case 1:
- button = CCT_GROUP_1_ON;
- break;
- case 2:
- button = CCT_GROUP_2_ON;
- break;
- case 3:
- button = CCT_GROUP_3_ON;
- break;
- case 4:
- button = CCT_GROUP_4_ON;
- break;
- }
- } else {
- switch(groupId) {
- case 0:
- button = CCT_ALL_OFF;
- break;
- case 1:
- button = CCT_GROUP_1_OFF;
- break;
- case 2:
- button = CCT_GROUP_2_OFF;
- break;
- case 3:
- button = CCT_GROUP_3_OFF;
- break;
- case 4:
- button = CCT_GROUP_4_OFF;
- break;
- }
- }
- return button;
- }
- uint8_t CctPacketFormatter::cctCommandIdToGroup(uint8_t command) {
- switch (command & 0xF) {
- case CCT_GROUP_1_ON:
- case CCT_GROUP_1_OFF:
- return 1;
- case CCT_GROUP_2_ON:
- case CCT_GROUP_2_OFF:
- return 2;
- case CCT_GROUP_3_ON:
- case CCT_GROUP_3_OFF:
- return 3;
- case CCT_GROUP_4_ON:
- case CCT_GROUP_4_OFF:
- return 4;
- case CCT_ALL_ON:
- case CCT_ALL_OFF:
- return 0;
- }
- return 255;
- }
- MiLightStatus CctPacketFormatter::cctCommandToStatus(uint8_t command) {
- switch (command & 0xF) {
- case CCT_GROUP_1_ON:
- case CCT_GROUP_2_ON:
- case CCT_GROUP_3_ON:
- case CCT_GROUP_4_ON:
- case CCT_ALL_ON:
- return ON;
- case CCT_GROUP_1_OFF:
- case CCT_GROUP_2_OFF:
- case CCT_GROUP_3_OFF:
- case CCT_GROUP_4_OFF:
- case CCT_ALL_OFF:
- default:
- return OFF;
- }
- }
- BulbId CctPacketFormatter::parsePacket(const uint8_t* packet, JsonObject& result) {
- uint8_t command = packet[CCT_COMMAND_INDEX] & 0x7F;
- uint8_t onOffGroupId = cctCommandIdToGroup(command);
- BulbId bulbId(
- (packet[1] << 8) | packet[2],
- onOffGroupId < 255 ? onOffGroupId : packet[3],
- REMOTE_TYPE_CCT
- );
- if (onOffGroupId < 255) {
- result["state"] = cctCommandToStatus(command) == ON ? "ON" : "OFF";
- } else if (command == CCT_BRIGHTNESS_DOWN) {
- result["command"] = "brightness_down";
- } else if (command == CCT_BRIGHTNESS_UP) {
- result["command"] = "brightness_up";
- } else if (command == CCT_TEMPERATURE_DOWN) {
- result["command"] = "temperature_down";
- } else if (command == CCT_TEMPERATURE_UP) {
- result["command"] = "temperature_up";
- } else {
- result["button_id"] = command;
- }
- return bulbId;
- }
- void CctPacketFormatter::format(uint8_t const* packet, char* buffer) {
- PacketFormatter::formatV1Packet(packet, buffer);
- }
|