void parsing() { if (Udp.parsePacket()) { static uint32_t tmr = 0; static char buf[UDP_TX_PACKET_MAX_SIZE + 1]; int n = Udp.read(buf, UDP_TX_PACKET_MAX_SIZE); if (millis() - tmr < 500) return; // принимаем посылки не чаще 2 раз в секунду tmr = millis(); buf[n] = NULL; DEBUGLN(buf); // пакет вида <ключ>,<канал>,<тип>,<дата1>,<дата2>... mString pars(buf, sizeof(buf)); if (!pars.startsWith(GL_KEY)) return; // не наш ключ byte keyLen = strlen(GL_KEY); byte data[MAX_PRESETS * PRES_SIZE + 5]; memset(data, 0, MAX_PRESETS * PRES_SIZE + keyLen); int count = 0; char *str, *p = buf + keyLen; // сдвиг до даты char *ssid, *pass; uint32_t city = 0; uint16_t stripL, stripW; while ((str = strtok_r(p, ",", &p)) != NULL) { uint32_t thisInt = atoi(str); data[count++] = (byte)thisInt; if (data[1] == 0) { if (count == 4) ssid = str; if (count == 5) pass = str; } if (data[1] == 1) { if (count == 16) stripL = thisInt; if (count == 17) stripW = thisInt; if (count == 18) city = thisInt; } } // широковещательный запрос времени для local устройств в сети AP лампы if (data[0] == 0 && cfg.WiFimode && !gotNTP) { now.day = data[1]; now.hour = data[2]; now.min = data[3]; now.sec = data[4]; now.setMs(0); } if (data[0] != cfg.group) return; // не наш адрес, выходим switch (data[1]) { // тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette case 0: DEBUGLN("Control"); switch (data[2]) { case 0: controlHandler(0); break; // выкл case 1: controlHandler(1); break; // вкл case 2: cfg.minLight = phot.getRaw(); break; // мин яркость case 3: cfg.maxLight = phot.getRaw(); break; // макс яркость case 4: changePreset(-1); break; // пред пресет case 5: changePreset(1); break; // след пресет case 6: setPreset(data[3] - 1); break; // конкретный пресет data[3] case 7: cfg.WiFimode = data[3]; EE_updCfgRst(); break; // смена режима WiFi case 8: cfg.role = data[3]; break; // смена роли case 9: cfg.group = data[3]; break; // смена группы case 10: // установка настроек WiFi strcpy(cfg.ssid, ssid); strcpy(cfg.pass, pass); break; case 11: EE_updCfgRst(); break; // рестарт case 12: if (gotNTP) { // OTA обновление, если есть интернет cfg.update = 1; EE_updCfg(); FastLED.clear(); FastLED.show(); char OTA[60]; mString ota(OTA, 60); ota.clear(); ota += OTAhost; ota += OTAfile[data[3]]; DEBUG("Update to "); DEBUGLN(OTA); delay(100); ESPhttpUpdate.update(OTA); } break; case 13: // выключить через if (data[3] == 0) turnoffTmr.stop(); else { turnoffTmr.setInterval((uint32_t)data[3] * 60000ul); turnoffTmr.restart(); } break; } EE_updCfg(); break; case 1: DEBUGLN("Config"); FOR_i(0, CFG_SIZE) { *((byte*)&cfg + i) = data[i + 2]; // загоняем в структуру } cfg.length = stripL; cfg.width = stripW; cfg.cityID = city; if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS; if (cfg.deviceType == GL_TYPE_STRIP) cfg.width = 1; if (cfg.length * cfg.width > MAX_LEDS) cfg.width = MAX_LEDS / cfg.length; ntp.setTimeOffset((cfg.GMT - 13) * 3600); FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100); if (cfg.adcMode == GL_ADC_BRI) switchToPhot(); else if (cfg.adcMode == GL_ADC_MIC) switchToMic(); else disableADC(); EE_updCfg(); break; case 2: DEBUGLN("Preset"); cfg.presetAmount = data[2]; // кол-во режимов FOR_j(0, cfg.presetAmount) { FOR_i(0, PRES_SIZE) { *((byte*)&preset + j * PRES_SIZE + i) = data[j * PRES_SIZE + i + 3]; // загоняем в структуру } } if (!cfg.rotation) setPreset(data[cfg.presetAmount * PRES_SIZE + 3] - 1); EE_updatePreset(); presetRotation(true); // форсировать смену режима loading = true; break; case 3: DEBUGLN("Dawn"); FOR_i(0, (2 + 3 * 7)) { *((byte*)&dawn + i) = data[i + 2]; // загоняем в структуру } EE_updateDawn(); break; case 4: DEBUGLN("From master"); if (cfg.role == GL_SLAVE) { switch (data[2]) { case 0: setPower(data[3]); break; // вкл выкл case 1: setPreset(data[3]); break; // пресет case 2: cfg.bright = data[3]; break; // яркость } EE_updateCfg(); } break; case 5: DEBUGLN("Palette"); FOR_i(0, 1 + 16 * 3) { *((byte*)&pal + i) = data[i + 2]; // загоняем в структуру } updPal(); EE_updatePal(); break; case 6: DEBUGLN("Time"); if (!cfg.WiFimode) { // если мы AP now.day = data[2]; now.hour = data[3]; now.min = data[4]; } gotTime = true; break; } FastLED.clear(); // на всякий случай } } void sendToSlaves(byte data1, byte data2) { if (cfg.role == GL_MASTER) { IPAddress ip = WiFi.localIP(); ip[3] = 255; char reply[20]; mString packet(reply, sizeof(reply)); packet.clear(); packet += GL_KEY; packet += ','; packet += cfg.group; packet += ",4,"; packet += data1; packet += ','; packet += data2; DEBUG("Sending to Slaves: "); DEBUGLN(reply); FOR_i(0, 3) { Udp.beginPacket(ip, 8888); Udp.write(reply); Udp.endPacket(); delay(10); } } }