module LocalUpdate, GyverLamp, WebSocket for C6

This commit is contained in:
Mit4el
2024-12-17 21:09:22 +03:00
parent 5e801e7789
commit a844d08ebf
18 changed files with 4199 additions and 33 deletions

View File

@@ -25,6 +25,14 @@
#include "WebSockets.h"
#include "WebSocketsServer.h"
#ifdef ESP32
#if defined __has_include
#if __has_include("soc/wdev_reg.h")
#include "soc/wdev_reg.h"
#endif // __has_include
#endif // defined __has_include
#endif
WebSocketsServerCore::WebSocketsServerCore(const String & origin, const String & protocol) {
_origin = origin;
_protocol = protocol;
@@ -65,6 +73,7 @@ WebSocketsServerCore::~WebSocketsServerCore() {
}
WebSocketsServer::~WebSocketsServer() {
delete _server;
}
/**
@@ -82,9 +91,13 @@ void WebSocketsServerCore::begin(void) {
#ifdef ESP8266
randomSeed(RANDOM_REG32);
#elif defined(ESP32) && defined(WDEV_RND_REG)
randomSeed(REG_READ(WDEV_RND_REG));
#elif defined(ESP32)
#define DR_REG_RNG_BASE 0x3ff75144
randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
#elif defined(ARDUINO_ARCH_RP2040)
randomSeed(rp2040.hwrand32());
#else
// TODO find better seed
randomSeed(millis());
@@ -400,7 +413,7 @@ bool WebSocketsServerCore::clientIsConnected(uint8_t num) {
return clientIsConnected(client);
}
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
/**
* get an IP for a client
* @param num uint8_t client id
@@ -432,8 +445,16 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i];
// look for match to existing socket before creating a new one
if(clientIsConnected(client)) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
// Check to see if it is the same socket - if so, return it
if(client->tcp->getSocketNumber() == TCPclient->getSocketNumber()) {
return client;
}
#endif
} else {
// state is not connected or tcp connection is lost
if(!clientIsConnected(client)) {
client->tcp = TCPclient;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
@@ -445,7 +466,7 @@ WSclient_t * WebSocketsServerCore::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclien
client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif
client->status = WSC_HEADER;
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifndef NODEBUG_WEBSOCKETS
IPAddress ip = client->tcp->remoteIP();
#endif
@@ -527,7 +548,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
}
if(client->tcp) {
if(client->tcp->connected()) {
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_RP2040)
client->tcp->flush();
#endif
client->tcp->stop();
@@ -546,7 +567,7 @@ void WebSocketsServerCore::dropNativeClient(WSclient_t * client) {
* @param client WSclient_t * ptr to the client struct
*/
void WebSocketsServerCore::clientDisconnect(WSclient_t * client) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
if(client->isSSL && client->ssl) {
if(client->ssl->connected()) {
client->ssl->flush();
@@ -620,7 +641,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
if(!client) {
// no free space to handle client
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
#ifndef NODEBUG_WEBSOCKETS
IPAddress ip = tcpClient->remoteIP();
#endif
@@ -633,6 +654,7 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
client = &dummy;
client->tcp = tcpClient;
dropNativeClient(client);
return nullptr;
}
WEBSOCKETS_YIELD();
@@ -644,12 +666,12 @@ WSclient_t * WebSocketsServerCore::handleNewClient(WEBSOCKETS_NETWORK_CLASS * tc
* Handle incoming Connection Request
*/
void WebSocketsServer::handleNewClients(void) {
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
while(_server->hasClient()) {
#endif
// store new connection
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->accept());
if(!tcpClient) {
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
return;
@@ -657,7 +679,7 @@ void WebSocketsServer::handleNewClients(void) {
handleNewClient(tcpClient);
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
}
#endif
}
@@ -928,7 +950,7 @@ void WebSocketsServer::begin(void) {
void WebSocketsServer::close(void) {
WebSocketsServerCore::close();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
_server->close();
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
_server->end();

View File

@@ -90,7 +90,7 @@ class WebSocketsServerCore : protected WebSockets {
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
void disableHeartbeat();
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_RP2040)
IPAddress remoteIP(uint8_t num);
#endif

View File

@@ -250,8 +250,10 @@ void setup() {
// сброс WDT
#if defined(ESP32)
//SerialPrint("i", "Task", "reset wdt");
#if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init
esp_task_wdt_reset();
#endif
#endif
// сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение)
if (needSaveValues) {
syncValuesFlashJson();
@@ -287,8 +289,8 @@ void setup() {
nullptr, true);
// test
Serial.println("-------test start--------");
Serial.println("--------test end---------");
//Serial.println("-------test start--------");
//Serial.println("--------test end---------");
stopErrorMarker(SETUPLAST_ERRORMARKER);
#if defined(RESTART_DEBUG_INFO)

View File

@@ -159,7 +159,7 @@ void handleStatus() {
}
void handleLocalOTA() {
upgrade_firmware(3, "local");
upgrade_firmware(3,"");
}
#ifdef ESP32

View File

@@ -3,6 +3,9 @@
updateFirm update;
void upgrade_firmware(int type, String path) {
if (path == ""){
path = getBinPath();
}
putUserDataToRam();
// сбросим файл статуса последнего обновления
writeFile("ota.json", "{}");
@@ -44,8 +47,6 @@ bool upgradeFS(String path) {
SerialPrint("E", F("Update"), F("FS Path error"));
saveUpdeteStatus("fs", PATH_ERROR);
return ret;
} else if (path == "local"){
path = getBinPath();
}
#ifdef ESP8266
ESPhttpUpdate.rebootOnUpdate(false);
@@ -88,8 +89,6 @@ bool upgradeBuild(String path) {
SerialPrint("E", F("Update"), F("Build Path error"));
saveUpdeteStatus("build", PATH_ERROR);
return ret;
} else if (path == "local"){
path = getBinPath();
}
#if defined(esp8266_4mb) || defined(esp8266_16mb) || defined(esp8266_1mb) || defined(esp8266_1mb_ota) || defined(esp8266_2mb) || defined(esp8266_2mb_ota)
ESPhttpUpdate.rebootOnUpdate(false);
@@ -134,15 +133,29 @@ const String getBinPath() {
String path = "error";
int targetVersion = 400; //HACKFUCK local OTA version in PrepareServer.py
String serverip;
// if (jsonRead(errorsHeapJson, F("chver"), targetVersion)) {
if (targetVersion >= 400) {
if (jsonRead(errorsHeapJson, F("chver"), targetVersion)) {
if (targetVersion >= 400)
{
if (jsonRead(settingsFlashJson, F("serverip"), serverip))
{
if (serverip != "")
{
path = jsonReadStr(settingsFlashJson, F("serverip")) + "/iotm/" + String(FIRMWARE_NAME) + "/" + String(targetVersion) + "/" ;
}
}
}
}
else if (targetVersion >= 400)
{
if (jsonRead(settingsFlashJson, F("serverlocal"), serverip)) {
if (serverip != "") {
if (serverip != "")
{
path = jsonReadStr(settingsFlashJson, F("serverlocal")) + "/iotm/" + String(FIRMWARE_NAME) + "/" + String(targetVersion) + "/";
}
}
}
// }
SerialPrint("i", F("Update"), "server local: " + path);
return path;
}

View File

@@ -435,9 +435,9 @@ void sendFileToWsByFrames(const String& filename, const String& header, const St
continuation = true;
}
Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: "
+ String(size) + " fin: " + String(fin) + " cnt: " +
String(continuation));
// Serial.println(String(i) + ") " + "ws: " + String(client_id) + " fr sz: "
// + String(size) + " fin: " + String(fin) + " cnt: " +
// String(continuation));
#ifdef ASYNC_WEB_SOCKETS
if (client_id == -1) {
//ws.broadcastBIN(frameBuf, size, fin, continuation);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
// матрица
#define WIDTH 16 // ширина матрицы
#define HEIGHT 16 // высота матрицы
#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты)
#define NUM_LEDS WIDTH *HEIGHT *SEGMENTS
// лента
#define LED_COUNT NUM_LEDS // число светодиодов в кольце/ленте
#define LED_DT 13 // пин, куда подключен DIN ленты

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,770 @@
#include "utility.h"
byte hue;
boolean loadingFlag = true;
// **************** НАСТРОЙКИ ЭФФЕКТОВ ****************
// эффект "синусоиды" - ОТКЛЮЧЕН
#define WAVES_AMOUNT 2 // количество синусоид
// эффект "шарики"
#define BALLS_AMOUNT 3 // количество "шариков"
#define CLEAR_PATH 1 // очищать путь
#define BALL_TRACK 1 // (0 / 1) - вкл/выкл следы шариков
#define DRAW_WALLS 0 // режим с рисованием препятствий для шаров (не работает на ESP и STM32)
#define TRACK_STEP 70 // длина хвоста шарика (чем больше цифра, тем хвост короче)
// эффект "квадратик"
#define BALL_SIZE 3 // размер шара
#define RANDOM_COLOR 1 // случайный цвет при отскоке
// эффект "огонь"
#define SPARKLES 1 // вылетающие угольки вкл выкл
#define HUE_ADD 0 // добавка цвета в огонь (от 0 до 230) - меняет весь цвет пламени
// эффект "кометы"
#define TAIL_STEP 100 // длина хвоста кометы
#define SATURATION 150 // насыщенность кометы (от 0 до 255)
#define STAR_DENSE 60 // количество (шанс появления) комет
// эффект "конфетти"
#define DENSE 3 // плотность конфетти
#define BRIGHT_STEP 70 // шаг уменьшения яркости
// эффект "снег"
#define SNOW_DENSE 10 // плотность снегопада
// эффект "Светляки"
#define LIGHTERS_AM 35 // количество светляков
uint32_t globalColor = 0xffffff; // Цвет рисования при запуске белый
unsigned char matrixValue[8][16];
unsigned char line[WIDTH];
int pcnt = 0;
int effectSpeed = _speed; // скрость изменения эффекта
uint8_t USE_SEGMENTS = 1;
uint8_t BorderWidth = 0;
uint8_t dir_mx, seg_num, seg_size, seg_offset;
uint16_t XY(uint8_t, uint8_t); // __attribute__ ((weak));
// эффекты матрицы
// *********** "дыхание" яркостью ***********
boolean brightnessDirection;
byte breathBrightness; // Яркость эффекта "Дыхание"
byte globalBrightness = _brightness;
void brightnessRoutine()
{
if (brightnessDirection)
{
breathBrightness += 2;
if (breathBrightness > globalBrightness - 1)
{
brightnessDirection = false;
}
}
else
{
breathBrightness -= 2;
if (breathBrightness < 1)
{
brightnessDirection = true;
}
}
FastLED.setBrightness(breathBrightness);
}
// *********** снегопад 2.0 ***********
void snowRoutine()
{
// сдвигаем всё вниз
for (byte x = 0; x < WIDTH; x++)
{
for (byte y = 0; y < HEIGHT - 1; y++)
{
drawPixelXY(x, y, getPixColorXY(x, y + 1));
}
}
for (byte x = 0; x < WIDTH; x++)
{
// заполняем случайно верхнюю строку
// а также не даём двум блокам по вертикали вместе быть
if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, SNOW_DENSE) == 0))
drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4));
else
drawPixelXY(x, HEIGHT - 1, 0x000000);
}
}
// ***************************** БЛУДНЫЙ КУБИК *****************************
int coordB[2];
int8_t vectorB[2];
CRGB ballColor;
void ballRoutine()
{
if (loadingFlag)
{
for (byte i = 0; i < 2; i++)
{
coordB[i] = WIDTH / 2 * 10;
vectorB[i] = random(8, 20);
ballColor = CHSV(random(0, 9) * 28, 255, 255);
}
loadingFlag = false;
}
for (byte i = 0; i < 2; i++)
{
coordB[i] += vectorB[i];
if (coordB[i] < 0)
{
coordB[i] = 0;
vectorB[i] = -vectorB[i];
if (RANDOM_COLOR)
ballColor = CHSV(random(0, 9) * 28, 255, 255);
// vectorB[i] += random(0, 6) - 3;
}
}
if (coordB[0] > (WIDTH - BALL_SIZE) * 10)
{
coordB[0] = (WIDTH - BALL_SIZE) * 10;
vectorB[0] = -vectorB[0];
if (RANDOM_COLOR)
ballColor = CHSV(random(0, 9) * 28, 255, 255);
// vectorB[0] += random(0, 6) - 3;
}
if (coordB[1] > (HEIGHT - BALL_SIZE) * 10)
{
coordB[1] = (HEIGHT - BALL_SIZE) * 10;
vectorB[1] = -vectorB[1];
if (RANDOM_COLOR)
ballColor = CHSV(random(0, 9) * 28, 255, 255);
// vectorB[1] += random(0, 6) - 3;
}
FastLED.clear();
for (byte i = 0; i < BALL_SIZE; i++)
for (byte j = 0; j < BALL_SIZE; j++)
leds[getPixelNumber(coordB[0] / 10 + i, coordB[1] / 10 + j)] = ballColor;
}
// *********** радуга заливка ***********
void rainbowRoutine()
{
hue += 3;
for (byte i = 0; i < WIDTH; i++)
{
CHSV thisColor = CHSV((byte)(hue + i * float(255 / WIDTH)), 255, 255);
for (byte j = 0; j < HEIGHT; j++)
drawPixelXY(i, j, thisColor); // leds[getPixelNumber(i, j)] = thisColor;
}
}
// *********** радуга дигональная ***********
void rainbowDiagonalRoutine()
{
hue += 3;
for (byte x = 0; x < WIDTH; x++)
{
for (byte y = 0; y < HEIGHT; y++)
{
CHSV thisColor = CHSV((byte)(hue + (float)(WIDTH / HEIGHT * x + y) * (float)(255 / 100)), 255, 255);
drawPixelXY(x, y, thisColor); // leds[getPixelNumber(i, j)] = thisColor;
}
}
}
// *********** радуга активных светодиодов (рисунка) ***********
void rainbowColorsRoutine()
{
hue++;
for (byte i = 0; i < WIDTH; i++)
{
CHSV thisColor = CHSV((byte)(hue + i * float(255 / WIDTH)), 255, 255);
for (byte j = 0; j < HEIGHT; j++)
if (getPixColor(getPixelNumber(i, j)) > 0)
drawPixelXY(i, j, thisColor);
}
}
// ****************************** ОГОНЬ ******************************
// ********************** огонь **********************
// these values are substracetd from the generated values to give a shape to the animation
const unsigned char valueMask[8][16] PROGMEM = {
{32, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0, 0, 0, 0, 0, 32},
{64, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 64},
{96, 32, 0, 0, 0, 0, 32, 96, 96, 32, 0, 0, 0, 0, 32, 96},
{128, 64, 32, 0, 0, 32, 64, 128, 128, 64, 32, 0, 0, 32, 64, 128},
{160, 96, 64, 32, 32, 64, 96, 160, 160, 96, 64, 32, 32, 64, 96, 160},
{192, 128, 96, 64, 64, 96, 128, 192, 192, 128, 96, 64, 64, 96, 128, 192},
{255, 160, 128, 96, 96, 128, 160, 255, 255, 160, 128, 96, 96, 128, 160, 255},
{255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255}};
// these are the hues for the fire,
// should be between 0 (red) to about 25 (yellow)
const unsigned char hueMask[8][16] PROGMEM = {
{1, 11, 19, 25, 25, 22, 11, 1, 1, 11, 19, 25, 25, 22, 11, 1},
{1, 8, 13, 19, 25, 19, 8, 1, 1, 8, 13, 19, 25, 19, 8, 1},
{1, 8, 13, 16, 19, 16, 8, 1, 1, 8, 13, 16, 19, 16, 8, 1},
{1, 5, 11, 13, 13, 13, 5, 1, 1, 5, 11, 13, 13, 13, 5, 1},
{1, 5, 11, 11, 11, 11, 5, 1, 1, 5, 11, 11, 11, 11, 5, 1},
{0, 1, 5, 8, 8, 5, 1, 0, 0, 1, 5, 8, 8, 5, 1, 0},
{0, 0, 1, 5, 5, 1, 0, 0, 0, 0, 1, 5, 5, 1, 0, 0},
{0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}};
// Randomly generate the next line (matrix row)
void generateLine()
{
for (uint8_t x = 0; x < WIDTH; x++)
{
line[x] = random(64, 255);
}
}
// shift all values in the matrix up one row
void shiftUp()
{
for (uint8_t y = HEIGHT - 1; y > 0; y--)
{
for (uint8_t x = 0; x < WIDTH; x++)
{
uint8_t newX = x;
if (x > 15)
newX = x % 16;
if (y > 7)
continue;
matrixValue[y][newX] = matrixValue[y - 1][newX];
}
}
for (uint8_t x = 0; x < WIDTH; x++)
{
uint8_t newX = x;
if (x > 15)
newX = x % 16;
matrixValue[0][newX] = line[newX];
}
}
// draw a frame, interpolating between 2 "key frames"
// @param pcnt percentage of interpolation
void drawFrame(int pcnt)
{
int nextv;
// each row interpolates with the one before it
for (unsigned char y = HEIGHT - 1; y > 0; y--)
{
for (unsigned char x = 0; x < WIDTH; x++)
{
uint8_t newX = x;
if (x > 15)
newX = x % 16;
if (y < 8)
{
nextv =
(((100.0 - pcnt) * matrixValue[y][newX] + pcnt * matrixValue[y - 1][newX]) / 100.0) - pgm_read_byte(&(valueMask[y][newX]));
CRGB color = CHSV(
HUE_ADD + pgm_read_byte(&(hueMask[y][newX])), // H
255, // S
(uint8_t)max(0, nextv) // V
);
leds[getPixelNumber(x, y)] = color;
}
else if (y == 8 && SPARKLES)
{
if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0)
drawPixelXY(x, y, getPixColorXY(x, y - 1));
else
drawPixelXY(x, y, 0);
}
else if (SPARKLES)
{
// старая версия для яркости
if (getPixColorXY(x, y - 1) > 0)
drawPixelXY(x, y, getPixColorXY(x, y - 1));
else
drawPixelXY(x, y, 0);
}
}
}
// first row interpolates with the "next" line
for (unsigned char x = 0; x < WIDTH; x++)
{
uint8_t newX = x;
if (x > 15)
newX = x % 16;
CRGB color = CHSV(
HUE_ADD + pgm_read_byte(&(hueMask[0][newX])), // H
255, // S
(uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V
);
// leds[getPixelNumber(newX, 0)] = color; // На форуме пишут что это ошибка - вместо newX должно быть x, иначе
leds[getPixelNumber(x, 0)] = color; // на матрицах шире 16 столбцов нижний правый угол неработает
}
}
void fireRoutine()
{
if (loadingFlag)
{
loadingFlag = false;
FastLED.clear();
generateLine();
memset(matrixValue, 0, sizeof(matrixValue));
}
if (pcnt >= 100)
{
shiftUp();
generateLine();
pcnt = 0;
}
drawFrame(pcnt);
pcnt += 30;
}
// **************** МАТРИЦА *****************
void matrixRoutine()
{
if (loadingFlag)
{
loadingFlag = false;
FastLED.clear();
}
for (byte x = 0; x < WIDTH; x++)
{
// заполняем случайно верхнюю строку
uint32_t thisColor = getPixColorXY(x, HEIGHT - 1);
if (thisColor == 0)
drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, 10) == 0));
else if (thisColor < 0x002000)
drawPixelXY(x, HEIGHT - 1, 0);
else
drawPixelXY(x, HEIGHT - 1, thisColor - 0x002000);
}
// сдвигаем всё вниз
for (byte x = 0; x < WIDTH; x++)
{
for (byte y = 0; y < HEIGHT - 1; y++)
{
drawPixelXY(x, y, getPixColorXY(x, y + 1));
}
}
}
// ********************* ЗВЕЗДОПАД ******************
void fadePixel(byte i, byte j, byte step)
{ // новый фейдер
int pixelNum = getPixelNumber(i, j);
if (getPixColor(pixelNum) == 0)
return;
if (leds[pixelNum].r >= 30 ||
leds[pixelNum].g >= 30 ||
leds[pixelNum].b >= 30)
{
leds[pixelNum].fadeToBlackBy(step);
}
else
{
leds[pixelNum] = 0;
}
}
// функция плавного угасания цвета для всех пикселей
void fader(byte step)
{
for (byte i = 0; i < WIDTH; i++)
{
for (byte j = 0; j < HEIGHT; j++)
{
fadePixel(i, j, step);
}
}
}
void starfallRoutine()
{
// заполняем головами комет левую и верхнюю линию
for (byte i = HEIGHT / 2; i < HEIGHT; i++)
{
if (getPixColorXY(0, i) == 0 && (random(0, STAR_DENSE) == 0) && getPixColorXY(0, i + 1) == 0 && getPixColorXY(0, i - 1) == 0)
leds[getPixelNumber(0, i)] = CHSV(random(0, 200), SATURATION, 255);
}
for (byte i = 0; i < WIDTH / 2; i++)
{
if (getPixColorXY(i, HEIGHT - 1) == 0 && (random(0, STAR_DENSE) == 0) && getPixColorXY(i + 1, HEIGHT - 1) == 0 && getPixColorXY(i - 1, HEIGHT - 1) == 0)
leds[getPixelNumber(i, HEIGHT - 1)] = CHSV(random(0, 200), SATURATION, 255);
}
// сдвигаем по диагонали
for (byte y = 0; y < HEIGHT - 1; y++)
{
for (byte x = WIDTH - 1; x > 0; x--)
{
drawPixelXY(x, y, getPixColorXY(x - 1, y + 1));
}
}
// уменьшаем яркость левой и верхней линии, формируем "хвосты"
for (byte i = HEIGHT / 2; i < HEIGHT; i++)
{
fadePixel(0, i, TAIL_STEP);
}
for (byte i = 0; i < WIDTH / 2; i++)
{
fadePixel(i, HEIGHT - 1, TAIL_STEP);
}
}
// рандомные гаснущие вспышки
void sparklesRoutine()
{
for (byte i = 0; i < DENSE; i++)
{
byte x = random(0, WIDTH);
byte y = random(0, HEIGHT);
if (getPixColorXY(x, y) == 0)
leds[getPixelNumber(x, y)] = CHSV(random(0, 255), 255, 255);
}
fader(BRIGHT_STEP);
}
// ----------------------------- СВЕТЛЯКИ ------------------------------
int lightersPos[2][LIGHTERS_AM];
int8_t lightersSpeed[2][LIGHTERS_AM];
CHSV lightersColor[LIGHTERS_AM];
byte loopCounter;
int angle[LIGHTERS_AM];
int speedV[LIGHTERS_AM];
int8_t angleSpeed[LIGHTERS_AM];
void lightersRoutine()
{
if (loadingFlag)
{
loadingFlag = false;
randomSeed(millis());
for (byte i = 0; i < LIGHTERS_AM; i++)
{
lightersPos[0][i] = random(0, WIDTH * 10);
lightersPos[1][i] = random(0, HEIGHT * 10);
lightersSpeed[0][i] = random(-10, 10);
lightersSpeed[1][i] = random(-10, 10);
lightersColor[i] = CHSV(random(0, 255), 255, 255);
}
}
FastLED.clear();
if (++loopCounter > 20)
loopCounter = 0;
for (byte i = 0; i < map(LIGHTERS_AM, 0, 255, 5, 150); i++)
{
if (loopCounter == 0)
{ // меняем скорость каждые 255 отрисовок
lightersSpeed[0][i] += random(-3, 4);
lightersSpeed[1][i] += random(-3, 4);
lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20);
lightersSpeed[1][i] = constrain(lightersSpeed[1][i], -20, 20);
}
lightersPos[0][i] += lightersSpeed[0][i];
lightersPos[1][i] += lightersSpeed[1][i];
if (lightersPos[0][i] < 0)
lightersPos[0][i] = (WIDTH - 1) * 10;
if (lightersPos[0][i] >= WIDTH * 10)
lightersPos[0][i] = 0;
if (lightersPos[1][i] < 0)
{
lightersPos[1][i] = 0;
lightersSpeed[1][i] = -lightersSpeed[1][i];
}
if (lightersPos[1][i] >= (HEIGHT - 1) * 10)
{
lightersPos[1][i] = (HEIGHT - 1) * 10;
lightersSpeed[1][i] = -lightersSpeed[1][i];
}
drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]);
}
}
// ------------- ПЕЙНТБОЛ -------------
void lightBallsRoutine()
{
if (loadingFlag)
{
loadingFlag = false;
FastLED.clear(); // очистить
dir_mx = WIDTH > HEIGHT ? 0 : 1; // 0 - квадратные сегменты расположены горизонтально, 1 - вертикально
seg_num = dir_mx == 0 ? (WIDTH / HEIGHT) : (HEIGHT / WIDTH); // вычисляем количество сегментов, умещающихся на матрице
seg_size = dir_mx == 0 ? HEIGHT : WIDTH; // Размер квадратного сегмента (высота и ширина равны)
seg_offset = ((dir_mx == 0 ? WIDTH : HEIGHT) - seg_size * seg_num) / (seg_num + 1); // смещение от края матрицы и между сегментами
BorderWidth = 0;
}
// Apply some blurring to whatever's already on the matrix
// Note that we never actually clear the matrix, we just constantly
// blur it repeatedly. Since the blurring is 'lossy', there's
// an automatic trend toward black -- by design.
uint8_t blurAmount = dim8_raw(beatsin8(2, 64, 100));
blur2d(leds, WIDTH, HEIGHT, blurAmount);
// The color of each point shifts over time, each at a different speed.
uint32_t ms = millis();
int16_t idx;
byte cnt = map(effectSpeed, 0, 255, 1, 4);
if (USE_SEGMENTS != 0)
{
// Для неквадратных - вычленяем квадратные сегменты, которые равномерно распределяем по ширине / высоте матрицы
uint8_t i = beatsin8(91, 0, seg_size - BorderWidth - 1);
uint8_t j = beatsin8(109, 0, seg_size - BorderWidth - 1);
uint8_t k = beatsin8(73, 0, seg_size - BorderWidth - 1);
uint8_t m = beatsin8(123, 0, seg_size - BorderWidth - 1);
uint8_t d1 = ms / 29;
uint8_t d2 = ms / 41;
uint8_t d3 = ms / 73;
uint8_t d4 = ms / 97;
for (uint8_t ii = 0; ii < seg_num; ii++)
{
delay(0); // Для предотвращения ESP8266 Watchdog Timer
uint8_t cx = dir_mx == 0 ? (seg_offset * (ii + 1) + seg_size * ii) : 0;
uint8_t cy = dir_mx == 0 ? 0 : (seg_offset * (ii + 1) + seg_size * ii);
uint8_t color_shift = ii * 50;
if (cnt <= 1)
{
idx = XY(i + cx, j + cy);
leds[idx] += CHSV(color_shift + d1, 200U, 255U);
}
if (cnt <= 2)
{
idx = XY(j + cx, k + cy);
leds[idx] += CHSV(color_shift + d2, 200U, 255U);
}
if (cnt <= 3)
{
idx = XY(k + cx, m + cy);
leds[idx] += CHSV(color_shift + d3, 200U, 255U);
}
if (cnt <= 4)
{
idx = XY(m + cx, i + cy);
leds[idx] += CHSV(color_shift + d4, 200U, 255U);
}
// При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые
// не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно.
// При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается
for (byte i2 = cy; i2 < cy + seg_size; i2++)
{
fadePixel(cx + BorderWidth, i2, 15);
fadePixel(cx + seg_size - BorderWidth - 1, i2, 15);
}
}
}
else
{
uint8_t i = beatsin8(91, BorderWidth, WIDTH - BorderWidth - 1);
uint8_t j = beatsin8(109, BorderWidth, HEIGHT - BorderWidth - 1);
uint8_t k = beatsin8(73, BorderWidth, WIDTH - BorderWidth - 1);
uint8_t m = beatsin8(123, BorderWidth, HEIGHT - BorderWidth - 1);
if (cnt <= 1)
{
idx = XY(i, j);
leds[idx] += CHSV(ms / 29, 200U, 255U);
}
if (cnt <= 2)
{
idx = XY(k, j);
leds[idx] += CHSV(ms / 41, 200U, 255U);
}
if (cnt <= 3)
{
idx = XY(k, m);
leds[idx] += CHSV(ms / 73, 200U, 255U);
}
if (cnt <= 4)
{
idx = XY(i, m);
leds[idx] += CHSV(ms / 97, 200U, 255U);
}
if (WIDTH == HEIGHT)
{
// При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые
// не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно.
// При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается
for (byte i = 0; i < HEIGHT; i++)
{
fadePixel(0, i, 15);
fadePixel(WIDTH - 1, i, 15);
}
}
}
}
// ------------- ВОДОВОРОТ -------------
void swirlRoutine()
{
if (loadingFlag)
{
loadingFlag = false;
FastLED.clear(); // очистить
dir_mx = WIDTH > HEIGHT ? 0 : 1; // 0 - квадратные сегменты расположены горизонтально, 1 - вертикально
seg_num = dir_mx == 0 ? (WIDTH / HEIGHT) : (HEIGHT / WIDTH); // вычисляем количество сегментов, умещающихся на матрице
seg_size = dir_mx == 0 ? HEIGHT : WIDTH; // Размер квадратного сегмента (высота и ширина равны)
seg_offset = ((dir_mx == 0 ? WIDTH : HEIGHT) - seg_size * seg_num) / (seg_num + 1); // смещение от края матрицы и между сегментами
BorderWidth = seg_num == 1 ? 0 : 1;
}
// Apply some blurring to whatever's already on the matrix
// Note that we never actually clear the matrix, we just constantly
// blur it repeatedly. Since the blurring is 'lossy', there's
// an automatic trend toward black -- by design.
uint8_t blurAmount = dim8_raw(beatsin8(2, 64, 100));
blur2d(leds, WIDTH, HEIGHT, blurAmount);
uint32_t ms = millis();
int16_t idx;
if (USE_SEGMENTS != 0)
{
// Use two out-of-sync sine waves
uint8_t i = beatsin8(41, 0, seg_size - BorderWidth - 1);
uint8_t j = beatsin8(27, 0, seg_size - BorderWidth - 1);
// Also calculate some reflections
uint8_t ni = (seg_size - 1) - i;
uint8_t nj = (seg_size - 1) - j;
uint8_t d1 = ms / 11;
uint8_t d2 = ms / 13;
uint8_t d3 = ms / 17;
uint8_t d4 = ms / 29;
uint8_t d5 = ms / 37;
uint8_t d6 = ms / 41;
for (uint8_t ii = 0; ii < seg_num; ii++)
{
delay(0); // Для предотвращения ESP8266 Watchdog Timer
uint8_t cx = dir_mx == 0 ? (seg_offset * (ii + 1) + seg_size * ii) : 0;
uint8_t cy = dir_mx == 0 ? 0 : (seg_offset * (ii + 1) + seg_size * ii);
uint8_t color_shift = ii * 50;
// The color of each point shifts over time, each at a different speed.
idx = XY(i + cx, j + cy);
leds[idx] += CHSV(color_shift + d1, 200, 192);
idx = XY(ni + cx, nj + cy);
leds[idx] += CHSV(color_shift + d2, 200, 192);
idx = XY(i + cx, nj + cy);
leds[idx] += CHSV(color_shift + d3, 200, 192);
idx = XY(ni + cx, j + cy);
leds[idx] += CHSV(color_shift + d4, 200, 192);
idx = XY(j + cx, i + cy);
leds[idx] += CHSV(color_shift + d5, 200, 192);
idx = XY(nj + cx, ni + cy);
leds[idx] += CHSV(color_shift + d6, 200, 192);
// При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые
// не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно.
// При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается
for (byte i2 = cy; i2 < cy + seg_size; i2++)
{
fadePixel(cx, i2, 15);
fadePixel(cx + BorderWidth, i2, 15);
fadePixel(cx + seg_size - 1, i2, 15);
fadePixel(cx + seg_size - BorderWidth - 1, i2, 15);
}
}
}
else
{
// Use two out-of-sync sine waves
uint8_t i = beatsin8(41, BorderWidth, WIDTH - BorderWidth - 1);
uint8_t j = beatsin8(27, BorderWidth, HEIGHT - BorderWidth - 1);
// Also calculate some reflections
uint8_t ni = (WIDTH - 1) - i;
uint8_t nj = (HEIGHT - 1) - j;
// The color of each point shifts over time, each at a different speed.
idx = XY(i, j);
leds[idx] += CHSV(ms / 11, 200, 192);
idx = XY(ni, nj);
leds[idx] += CHSV(ms / 13, 200, 192);
idx = XY(i, nj);
leds[idx] += CHSV(ms / 17, 200, 192);
idx = XY(ni, j);
leds[idx] += CHSV(ms / 29, 200, 192);
if (HEIGHT == WIDTH)
{
// для квадратных матриц - 6 точек создают более красивую картину
idx = XY(j, i);
leds[idx] += CHSV(ms / 37, 200, 192);
idx = XY(nj, ni);
leds[idx] += CHSV(ms / 41, 200, 192);
// При соединении матрицы из угла вверх или вниз почему-то слева и справа узора остаются полосы, которые
// не гаснут обычным blur - гасим полоски левой и правой стороны дополнительно.
// При соединении из угла влево или вправо или на неквадратных матрицах такого эффекта не наблюдается
for (byte i = 0; i < HEIGHT; i++)
{
fadePixel(0, i, 15);
fadePixel(WIDTH - 1, i, 15);
}
}
}
}
uint16_t XY(uint8_t x, uint8_t y)
{
return getPixelNumber(x, y);
}
//--------------------крутящаяся радуга матрица------------------
void rainbow_loop_matrix()
{ //-m3-LOOP HSV RAINBOW
idex++;
ihue = ihue + thisstep;
if (idex >= LED_COUNT)
{
idex = 0;
}
if (ihue > 255)
{
ihue = 0;
}
for (byte i = 0; i < WIDTH; i++)
{
CHSV thisColor = CHSV(ihue, thissat, 255);
for (byte j = 0; j < HEIGHT; j++)
drawPixelXY(i, j, thisColor); // leds[getPixelNumber(i, j)] = thisColor;
}
LEDS.show();
if (safeDelay(thisdelay))
return;
}

View File

@@ -0,0 +1,40 @@
{
"menuSection": "screens",
"configItem": [
{
"global": 0,
"name": "GyverLAMP",
"type": "Reading",
"subtype": "GyverLAMP",
"id": "GyverLAMP",
"widget": "range",
"page": "Кнопки",
"descr": "GyverLAMP",
"needSave": 0,
"brightness": "10",
"speed": 30,
"dalay": 10000
}
],
"about": {
"authorName": "",
"authorContact": "",
"authorGit": "",
"exampleURL": "",
"specialThanks": "",
"moduleName": "GyverLAMP",
"moduleVersion": "1",
"moduleDesc": "xxx",
"propInfo": {},
"funcInfo": []
},
"defActive": false,
"usedLibs": {
"esp32*": [
"fastled/FastLED@^3.5.0"
],
"esp82*": [
"fastled/FastLED@^3.5.0"
]
}
}

View File

@@ -0,0 +1,92 @@
#include "config.h"
#define MATRIX_TYPE 0
// #define NUM_LEDS LED_COUNT
// **************** НАСТРОЙКА МАТРИЦЫ ****************
#if (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 0)
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y y
#elif (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 1)
#define _WIDTH HEIGHT
#define THIS_X y
#define THIS_Y x
#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 0)
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y (HEIGHT - y - 1)
#elif (CONNECTION_ANGLE == 1 && STRIP_DIRECTION == 3)
#define _WIDTH HEIGHT
#define THIS_X (HEIGHT - y - 1)
#define THIS_Y x
#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 2)
#define _WIDTH WIDTH
#define THIS_X (WIDTH - x - 1)
#define THIS_Y (HEIGHT - y - 1)
#elif (CONNECTION_ANGLE == 2 && STRIP_DIRECTION == 3)
#define _WIDTH HEIGHT
#define THIS_X (HEIGHT - y - 1)
#define THIS_Y (WIDTH - x - 1)
#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 2)
#define _WIDTH WIDTH
#define THIS_X (WIDTH - x - 1)
#define THIS_Y y
#elif (CONNECTION_ANGLE == 3 && STRIP_DIRECTION == 1)
#define _WIDTH HEIGHT
#define THIS_X y
#define THIS_Y (WIDTH - x - 1)
#else
#define _WIDTH WIDTH
#define THIS_X x
#define THIS_Y y
#pragma message "Wrong matrix parameters! Set to default"
#endif
// получить номер пикселя в ленте по координатам
uint16_t getPixelNumber(int8_t x, int8_t y)
{
if ((THIS_Y % 2 == 0) || MATRIX_TYPE)
{ // если чётная строка
return (THIS_Y * _WIDTH + THIS_X);
}
else
{ // если нечётная строка
return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1);
}
}
// функция отрисовки точки по координатам X Y
void drawPixelXY(int8_t x, int8_t y, CRGB color)
{
if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1)
return;
int thisPixel = getPixelNumber(x, y) * SEGMENTS;
for (byte i = 0; i < SEGMENTS; i++)
{
leds[thisPixel + i] = color;
}
//FastLED.show();
}
// функция получения цвета пикселя по его номеру
uint32_t getPixColor(int thisSegm)
{
int thisPixel = thisSegm * SEGMENTS;
if (thisPixel < 0 || thisPixel > NUM_LEDS - 1)
return 0;
return (((uint32_t)leds[thisPixel].r << 16) | ((long)leds[thisPixel].g << 8) | (long)leds[thisPixel].b);
}
// функция получения цвета пикселя в матрице по его координатам
uint32_t getPixColorXY(int8_t x, int8_t y)
{
return getPixColor(getPixelNumber(x, y));
}

