|
9 | 9 | | SPDX-License-Identifier: GPL-2.0-only | |
10 | 10 | \*---------------------------------------------------------*/ |
11 | 11 |
|
| 12 | +#include <algorithm> |
12 | 13 | #include <nlohmann/json.hpp> |
13 | 14 | #include "base64.hpp" |
14 | 15 | #include "GoveeController.h" |
@@ -182,22 +183,48 @@ void GoveeController::SetColor(unsigned char red, unsigned char green, unsigned |
182 | 183 |
|
183 | 184 | void GoveeController::SendRazerData(RGBColor* colors, unsigned int size) |
184 | 185 | { |
185 | | - std::vector<base64::byte> pkt = { 0xBB, 0x00, 0x00, 0xB0, 0x00, 0x00 }; |
186 | | - json command; |
| 186 | + /*-----------------------------------------------------*\ |
| 187 | + | Do not send an empty frame (this was producing | |
| 188 | + | length=2, count=0) | |
| 189 | + \*-----------------------------------------------------*/ |
| 190 | + if(size == 0) |
| 191 | + { |
| 192 | + return; |
| 193 | + } |
| 194 | + |
| 195 | + /*-----------------------------------------------------*\ |
| 196 | + | PT payload: BB [len_hi] [len_lo] B0 [gradient_off=1] | |
| 197 | + | [led_count] (RGB * N) [xor] | |
| 198 | + | length = 2 + 3*N (bytes after 0xB0: gradient_off + | |
| 199 | + | led_count + RGB*count) | |
| 200 | + \*-----------------------------------------------------*/ |
| 201 | + const unsigned int count = std::min(size, 255u); |
| 202 | + const unsigned int payload_len = 2 + (3 * count); |
| 203 | + |
| 204 | + /*-----------------------------------------------------*\ |
| 205 | + | Create buffer with fixed size and fill sequentially | |
| 206 | + \*-----------------------------------------------------*/ |
187 | 207 |
|
188 | | - pkt[2] = 2 + (3 * size); |
189 | | - pkt[5] = size; |
190 | | - pkt.resize(6 + (3 * size)); |
| 208 | + std::vector<base64::byte> pkt; |
| 209 | + pkt.reserve(7 + (3 * count)); |
191 | 210 |
|
192 | | - for(std::size_t led_idx = 0; led_idx < size; led_idx++) |
| 211 | + pkt.push_back(0xBB); |
| 212 | + pkt.push_back(static_cast<base64::byte>((payload_len >> 8) & 0xFF)); /* len_hi */ |
| 213 | + pkt.push_back(static_cast<base64::byte>(payload_len & 0xFF)); /* len_lo */ |
| 214 | + pkt.push_back(0xB0); /* subcommand */ |
| 215 | + pkt.push_back(0x01); /* gradient_off = 1 */ |
| 216 | + pkt.push_back(static_cast<base64::byte>(count)); /* led_count */ |
| 217 | + |
| 218 | + for(std::size_t led_idx = 0; led_idx < count; led_idx++) |
193 | 219 | { |
194 | | - pkt[6 + (led_idx * 3)] = RGBGetRValue(colors[led_idx]); |
195 | | - pkt[7 + (led_idx * 3)] = RGBGetGValue(colors[led_idx]); |
196 | | - pkt[8 + (led_idx * 3)] = RGBGetBValue(colors[led_idx]); |
| 220 | + pkt.push_back(RGBGetRValue(colors[led_idx])); |
| 221 | + pkt.push_back(RGBGetGValue(colors[led_idx])); |
| 222 | + pkt.push_back(RGBGetBValue(colors[led_idx])); |
197 | 223 | } |
198 | 224 |
|
199 | 225 | pkt.push_back(CalculateXorChecksum(pkt)); |
200 | 226 |
|
| 227 | + json command; |
201 | 228 | command["msg"]["cmd"] = "razer"; |
202 | 229 | command["msg"]["data"]["pt"] = base64::encode(pkt); |
203 | 230 |
|
@@ -246,7 +273,11 @@ void GoveeController::SendScan() |
246 | 273 | json command; |
247 | 274 |
|
248 | 275 | command["msg"]["cmd"] = "scan"; |
249 | | - command["msg"]["data"]["account_topic"] = "GA/123456789"; |
| 276 | + /*-----------------------------------------------------*\ |
| 277 | + | Matches what Govee devices commonly accept for LAN | |
| 278 | + | scan | |
| 279 | + \*-----------------------------------------------------*/ |
| 280 | + command["msg"]["data"]["account_topic"] = "reserve"; |
250 | 281 |
|
251 | 282 | /*-----------------------------------------------------*\ |
252 | 283 | | Convert the JSON object to a string and write it | |
|
0 commit comments