View File

@@ -50,7 +50,7 @@
}
]
},
"defActive": true,
"defActive": false,
"usedLibs": {
"esp32*": [
"https://github.com/RoboticsBrno/ServoESP32#v1.0.3"

View File

@@ -38,7 +38,7 @@
"freq": "Частота"
}
},
"defActive": true,
"defActive": false,
"usedLibs": {
"esp82*": []
}

View File

@@ -64,7 +64,13 @@
},
"defActive": false,
"usedLibs": {
"esp32*": [
"esp32c62_4mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32c62_8mb": [
"https://github.com/h2zero/NimBLE-Arduino#c6-build"
],
"esp32_4mb3f": [
"https://github.com/Mit4el/NimBLE-Arduino.git"
],
"esp32s2_4mb": [

View File

@@ -0,0 +1,27 @@
#include "Global.h"
#include "classes/IoTItem.h"
class UpdateServer : public IoTItem {
public:
UpdateServer(String parameters) : IoTItem(parameters) {}
void onModuleOrder(String &key, String &value) {
if (key == "startUpdateAll") {
upgrade_firmware(3, value);
} else if (key == "startUpdateFS") {
upgrade_firmware(2, value);
} else if (key == "startUpdateFW") {
upgrade_firmware(1, value);
}
}
~UpdateServer() {};
};
void* getAPI_UpdateServer(String subtype, String param) {
if (subtype == F("UpdateServer")) {
return new UpdateServer(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,41 @@
{
"menuSection": "virtual_elments",
"configItem": [
{
"global": 0,
"name": "Свой сервер обновлений",
"type": "Reading",
"subtype": "UpdateServer",
"id": "UpdateServer",
"widget": "",
"page": "",
"descr": "",
"btn-startUpdateAll": "http://192.168.11.112/iotm/esp8266_4mb/400",
"btn-startUpdateFS": "http://192.168.11.112/iotm/esp8266_4mb/400",
"btn-startUpdateFW": "http://192.168.11.112/iotm/esp8266_4mb/400"
}
],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"exampleURL": "https://iotmanager.org/",
"specialThanks": "",
"moduleName": "UpdateServer",
"moduleVersion": "1.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"title": "Свой сервер обновлений",
"moduleDesc": "Модуль для получения прошивки из своего сервера обновлений.",
"propInfo": {
"btn-startUpdate": "Кнопка запуска процесса обновления из указанного URL"
}
},
"defActive": true,
"usedLibs": {
"esp32*": [],
"esp82*": []
}
}

View File

@@ -96,8 +96,10 @@ void routerConnect()
}
#if defined(ESP32)
//SerialPrint("i", "Task", "Resetting WDT...");
#if !defined(esp32c6_4mb) && !defined(esp32c6_8mb) //TODO esp32-c6 переписать esp_task_wdt_init
esp_task_wdt_reset();
#endif
#endif
Serial.print(".");
delay(1000);
}