added saving image snapshot to micro SD card
parent
b32f0e7a86
commit
55bdcecf84
|
|
@ -123,6 +123,7 @@ void setup() {
|
|||
xTaskCreatePinnedToCore(System_TaskStreamTelemetry, "PrintStreamTelemetry", 3300, NULL, 6, &Task_StreamTelemetry, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||
xTaskCreatePinnedToCore(System_TaskSysLed, "SystemLed", 3000, NULL, 7, &Task_SysLed, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||
xTaskCreatePinnedToCore(System_TaskWiFiWatchdog, "WiFiWatchdog", 3500, NULL, 8, &Task_WiFiWatchdog, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||
//xTaskCreatePinnedToCore(System_TaskSdCardRemove, "SdCardRemove", 3000, NULL, 9, &Task_SdCardFileRemove, 0); /*function, description, stack size, parameters, priority, task handle, core*/
|
||||
|
||||
/* init wdg */
|
||||
SystemLog.AddEvent(LogLevel_Info, F("Init WDG"));
|
||||
|
|
@ -136,6 +137,7 @@ void setup() {
|
|||
esp_task_wdt_add(Task_StreamTelemetry);
|
||||
esp_task_wdt_add(Task_SysLed);
|
||||
esp_task_wdt_add(Task_WiFiWatchdog);
|
||||
//esp_task_wdt_add(Task_SdCardFileRemove);
|
||||
esp_task_wdt_reset(); /* reset wdg */
|
||||
|
||||
SystemLog.AddEvent(LogLevel_Info, F("MCU configuration done"));
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -30,6 +30,7 @@ Camera::Camera(Configuration* i_conf, Logs* i_log, uint8_t i_FlashPin) {
|
|||
PhotoExifData.header = NULL;
|
||||
PhotoExifData.len = 0;
|
||||
PhotoExifData.offset = 0;
|
||||
PhotoSending = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -185,6 +186,10 @@ framesize_t Camera::TransformFrameSizeDataType(uint8_t i_data) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Camera::SetPhotoSending(bool i_data) {
|
||||
PhotoSending = i_data;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Function set flash status
|
||||
@param bool i_data - true = on, false = off
|
||||
|
|
@ -268,6 +273,11 @@ void Camera::ReinitCameraModule() {
|
|||
@return none
|
||||
*/
|
||||
void Camera::CapturePhoto() {
|
||||
|
||||
if (true == PhotoSending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (false == StreamOnOff) {
|
||||
if (!xSemaphoreTake(frameBufferSemaphore, portMAX_DELAY)) {
|
||||
log->AddEvent(LogLevel_Error, F("Failed to take frame buffer semaphore"));
|
||||
|
|
@ -313,13 +323,21 @@ void Camera::CapturePhoto() {
|
|||
if (ControlFlag != 0x00) {
|
||||
log->AddEvent(LogLevel_Error, "Camera capture failed! photo " + String(ControlFlag, HEX));
|
||||
FrameBuffer->len = 0;
|
||||
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Info, "Photo OK! " + String(ControlFlag, HEX));
|
||||
|
||||
/* generate exif header */
|
||||
update_exif_from_cfg(imageExifRotation);
|
||||
get_exif_header(FrameBuffer, &PhotoExifData.header, &PhotoExifData.len);
|
||||
PhotoExifData.offset = get_jpeg_data_offset(FrameBuffer);
|
||||
CameraCaptureSuccess = true;
|
||||
|
||||
if (PhotoExifData.header != NULL) {
|
||||
log->AddEvent(LogLevel_Info, "Exif header OK! Len: " + String(PhotoExifData.len));
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Error, "Exif header failed! " + String(PhotoExifData.len));
|
||||
}
|
||||
}
|
||||
|
||||
attempts++;
|
||||
|
|
@ -335,33 +353,6 @@ void Camera::CapturePhoto() {
|
|||
ledcWrite(FLASH_PWM_CHANNEL, FLASH_OFF_STATUS);
|
||||
}
|
||||
xSemaphoreGive(frameBufferSemaphore);
|
||||
/*
|
||||
// Save picture
|
||||
File file = SD_MMC.open("/photo.jpg", FILE_WRITE);
|
||||
|
||||
if (file) {
|
||||
size_t ret = 0;
|
||||
if (PhotoExifData.header != NULL) {
|
||||
ret = file.write(PhotoExifData.header, PhotoExifData.len);
|
||||
if (ret != PhotoExifData.len) {
|
||||
Serial.println("Failed\nError while writing header to file");
|
||||
PhotoExifData.offset = 0;
|
||||
}
|
||||
} else {
|
||||
PhotoExifData.offset = 0;
|
||||
}
|
||||
|
||||
ret = file.write(&FrameBuffer->buf[PhotoExifData.offset], FrameBuffer->len - PhotoExifData.offset);
|
||||
if (ret != FrameBuffer->len - PhotoExifData.offset) {
|
||||
Serial.println("Failed\nError while writing to file");
|
||||
} else {
|
||||
Serial.printf("Saved as %s\n", "photo.jpg");
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
Serial.printf("Failed\nCould not open file: %s\n", "photo.jpg");
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ private:
|
|||
uint8_t imageExifRotation; ///< image rotation. 0 degree: value 1, 90 degree: value 6, 180 degree: value 3, 270 degree: value 8
|
||||
|
||||
bool CameraCaptureSuccess; ///< camera capture success
|
||||
bool PhotoSending; ///< photo sending
|
||||
|
||||
/* OV2640 camera module pinout and cfg*/
|
||||
camera_config_t CameraConfig; ///< camera configuration
|
||||
|
|
@ -109,6 +110,7 @@ public:
|
|||
camera_fb_t *GetPhotoFb();
|
||||
PhotoExifData_t * GetPhotoExifData();
|
||||
framesize_t TransformFrameSizeDataType(uint8_t);
|
||||
void SetPhotoSending(bool);
|
||||
|
||||
void SetFlashStatus(bool);
|
||||
bool GetFlashStatus();
|
||||
|
|
|
|||
|
|
@ -83,6 +83,13 @@ void Configuration::ReadCfg() {
|
|||
LoadGainCtrl();
|
||||
LoadAgcGain();
|
||||
LoadPrusaConnectHostname();
|
||||
LoadNetworkIpMethod();
|
||||
LoadNetworkIp();
|
||||
LoadNetworkMask();
|
||||
LoadNetworkGateway();
|
||||
LoadNetworkDns();
|
||||
LoadCameraImageExifRotation();
|
||||
LoadTimeLapseFunctionStatus();
|
||||
Log->AddEvent(LogLevel_Info, "Active WiFi client cfg: " + String(CheckActifeWifiCfgFlag() ? "true" : "false"));
|
||||
Log->AddEvent(LogLevel_Info, F("Load CFG from EEPROM done"));
|
||||
}
|
||||
|
|
@ -167,6 +174,7 @@ void Configuration::DefaultCfg() {
|
|||
SaveNetworkGateway(FACTORY_CFG_NETWORK_STATIC_GATEWAY);
|
||||
SaveNetworkDns(FACTORY_CFG_NETWORK_STATIC_DNS);
|
||||
SaveCameraImageExifRotation(FACTORY_CFG_IMAGE_EXIF_ROTATION);
|
||||
SaveTimeLapseFunctionStatus(FACTORY_CFG_TIMELAPS_ENABLE);
|
||||
Log->AddEvent(LogLevel_Warning, F("+++++++++++++++++++++++++++"));
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +659,6 @@ void Configuration::SaveBasicAuthUsername(String i_data) {
|
|||
SaveString(EEPROM_ADDR_BASIC_AUTH_USERNAME_START, EEPROM_ADDR_BASIC_AUTH_USERNAME_LENGTH, i_data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@info save password fof BasicAuth to EEPROM
|
||||
@param string - password
|
||||
|
|
@ -834,6 +841,16 @@ void Configuration::SaveCameraImageExifRotation(uint8_t i_data) {
|
|||
SaveUint8(EEPROM_ADDR_IMAGE_ROTATION_START, i_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@info Save time lapse function status
|
||||
@param bool - value
|
||||
@return none
|
||||
*/
|
||||
void Configuration::SaveTimeLapseFunctionStatus(bool i_data) {
|
||||
Log->AddEvent(LogLevel_Verbose, "Save time lapse function status: " + String(i_data));
|
||||
SaveBool(EEPROM_ADDR_TIMELAPS_ENABLE_START, i_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@info load refresh interval from eeprom
|
||||
@param none
|
||||
|
|
@ -1311,6 +1328,11 @@ String Configuration::LoadNetworkDns() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load camera image rotation from EEPROM
|
||||
*
|
||||
* @return uint8_t - rotation
|
||||
*/
|
||||
uint8_t Configuration::LoadCameraImageExifRotation() {
|
||||
uint8_t ret = EEPROM.read(EEPROM_ADDR_IMAGE_ROTATION_START);
|
||||
|
||||
|
|
@ -1324,4 +1346,20 @@ uint8_t Configuration::LoadCameraImageExifRotation() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load time lapse function status
|
||||
*
|
||||
* @return bool - status
|
||||
*/
|
||||
bool Configuration::LoadTimeLapseFunctionStatus() {
|
||||
uint8_t ret = EEPROM.read(EEPROM_ADDR_TIMELAPS_ENABLE_START);
|
||||
Log->AddEvent(LogLevel_Info, F("Time lapse function status: "), String(ret));
|
||||
|
||||
if (ret == 255) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return (bool) ret;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
class Configuration {
|
||||
public:
|
||||
Configuration(Logs*);
|
||||
Configuration(Logs *);
|
||||
~Configuration(){};
|
||||
void Init();
|
||||
bool CheckActifeWifiCfgFlag();
|
||||
|
|
@ -72,6 +72,7 @@ public:
|
|||
void SaveNetworkGateway(String);
|
||||
void SaveNetworkDns(String);
|
||||
void SaveCameraImageExifRotation(uint8_t);
|
||||
void SaveTimeLapseFunctionStatus(bool);
|
||||
|
||||
uint8_t LoadRefreshInterval();
|
||||
String LoadToken();
|
||||
|
|
@ -113,6 +114,7 @@ public:
|
|||
String LoadNetworkGateway();
|
||||
String LoadNetworkDns();
|
||||
uint8_t LoadCameraImageExifRotation();
|
||||
bool LoadTimeLapseFunctionStatus();
|
||||
|
||||
private:
|
||||
Logs *Log; ///< Pointer to Logs object
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ PrusaConnect::PrusaConnect(Configuration *i_conf, Logs *i_log, Camera *i_camera,
|
|||
*/
|
||||
void PrusaConnect::Init() {
|
||||
log->AddEvent(LogLevel_Info, F("Init PrusaConnect lib"));
|
||||
BackendReceivedStatus = F("Wait for first connection");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -51,6 +52,7 @@ void PrusaConnect::LoadCfgFromEeprom() {
|
|||
Fingerprint = config->LoadFingerprint();
|
||||
RefreshInterval = config->LoadRefreshInterval();
|
||||
PrusaConnectHostname = config->LoadPrusaConnectHostname();
|
||||
EnableTimelapsPhotoSave = config->LoadTimeLapseFunctionStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -86,7 +88,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
|||
//client.setInsecure();
|
||||
client.setTimeout(1000);
|
||||
client.setNoDelay(true);
|
||||
|
||||
|
||||
log->AddEvent(LogLevel_Verbose, F("Connecting to server..."));
|
||||
|
||||
/* connecting to server */
|
||||
|
|
@ -138,7 +140,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
|||
}
|
||||
|
||||
/* sending photo */
|
||||
for (size_t i=0; i < fbLen; i += PHOTO_FRAGMENT_SIZE) {
|
||||
for (size_t i = 0; i < fbLen; i += PHOTO_FRAGMENT_SIZE) {
|
||||
if ((i + PHOTO_FRAGMENT_SIZE) < fbLen) {
|
||||
sendet_data += client.write(fbBuf, PHOTO_FRAGMENT_SIZE);
|
||||
fbBuf += PHOTO_FRAGMENT_SIZE;
|
||||
|
|
@ -158,7 +160,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
|||
SystemLog.AddEvent(LogLevel_Warning, F("Photo without EXIF data sent"));
|
||||
}
|
||||
|
||||
/* sending device information */
|
||||
/* sending device information */
|
||||
} else if (SendInfo == i_data_type) {
|
||||
log->AddEvent(LogLevel_Verbose, F("Sending info"));
|
||||
sendet_data = client.print(*i_data);
|
||||
|
|
@ -171,7 +173,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
|||
/* read response from server */
|
||||
String response = "";
|
||||
String fullResponse = "";
|
||||
log->AddEvent(LogLevel_Verbose, "Response:");
|
||||
log->AddEvent(LogLevel_Verbose, F("Response:"));
|
||||
while (client.connected()) {
|
||||
if (client.available()) {
|
||||
response = client.readStringUntil('\n');
|
||||
|
|
@ -219,6 +221,7 @@ bool PrusaConnect::SendDataToBackend(String *i_data, int i_data_length, String i
|
|||
*/
|
||||
void PrusaConnect::SendPhotoToBackend() {
|
||||
log->AddEvent(LogLevel_Info, F("Start sending photo to prusaconnect"));
|
||||
camera->SetPhotoSending(true);
|
||||
String Photo = "";
|
||||
size_t total_len = 0;
|
||||
|
||||
|
|
@ -227,7 +230,8 @@ void PrusaConnect::SendPhotoToBackend() {
|
|||
} else {
|
||||
total_len = camera->GetPhotoFb()->len;
|
||||
}
|
||||
SendDataToBackend(&Photo, total_len, "image/jpg", "Photo", HOST_URL_CAM_PATH, SendPhoto);
|
||||
SendDataToBackend(&Photo, total_len, F("image/jpg"), F("Photo"), HOST_URL_CAM_PATH, SendPhoto);
|
||||
camera->SetPhotoSending(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -258,7 +262,7 @@ void PrusaConnect::SendInfoToBackend() {
|
|||
|
||||
serializeJson(json_data, json_string);
|
||||
log->AddEvent(LogLevel_Info, "Data: " + json_string);
|
||||
bool response = SendDataToBackend(&json_string, json_string.length(), "application/json", "Info", HOST_URL_INFO_PATH, SendInfo);
|
||||
bool response = SendDataToBackend(&json_string, json_string.length(), F("application/json"), F("Info"), HOST_URL_INFO_PATH, SendInfo);
|
||||
|
||||
if (true == response) {
|
||||
SendDeviceInformationToBackend = false;
|
||||
|
|
@ -274,11 +278,22 @@ void PrusaConnect::SendInfoToBackend() {
|
|||
*/
|
||||
void PrusaConnect::TakePictureAndSendToBackend() {
|
||||
camera->CapturePhoto();
|
||||
|
||||
/* check if photo was captured */
|
||||
if (camera->GetCameraCaptureSuccess() == true) {
|
||||
|
||||
/* send photo to backend */
|
||||
SendPhotoToBackend();
|
||||
|
||||
/* save photo to SD card */
|
||||
if (false == camera->GetStreamStatus()) {
|
||||
SavePhotoToSdCard();
|
||||
}
|
||||
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Error, F("Error capturing photo. Stop sending to backend!"));
|
||||
}
|
||||
|
||||
camera->CaptureReturnFrameBuffer();
|
||||
}
|
||||
|
||||
|
|
@ -428,6 +443,51 @@ void PrusaConnect::SetPrusaConnectHostname(String i_data) {
|
|||
config->SavePrusaConnectHostname(PrusaConnectHostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set time laps photo save status
|
||||
*
|
||||
* @param bool - status
|
||||
*/
|
||||
void PrusaConnect::SetTimeLapsPhotoSaveStatus(bool i_data) {
|
||||
EnableTimelapsPhotoSave = i_data;
|
||||
config->SaveTimeLapseFunctionStatus(EnableTimelapsPhotoSave);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Function for saving photo to SD card
|
||||
@param none
|
||||
@return none
|
||||
*/
|
||||
void PrusaConnect::SavePhotoToSdCard() {
|
||||
if (EnableTimelapsPhotoSave == true) {
|
||||
log->AddEvent(LogLevel_Info, F("Save TimeLaps photo to SD card"));
|
||||
if (false == log->CheckDir(SD_MMC, TIMELAPS_PHOTO_FOLDER)) {
|
||||
log->AddEvent(LogLevel_Info, F("Create folder for TimeLaps photos"));
|
||||
log->CreateDir(SD_MMC, TIMELAPS_PHOTO_FOLDER);
|
||||
}
|
||||
|
||||
String FileName = String(TIMELAPS_PHOTO_FOLDER) + "/" + String(TIMELAPS_PHOTO_PREFIX) + "_";
|
||||
FileName += log->GetSystemTime();
|
||||
FileName += TIMELAPS_PHOTO_SUFFIX;
|
||||
log->AddEvent(LogLevel_Verbose, "Saving file: " + FileName);
|
||||
|
||||
if (camera->GetPhotoExifData()->header != NULL) {
|
||||
if (log->WritePicture(FileName, camera->GetPhotoFb()->buf + camera->GetPhotoExifData()->offset, camera->GetPhotoFb()->len - camera->GetPhotoExifData()->offset, camera->GetPhotoExifData()->header, camera->GetPhotoExifData()->len) == true) {
|
||||
log->AddEvent(LogLevel_Info, F("Photo saved to SD card. EXIF"));
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Error, F("Error saving photo to SD card. EXIF"));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (log->WritePicture(FileName, camera->GetPhotoFb()->buf, camera->GetPhotoFb()->len) == true) {
|
||||
log->AddEvent(LogLevel_Info, F("Photo saved to SD card"));
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Error, F("Error saving photo to SD card"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get refresh interval
|
||||
*
|
||||
|
|
@ -512,6 +572,10 @@ String PrusaConnect::CovertBackendAvailabilitStatusToString(BackendAvailabilitSt
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool PrusaConnect::GetTimeLapsPhotoSaveStatus() {
|
||||
return EnableTimelapsPhotoSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increase sending interval counter
|
||||
*
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ private:
|
|||
BackendAvailabilitStatus BackendAvailability; ///< status of backend availability
|
||||
bool SendDeviceInformationToBackend; ///< flag for sending device information to backend
|
||||
uint8_t SendingIntervalCounter; ///< counter for sending interval, represents seconds
|
||||
bool EnableTimelapsPhotoSave; ///< flag for saving photo to SD card
|
||||
|
||||
String Token; ///< token for backend communication
|
||||
String Fingerprint; ///< fingerprint for backend communication
|
||||
|
|
@ -86,6 +87,9 @@ public:
|
|||
void SetToken(String);
|
||||
void SetBackendAvailabilitStatus(BackendAvailabilitStatus);
|
||||
void SetPrusaConnectHostname(String);
|
||||
void SetTimeLapsPhotoSaveStatus(bool);
|
||||
|
||||
void SavePhotoToSdCard();
|
||||
|
||||
uint8_t GetRefreshInterval();
|
||||
String GetBackendReceivedStatus();
|
||||
|
|
@ -94,6 +98,7 @@ public:
|
|||
String GetPrusaConnectHostname();
|
||||
BackendAvailabilitStatus GetBackendAvailabilitStatus();
|
||||
String CovertBackendAvailabilitStatusToString(BackendAvailabilitStatus);
|
||||
bool GetTimeLapsPhotoSaveStatus();
|
||||
|
||||
void IncreaseSendingIntervalCounter();
|
||||
void SetSendingIntervalCounter(uint8_t);
|
||||
|
|
|
|||
|
|
@ -101,13 +101,7 @@ void Logs::Init() {
|
|||
|
||||
if (true == GetCardDetectedStatus()) {
|
||||
/* check maximum log file size */
|
||||
uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName);
|
||||
Serial.printf("Log file size: %d\n", FileSize);
|
||||
if (FileSize >= LOGS_FILE_MAX_SIZE) {
|
||||
uint16_t file_count = FileCount(SD_MMC, FilePath, FileName);
|
||||
Serial.printf("Maximum log file size.\nFile count: %d\n", file_count);
|
||||
RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count));
|
||||
}
|
||||
CheckMaxLogFileSize();
|
||||
|
||||
/* added first message to log file after start MCU */
|
||||
String msg = F("----------------------------------------------------------------\n");
|
||||
|
|
@ -169,6 +163,30 @@ void Logs::AddEvent(LogLevel_enum level, String msg, bool newLine, bool date) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void Logs::AddEvent(LogLevel_enum level, const __FlashStringHelper *msg, String parameters, bool newLine, bool date) {
|
||||
if (LogLevel >= level) {
|
||||
String LogMsg = "";
|
||||
|
||||
if (true == date) {
|
||||
LogMsg += GetSystemTime();
|
||||
LogMsg += " - ";
|
||||
}
|
||||
LogMsg += msg;
|
||||
LogMsg += parameters;
|
||||
if (true == newLine) {
|
||||
LogMsg += "\n";
|
||||
}
|
||||
|
||||
AppendFile(SD_MMC, FilePath + FileName, LogMsg);
|
||||
Serial.print(LogMsg);
|
||||
}
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
else {
|
||||
Serial.println(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@info Set file name
|
||||
@param String - file name
|
||||
|
|
@ -242,6 +260,21 @@ bool Logs::GetNtpTimeSynced() {
|
|||
return NtpTimeSynced;
|
||||
}
|
||||
|
||||
/**
|
||||
@info Check maximum log file size
|
||||
@param none
|
||||
@return none
|
||||
*/
|
||||
void Logs::CheckMaxLogFileSize() {
|
||||
uint32_t FileSize = GetFileSize(SD_MMC, FilePath + FileName);
|
||||
Serial.printf("Log file size: %d bytes\n", FileSize);
|
||||
if (FileSize >= LOGS_FILE_MAX_SIZE) {
|
||||
uint16_t file_count = FileCount(SD_MMC, FilePath, FileName);
|
||||
Serial.printf("Maximum log file size.\nFile count: %d\n", file_count);
|
||||
RenameFile(SD_MMC, FilePath + FileName, FilePath + FileName + String(file_count));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@info Get system time
|
||||
@param none
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
|
||||
void Init();
|
||||
void AddEvent(LogLevel_enum, String, bool = true, bool = true);
|
||||
void AddEvent(LogLevel_enum, const __FlashStringHelper*, String, bool = true, bool = true);
|
||||
void SetLogLevel(LogLevel_enum);
|
||||
void SetFileName(String);
|
||||
void SetFilePath(String);
|
||||
|
|
@ -53,8 +54,8 @@ public:
|
|||
String GetFilePath();
|
||||
LogLevel_enum GetLogLevel();
|
||||
bool GetNtpTimeSynced();
|
||||
void CheckMaxLogFileSize();
|
||||
|
||||
protected:
|
||||
String GetSystemTime();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#define _MCU_CFG_H_
|
||||
|
||||
/* ---------------- BASIC MCU CFG --------------*/
|
||||
#define SW_VERSION "1.0.2-rc3" ///< SW version
|
||||
#define SW_VERSION "1.0.3-rc1" ///< SW version
|
||||
#define SW_BUILD __DATE__ " " __TIME__ ///< build number
|
||||
#define CONSOLE_VERBOSE_DEBUG false ///< enable/disable verbose debug log level for console
|
||||
#define DEVICE_HOSTNAME "Prusa-ESP32cam" ///< device hostname
|
||||
|
|
@ -50,12 +50,13 @@
|
|||
#define TASK_STREAM_TELEMETRY 30000 ///< stream telemetry task interval [ms]
|
||||
#define TASK_WIFI_WATCHDOG 20000 ///< wifi watchdog task interval [ms]
|
||||
#define TASK_PHOTO_SEND 1000 ///< photo send task interval [ms]
|
||||
#define TASK_SDCARD_FILE_REMOVE 30000 ///< sd card file remove task interval [ms]
|
||||
|
||||
/* --------------- WEB SERVER CFG --------------*/
|
||||
#define WEB_SERVER_PORT 80 ///< WEB server port
|
||||
#define SERIAL_PORT_SPEED 115200 ///< baud rate
|
||||
#define WDG_TIMEOUT 40 ///< wdg timeout [second]
|
||||
#define PHOTO_FRAGMENT_SIZE 1024 ///< photo fragmentation size [bytes]
|
||||
#define PHOTO_FRAGMENT_SIZE 2048 ///< photo fragmentation size [bytes]
|
||||
#define LOOP_DELAY 100 ///< loop delay [ms]
|
||||
#define WIFI_CLIENT_WAIT_CON false ///< wait for connecting to WiFi network
|
||||
#define DYNMIC_JSON_SIZE 1024 ///< maximum size for dynamic json [bytes]
|
||||
|
|
@ -63,8 +64,8 @@
|
|||
|
||||
/* --------------- OTA UPDATE CFG --------------*/
|
||||
#define OTA_UPDATE_API_SERVER "api.github.com" ///< OTA update server URL
|
||||
#define OTA_UPDATE_API_URL "/repos/prusa3d/Prusa-Firmware-ESP32-Cam/releases/latest" ///< path to file with OTA update
|
||||
#define OTA_UPDATE_FW_FILE "ESP32_PrusaConnectCam.ino.bin" ///< OTA update firmware file name
|
||||
#define OTA_UPDATE_API_URL F("/repos/prusa3d/Prusa-Firmware-ESP32-Cam/releases/latest") ///< path to file with OTA update
|
||||
#define OTA_UPDATE_FW_FILE PSTR("ESP32_PrusaConnectCam.ino.bin") ///< OTA update firmware file name
|
||||
|
||||
/* ---------- RESET CFG CONFIGURATION ----------*/
|
||||
#define CFG_RESET_PIN 12 ///< GPIO 16 is for reset CFG to default
|
||||
|
|
@ -74,18 +75,19 @@
|
|||
/* ---------------- MicroSD Logs ----------------*/
|
||||
#define LOGS_FILE_NAME "SysLog.log" ///< syslog file name
|
||||
#define LOGS_FILE_PATH "/" ///< directory for log files
|
||||
#define LOGS_FILE_MAX_SIZE 1024 ///< maximum file size in the [kb]
|
||||
#define LOGS_FILE_MAX_SIZE 512 ///< maximum file size in the [kb]
|
||||
#define FILE_REMOVE_MAX_COUNT 5 ///< maximum count for remove files from sd card
|
||||
|
||||
/* ---------------- AP MODE CFG ----------------*/
|
||||
#define STA_AP_MODE_TIMEOUT 300000 ///< how long is AP enable after start, when is module in the STA mode [ms]
|
||||
#define SERVICE_WIFI_SSID_UID true ///< enable/disable added UID to service SSID name
|
||||
#define SERVICE_WIFI_SSID "ESP32_camera" ///< service WI-FI SSID name. Maximum length SERVICE_WIFI_SSID + UID = 32
|
||||
#define SERVICE_WIFI_PASS "12345678" ///< service WI-FI password
|
||||
#define SERVICE_WIFI_SSID F("ESP32_camera") ///< service WI-FI SSID name. Maximum length SERVICE_WIFI_SSID + UID = 32
|
||||
#define SERVICE_WIFI_PASS F("12345678") ///< service WI-FI password
|
||||
#define SERVICE_WIFI_CHANNEL 10 ///< service WI-FI channel
|
||||
#define SERVICE_LOCAL_IP "192.168.0.1" ///< service WI-FI module IP address
|
||||
#define SERVICE_LOCAL_GATEWAY "192.168.0.1" ///< service WI-FI module gateway
|
||||
#define SERVICE_LOCAL_MASK "255.255.255.0" ///< service WI-FI module mask
|
||||
#define SERVICE_LOCAL_DNS "192.168.0.1" ///< service WI-FI module DNS
|
||||
#define SERVICE_LOCAL_IP F("192.168.0.1") ///< service WI-FI module IP address
|
||||
#define SERVICE_LOCAL_GATEWAY F("192.168.0.1") ///< service WI-FI module gateway
|
||||
#define SERVICE_LOCAL_MASK F("255.255.255.0") ///< service WI-FI module mask
|
||||
#define SERVICE_LOCAL_DNS F("192.168.0.1") ///< service WI-FI module DNS
|
||||
|
||||
/* ----------------- IPv4 CFG -------------------*/
|
||||
#define IPV4_ADDR_MAX_LENGTH 15 ///< maximum length for IPv4 address
|
||||
|
|
@ -100,9 +102,14 @@
|
|||
#define NTP_DAYLIGHT_OFFSET_SEC 0 ///< daylight offset in seconds. 0 = no daylight saving time. 3600 = +1 hour
|
||||
|
||||
/* ------------------ EXIF CFG ------------------*/
|
||||
#define CAMERA_MAKE "OmniVision" ///< Camera make string
|
||||
#define CAMERA_MODEL "OV2640" ///< Camera model string
|
||||
#define CAMERA_SOFTWARE "Prusa ESP32-cam" ///< Camera software string
|
||||
#define CAMERA_MAKE "OmniVision" ///< Camera make string
|
||||
#define CAMERA_MODEL "OV2640" ///< Camera model string
|
||||
#define CAMERA_SOFTWARE "Prusa ESP32-cam" ///< Camera software string
|
||||
|
||||
/* ---------------- TIMELAPS CFG ----------------*/
|
||||
#define TIMELAPS_PHOTO_FOLDER "/timelaps" ///< folder for timelaps photos
|
||||
#define TIMELAPS_PHOTO_PREFIX "photo" ///< photo name for timelaps
|
||||
#define TIMELAPS_PHOTO_SUFFIX ".jpg" ///< photo file type for timelaps
|
||||
|
||||
/* ---------------- FACTORY CFG ----------------*/
|
||||
#define FACTORY_CFG_PHOTO_REFRESH_INTERVAL 30 ///< in the second
|
||||
|
|
@ -121,25 +128,26 @@
|
|||
#define FACTORY_CFG_BPC 1 ///< bad pixel detection
|
||||
#define FACTORY_CFG_WPC 1 ///< white pixel correction
|
||||
#define FACTORY_CFG_RAW_GAMA 1 ///< raw gama
|
||||
#define FACTORY_CFG_WEB_AUTH_USERNAME "admin" ///< user name for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||
#define FACTORY_CFG_WEB_AUTH_PASSWORD "admin" ///< password for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||
#define FACTORY_CFG_WEB_AUTH_USERNAME F("admin") ///< user name for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||
#define FACTORY_CFG_WEB_AUTH_PASSWORD F("admin") ///< password for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be true
|
||||
#define FACTORY_CFG_WEB_AUTH_ENABLE false ///< enable web auth for login to WEB interface. definition WEB_ENABLE_BASIC_AUTH must be
|
||||
#define FACTORY_CFG_CAMERA_FLASH_ENABLE false ///< enable camera flash functionality
|
||||
#define FACTORY_CFG_CAMERA_FLASH_TIME 200 ///< time for camera flash duration time [ms]
|
||||
#define FACTORY_CFG_MDNS_RECORD_HOST "prusa-esp32cam" ///< mdns record http://MDNS_RECORD_HOST.local
|
||||
#define FACTORY_CFG_MDNS_RECORD_HOST F("prusa-esp32cam") ///< mdns record http://MDNS_RECORD_HOST.local
|
||||
#define FACTORY_CFG_AEC2 0 ///< enable automatic exposition
|
||||
#define FACTORY_CFG_AE_LEVEL 0 ///< automatic exposition level
|
||||
#define FACTORY_CFG_AEC_VALUE 300 ///< automatic exposition time
|
||||
#define FACTORY_CFG_GAIN_CTRL 1 ///< enable automatic gain
|
||||
#define FACTORY_CFG_AGC_GAIN 0 ///< automatic gain controll gain
|
||||
#define FACTORY_CFG_HOSTNAME "connect.prusa3d.com" ///< hostname for Prusa Connect
|
||||
#define FACTORY_CFG_HOSTNAME F("connect.prusa3d.com") ///< hostname for Prusa Connect
|
||||
#define FACTORY_CFG_ENABLE_SERVICE_AP 1 ///< enable service AP mode
|
||||
#define FACTORY_CFG_NETWORK_IP_METHOD 0 ///< 0 - DHCP, 1 - Static IP
|
||||
#define FACTORY_CFG_NETWORK_STATIC_IP "255.255.255.255" ///< Static IP address
|
||||
#define FACTORY_CFG_NETWORK_STATIC_MASK "255.255.255.255" ///< Static Mask
|
||||
#define FACTORY_CFG_NETWORK_STATIC_GATEWAY "255.255.255.255" ///< Static Gateway
|
||||
#define FACTORY_CFG_NETWORK_STATIC_DNS "255.255.255.255" ///< Static DNS
|
||||
#define FACTORY_CFG_NETWORK_STATIC_IP F("255.255.255.255") ///< Static IP address
|
||||
#define FACTORY_CFG_NETWORK_STATIC_MASK F("255.255.255.255") ///< Static Mask
|
||||
#define FACTORY_CFG_NETWORK_STATIC_GATEWAY F("255.255.255.255") ///< Static Gateway
|
||||
#define FACTORY_CFG_NETWORK_STATIC_DNS F("255.255.255.255") ///< Static DNS
|
||||
#define FACTORY_CFG_IMAGE_EXIF_ROTATION 1 ///< Image rotation 1 - 0°, 6 - 90°, 3 - 180°, 8 - 270°
|
||||
#define FACTORY_CFG_TIMELAPS_ENABLE 0 ///< enable timelaps functionality
|
||||
|
||||
/* ---------------- CFG FLAGS ------------------*/
|
||||
#define CFG_WIFI_SETTINGS_SAVED 0x0A ///< flag saved config
|
||||
|
|
@ -275,6 +283,9 @@
|
|||
#define EEPROM_ADDR_IMAGE_ROTATION_START (EEPROM_ADDR_NETWORK_STATIC_DNS_START + EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH)
|
||||
#define EEPROM_ADDR_IMAGE_ROTATION_LENGTH 1
|
||||
|
||||
#define EEPROM_ADDR_TIMELAPS_ENABLE_START (EEPROM_ADDR_IMAGE_ROTATION_START + EEPROM_ADDR_IMAGE_ROTATION_LENGTH)
|
||||
#define EEPROM_ADDR_TIMELAPS_ENABLE_LENGTH 1
|
||||
|
||||
#define EEPROM_SIZE (EEPROM_ADDR_REFRESH_INTERVAL_LENGTH + EEPROM_ADDR_FINGERPRINT_LENGTH + EEPROM_ADDR_TOKEN_LENGTH + \
|
||||
EEPROM_ADDR_FRAMESIZE_LENGTH + EEPROM_ADDR_BRIGHTNESS_LENGTH + EEPROM_ADDR_CONTRAST_LENGTH + \
|
||||
EEPROM_ADDR_SATURATION_LENGTH + EEPROM_ADDR_HMIRROR_LENGTH + EEPROM_ADDR_VFLIP_LENGTH + \
|
||||
|
|
@ -289,7 +300,7 @@
|
|||
EEPROM_ADDR_AEC_VALUE_LENGTH + EEPROM_ADDR_GAIN_CTRL_LENGTH + EEPROM_ADDR_AGC_GAIN_LENGTH + EEPROM_ADDR_LOG_LEVEL_LENGTH + \
|
||||
EEPROM_ADDR_HOSTNAME_LENGTH + EEPROM_ADDR_SERVICE_AP_ENABLE_LENGTH + EEPROM_ADDR_NETWORK_IP_METHOD_LENGTH +\
|
||||
EEPROM_ADDR_NETWORK_STATIC_IP_LENGTH + EEPROM_ADDR_NETWORK_STATIC_MASK_LENGTH + EEPROM_ADDR_NETWORK_STATIC_GATEWAY_LENGTH + \
|
||||
EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH + EEPROM_ADDR_IMAGE_ROTATION_LENGTH) ///< how many bits do we need for eeprom memory
|
||||
EEPROM_ADDR_NETWORK_STATIC_DNS_LENGTH + EEPROM_ADDR_IMAGE_ROTATION_LENGTH + EEPROM_ADDR_TIMELAPS_ENABLE_LENGTH) ///< how many bits do we need for eeprom memory
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
MicroSd::MicroSd() {
|
||||
CardDetected = false;
|
||||
CardSize = 0;
|
||||
DetectAfterBoot = false;
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ void MicroSd::InitSdCard() {
|
|||
if (!SD_MMC.begin("/sdcard", true)) {
|
||||
Serial.println(F("SD Card Mount Failed"));
|
||||
CardDetected = false;
|
||||
CardSize = 0;
|
||||
CardSizeMB = 0;
|
||||
//DetectAfterBoot = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -60,7 +59,7 @@ void MicroSd::InitSdCard() {
|
|||
if (cardType == CARD_NONE) {
|
||||
Serial.println(F("No SD_MMC card attached"));
|
||||
CardDetected = false;
|
||||
CardSize = 0;
|
||||
CardSizeMB = 0;
|
||||
//DetectAfterBoot = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -77,11 +76,11 @@ void MicroSd::InitSdCard() {
|
|||
Serial.print(F("UNKNOWN"));
|
||||
}
|
||||
|
||||
/* calculation card size */
|
||||
CardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf(", Card Size: %d MB\n", CardSize);
|
||||
CardDetected = true;
|
||||
DetectAfterBoot = true;
|
||||
|
||||
/* calculation card size */
|
||||
CheckCardUsedStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,6 +123,27 @@ void MicroSd::ListDir(fs::FS &fs, String DirName, uint8_t levels) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Check directory on the micro SD card
|
||||
@param fs::FS - card
|
||||
@param String - dir name
|
||||
@return bool - status
|
||||
*/
|
||||
bool MicroSd::CheckDir(fs::FS &fs, String path) {
|
||||
bool status = false;
|
||||
if (true == CardDetected) {
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.printf("Checking Dir: %s... ", path.c_str());
|
||||
#endif
|
||||
|
||||
if (fs.exists(path.c_str())) {
|
||||
status = true;
|
||||
}
|
||||
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief List directory on the micro SD card
|
||||
@param fs::FS - card
|
||||
|
|
@ -389,6 +409,140 @@ uint16_t MicroSd::FileCount(fs::FS &fs, String DirName, String FileName) {
|
|||
return FileCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Remove files in directory
|
||||
@param fs::FS - card
|
||||
@param String - dir name
|
||||
@param int - max files
|
||||
@return bool - status
|
||||
*/
|
||||
bool MicroSd::RemoveFilesInDir(fs::FS &fs, String path, int maxFiles) {
|
||||
bool ret = false;
|
||||
File dir = fs.open(path.c_str());
|
||||
if (!dir) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fileCount = 0;
|
||||
File file = dir.openNextFile();
|
||||
while (file) {
|
||||
ret = true;
|
||||
String fileName = path + "/" + file.name();
|
||||
fs.remove(fileName.c_str());
|
||||
Serial.printf("Removing file: %s\n", fileName.c_str());
|
||||
fileCount++;
|
||||
if (fileCount >= maxFiles) {
|
||||
break;
|
||||
}
|
||||
file = dir.openNextFile();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int MicroSd::CountFilesInDir(fs::FS &fs, String path) {
|
||||
uint16_t file_count = FileCount(fs, path, "");
|
||||
return file_count;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Check card used status
|
||||
@param none
|
||||
@return bool - status
|
||||
*/
|
||||
bool MicroSd::CheckCardUsedStatus() {
|
||||
|
||||
CardSizeMB = SD_MMC.cardSize() / (1024 * 1024);
|
||||
CardTotalMB = SD_MMC.totalBytes() / (1024 * 1024);
|
||||
CardUsedMB = SD_MMC.usedBytes() / (1024 * 1024);
|
||||
CardFreeMB = CardSizeMB - CardUsedMB;
|
||||
FreeSpacePercent = (CardFreeMB * 100) / CardSizeMB;
|
||||
UsedSpacePercent = 100 - FreeSpacePercent;
|
||||
|
||||
Serial.printf("Card size: %d MB, Total: %d MB, Used: %d MB, Free: %d GB, Free: %d %% \n", CardSizeMB, CardTotalMB, CardUsedMB, CardFreeMB, FreeSpacePercent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Write picture to the SD card
|
||||
@param fs::FS - card
|
||||
@param String - file name
|
||||
@return String - data
|
||||
*/
|
||||
bool MicroSd::WritePicture(String i_PhotoName, uint8_t *i_PhotoData, size_t i_PhotoLen) {
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.println(f("WritePicture"));
|
||||
#endif
|
||||
bool ret_stat = false;
|
||||
|
||||
File file = SD_MMC.open(i_PhotoName, FILE_WRITE);
|
||||
|
||||
if (file) {
|
||||
size_t ret = 0;
|
||||
|
||||
ret = file.write(i_PhotoData, i_PhotoLen);
|
||||
if (ret != i_PhotoLen) {
|
||||
Serial.println(F("Failed. Error while writing to file"));
|
||||
} else {
|
||||
Serial.printf("Saved as %s\n", i_PhotoName.c_str());
|
||||
ret_stat = true;
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
Serial.printf("Failed. Could not open file: %s\n", i_PhotoName.c_str());
|
||||
}
|
||||
|
||||
return ret_stat;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Write picture to the SD card with EXIF data
|
||||
@param fs::FS - card
|
||||
@param String - file name
|
||||
@param uint8_t - data
|
||||
@param size_t - data length
|
||||
@param const uint8_t - EXIF data
|
||||
@param size_t - EXIF data length
|
||||
@return bool - status
|
||||
*/
|
||||
bool MicroSd::WritePicture(String i_PhotoName, uint8_t *i_PhotoData, size_t i_PhotoLen, const uint8_t *i_PtohoExif, size_t i_PhotoExifLen) {
|
||||
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.println(F("WritePicture EXIF"));
|
||||
#endif
|
||||
bool ret_stat = false;
|
||||
|
||||
File file = SD_MMC.open(i_PhotoName, FILE_WRITE);
|
||||
|
||||
if (file) {
|
||||
size_t ret = 0;
|
||||
|
||||
ret = file.write(i_PtohoExif, i_PhotoExifLen);
|
||||
ret += file.write(i_PhotoData, i_PhotoLen);
|
||||
if (ret != (i_PhotoLen + i_PhotoExifLen)) {
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.println(F("Failed. Error while writing to file"));
|
||||
#endif
|
||||
ret_stat = false;
|
||||
} else {
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.printf("Saved as %s\n", i_PhotoName.c_str());
|
||||
#endif
|
||||
ret_stat = true;
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
#if (true == CONSOLE_VERBOSE_DEBUG)
|
||||
Serial.printf("Failed. Could not open file: %s\n", i_PhotoName.c_str());
|
||||
#endif
|
||||
ret_stat = false;
|
||||
}
|
||||
|
||||
return ret_stat;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get card detected status
|
||||
@param none
|
||||
|
|
@ -403,8 +557,8 @@ bool MicroSd::GetCardDetectedStatus() {
|
|||
@param none
|
||||
@return uint16_t - size
|
||||
*/
|
||||
uint16_t MicroSd::GetCardSize() {
|
||||
return CardSize;
|
||||
uint16_t MicroSd::GetCardSizeMB() {
|
||||
return CardSizeMB;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -416,4 +570,49 @@ bool MicroSd::GetCardDetectAfterBoot() {
|
|||
return DetectAfterBoot;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get card total MB
|
||||
@param none
|
||||
@return uint16_t - size
|
||||
*/
|
||||
uint16_t MicroSd::GetCardTotalMB() {
|
||||
return CardTotalMB;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get card used MB
|
||||
@param none
|
||||
@return uint16_t - size
|
||||
*/
|
||||
uint16_t MicroSd::GetCardUsedMB() {
|
||||
return CardUsedMB;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get card free MB
|
||||
@param none
|
||||
@return uint16_t - size
|
||||
*/
|
||||
uint16_t MicroSd::GetCardFreeMB() {
|
||||
return CardFreeMB;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get free space percent
|
||||
@param none
|
||||
@return uint8_t - percent
|
||||
*/
|
||||
uint8_t MicroSd::GetFreeSpacePercent() {
|
||||
return FreeSpacePercent;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Get used space percent
|
||||
@param none
|
||||
@return uint8_t - percent
|
||||
*/
|
||||
uint8_t MicroSd::GetUsedSpacePercent() {
|
||||
return UsedSpacePercent;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
@ -33,9 +33,14 @@
|
|||
|
||||
class MicroSd {
|
||||
private:
|
||||
bool CardDetected; ///< Card detected status
|
||||
uint16_t CardSize; ///< Card size
|
||||
bool DetectAfterBoot; ///< Card detect after boot
|
||||
bool CardDetected; ///< Card detected status
|
||||
bool DetectAfterBoot; ///< Card detect after boot
|
||||
uint32_t CardSizeMB; ///< Card size
|
||||
uint32_t CardTotalMB;
|
||||
uint32_t CardUsedMB;
|
||||
uint32_t CardFreeMB;
|
||||
uint8_t FreeSpacePercent;
|
||||
uint8_t UsedSpacePercent;
|
||||
|
||||
public:
|
||||
MicroSd();
|
||||
|
|
@ -45,6 +50,7 @@ public:
|
|||
void ReinitCard();
|
||||
|
||||
void ListDir(fs::FS &, String, uint8_t);
|
||||
bool CheckDir(fs::FS &, String);
|
||||
bool CreateDir(fs::FS &, String);
|
||||
bool RemoveDir(fs::FS &, String);
|
||||
void ReadFileConsole(fs::FS &, String);
|
||||
|
|
@ -54,10 +60,23 @@ public:
|
|||
bool DeleteFile(fs::FS &, String);
|
||||
uint32_t GetFileSize(fs::FS &, String);
|
||||
uint16_t FileCount(fs::FS &, String, String);
|
||||
bool RemoveFilesInDir(fs::FS &, String, int );
|
||||
int CountFilesInDir(fs::FS &, String );
|
||||
|
||||
bool WritePicture(String, uint8_t *, size_t);
|
||||
bool WritePicture(String, uint8_t *, size_t, const uint8_t *, size_t);
|
||||
|
||||
bool CheckCardUsedStatus();
|
||||
|
||||
bool GetCardDetectedStatus();
|
||||
uint16_t GetCardSize();
|
||||
bool GetCardDetectAfterBoot();
|
||||
uint16_t GetCardSizeMB();
|
||||
uint16_t GetCardTotalMB();
|
||||
uint16_t GetCardUsedMB();
|
||||
uint16_t GetCardFreeMB();
|
||||
uint32_t GetFreeSpaceMB();
|
||||
uint8_t GetFreeSpacePercent();
|
||||
uint8_t GetUsedSpacePercent();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ void Server_InitWebServer() {
|
|||
request->send_P(404, "text/plain", "Photo not found!");
|
||||
return;
|
||||
}
|
||||
SystemCamera.SetPhotoSending(true);
|
||||
|
||||
SystemLog.AddEvent(LogLevel_Verbose, "Photo size: " + String(SystemCamera.GetPhotoFb()->len) + " bytes");
|
||||
|
||||
|
|
@ -62,6 +63,8 @@ void Server_InitWebServer() {
|
|||
SystemLog.AddEvent(LogLevel_Verbose, F("Send photo without EXIF data"));
|
||||
request->send_P(200, "image/jpg", SystemCamera.GetPhotoFb()->buf, SystemCamera.GetPhotoFb()->len);
|
||||
}
|
||||
|
||||
SystemCamera.SetPhotoSending(false);
|
||||
});
|
||||
|
||||
/* route to jquery */
|
||||
|
|
@ -434,6 +437,17 @@ void Server_InitWebServer_Actions() {
|
|||
delay(100); /* wait for sending data */
|
||||
ESP.restart();
|
||||
});
|
||||
|
||||
/* route for change LED status */
|
||||
server.on("/action_sderase", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
SystemLog.AddEvent(LogLevel_Verbose, F("WEB server: /action_sderase remove files from SD card"));
|
||||
if (Server_CheckBasicAuth(request) == false)
|
||||
return;
|
||||
|
||||
StartRemoveSdCard = 1;
|
||||
|
||||
request->send_P(200, F("text/plain"), "Starting remove files from SD card");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -680,6 +694,12 @@ void Server_InitWebServer_Sets() {
|
|||
response = true;
|
||||
}
|
||||
|
||||
if (request->hasParam("timelaps_enable")) {
|
||||
SystemLog.AddEvent(LogLevel_Verbose, F("Set timelaps enable"));
|
||||
Connect.SetTimeLapsPhotoSaveStatus(Server_TransfeStringToBool(request->getParam("timelaps_enable")->value()));
|
||||
response = true;
|
||||
}
|
||||
|
||||
if (true == response) {
|
||||
request->send_P(200, F("text/html"), MSG_SAVE_OK);
|
||||
}
|
||||
|
|
@ -1004,7 +1024,7 @@ void Server_resume() {
|
|||
* @param const char* - content type
|
||||
* @param const char* - data
|
||||
*/
|
||||
void Server_handleCacheRequest(AsyncWebServerRequest* request, const char* contentType, const char* data) {
|
||||
void Server_handleCacheRequest(AsyncWebServerRequest* request, const char *contentType, const char *data) {
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, contentType, data);
|
||||
response->addHeader("Cache-Control", "public, max-age=" + String(WEB_CACHE_INTERVAL));
|
||||
request->send(response);
|
||||
|
|
@ -1019,14 +1039,14 @@ void Server_handleNotFound(AsyncWebServerRequest* request) {
|
|||
String message = "URL not Found\n\n";
|
||||
|
||||
message += "URI: " + request->url() + "\nMethod: ";
|
||||
message += (request->method() == HTTP_GET) ? "GET" : "POST";
|
||||
message += (request->method() == HTTP_GET) ? F("GET") : F("POST");
|
||||
message += "\nArguments: " + String(request->args()) + "\n";
|
||||
|
||||
for (uint8_t i = 0; i < request->args(); i++) {
|
||||
message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
|
||||
}
|
||||
|
||||
request->send(404, "text/plain", message);
|
||||
request->send(404, F("text/plain"), message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1048,23 +1068,23 @@ String Server_GetJsonData() {
|
|||
doc_json["brightness"] = String(SystemCamera.GetBrightness());
|
||||
doc_json["contrast"] = String(SystemCamera.GetContrast());
|
||||
doc_json["saturation"] = String(SystemCamera.GetSaturation());
|
||||
doc_json["hmirror"] = (SystemCamera.GetHMirror() == true) ? "true" : "";
|
||||
doc_json["vflip"] = (SystemCamera.GetVFlip() == true) ? "true" : "";
|
||||
doc_json["lensc"] = (SystemCamera.GetLensC() == true) ? "true" : "";
|
||||
doc_json["exposure_ctrl"] = (SystemCamera.GetExposureCtrl() == true) ? "true" : "";
|
||||
doc_json["awb"] = (SystemCamera.GetAwb() == true) ? "true" : "";
|
||||
doc_json["awb_gain"] = (SystemCamera.GetAwbGain() == true) ? "true" : "";
|
||||
doc_json["hmirror"] = Server_TranslateBoolToString(SystemCamera.GetHMirror());
|
||||
doc_json["vflip"] = Server_TranslateBoolToString(SystemCamera.GetVFlip());
|
||||
doc_json["lensc"] = Server_TranslateBoolToString(SystemCamera.GetLensC());
|
||||
doc_json["exposure_ctrl"] = Server_TranslateBoolToString(SystemCamera.GetExposureCtrl());
|
||||
doc_json["awb"] = Server_TranslateBoolToString(SystemCamera.GetAwb());
|
||||
doc_json["awb_gain"] = Server_TranslateBoolToString(SystemCamera.GetAwbGain());
|
||||
doc_json["wb_mode"] = String(SystemCamera.GetAwbMode());
|
||||
doc_json["bpc"] = (SystemCamera.GetBpc() == true) ? "true" : "";
|
||||
doc_json["wpc"] = (SystemCamera.GetWpc() == true) ? "true" : "";
|
||||
doc_json["raw_gama"] = (SystemCamera.GetRawGama() == true) ? "true" : "";
|
||||
doc_json["aec2"] = (SystemCamera.GetAec2() == true) ? "true" : "";
|
||||
doc_json["bpc"] = Server_TranslateBoolToString(SystemCamera.GetBpc());
|
||||
doc_json["wpc"] = Server_TranslateBoolToString(SystemCamera.GetWpc());
|
||||
doc_json["raw_gama"] = Server_TranslateBoolToString(SystemCamera.GetRawGama());
|
||||
doc_json["aec2"] = Server_TranslateBoolToString(SystemCamera.GetAec2());
|
||||
doc_json["ae_level"] = SystemCamera.GetAeLevel();
|
||||
doc_json["aec_value"] = SystemCamera.GetAecValue();
|
||||
doc_json["gain_ctrl"] = (SystemCamera.GetGainCtrl() == true) ? "true" : "";
|
||||
doc_json["gain_ctrl"] = Server_TranslateBoolToString(SystemCamera.GetGainCtrl());
|
||||
doc_json["agc_gain"] = SystemCamera.GetAgcGaint();
|
||||
doc_json["led"] = (SystemCamera.GetFlashStatus() == true) ? "true" : "";
|
||||
doc_json["flash"] = (SystemCamera.GetCameraFlashEnable() == true) ? "true" : "";
|
||||
doc_json["led"] = Server_TranslateBoolToString(SystemCamera.GetFlashStatus());
|
||||
doc_json["flash"] = Server_TranslateBoolToString(SystemCamera.GetCameraFlashEnable());
|
||||
doc_json["flash_time"] = SystemCamera.GetCameraFlashTime();
|
||||
doc_json["ssid"] = SystemWifiMngt.GetStaSsid();
|
||||
doc_json["bssid"] = SystemWifiMngt.GetStaBssid();
|
||||
|
|
@ -1075,8 +1095,8 @@ String Server_GetJsonData() {
|
|||
doc_json["wifi_mode"] = SystemWifiMngt.GetWiFiMode();
|
||||
doc_json["mdns"] = SystemWifiMngt.GetMdns();
|
||||
doc_json["service_ap_ssid"] = SystemWifiMngt.GetServiceApSsid();
|
||||
doc_json["serviceap"] = (SystemWifiMngt.GetEnableServiceAp() == true) ? "true" : "";
|
||||
doc_json["auth"] = (WebBasicAuth.EnableAuth == true) ? "true" : "";
|
||||
doc_json["serviceap"] = Server_TranslateBoolToString(SystemWifiMngt.GetEnableServiceAp());
|
||||
doc_json["auth"] = Server_TranslateBoolToString(WebBasicAuth.EnableAuth);
|
||||
doc_json["auth_username"] = WebBasicAuth.UserName;
|
||||
doc_json["last_upload_status"] = Connect.GetBackendReceivedStatus();
|
||||
doc_json["wifi_network_status"] = SystemWifiMngt.GetStaStatus();
|
||||
|
|
@ -1090,6 +1110,11 @@ String Server_GetJsonData() {
|
|||
doc_json["net_gw"] = SystemWifiMngt.GetNetStaticGateway();
|
||||
doc_json["net_dns"] = SystemWifiMngt.GetNetStaticDns();
|
||||
doc_json["image_rotation"] = SystemCamera.GetCameraImageRotation();
|
||||
doc_json["timelaps"] = Server_TranslateBoolToString(Connect.GetTimeLapsPhotoSaveStatus());
|
||||
doc_json["sd_status"] = (SystemLog.GetCardDetectedStatus() == true) ? F("Card detected") : F("No card detected");
|
||||
doc_json["sd_total"] = SystemLog.GetCardSizeMB();
|
||||
doc_json["sd_free_p"] = SystemLog.GetFreeSpacePercent();
|
||||
doc_json["sd_used_p"] = SystemLog.GetUsedSpacePercent();
|
||||
doc_json["sw_build"] = SW_BUILD;
|
||||
doc_json["sw_ver"] = SW_VERSION;
|
||||
doc_json["sw_new_ver"] = FirmwareUpdate.NewVersionFw;
|
||||
|
|
@ -1185,4 +1210,15 @@ bool Server_TransfeStringToBool(String data) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
String Server_TranslateBoolToString(bool i_data) {
|
||||
String ret = "";
|
||||
if (true == i_data) {
|
||||
ret = "true";
|
||||
} else {
|
||||
ret = "";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ void Server_streamJpg(AsyncWebServerRequest *);
|
|||
void Server_GetModuleUptime(String &);
|
||||
bool Server_TransfeStringToBool(String);
|
||||
|
||||
String Server_TranslateBoolToString(bool);
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
|
|
|||
|
|
@ -117,14 +117,14 @@ void System_CheckNewVersion() {
|
|||
WiFiClientSecure client;
|
||||
client.setCACert(root_CAs_ota);
|
||||
//client.setInsecure();
|
||||
FirmwareUpdate.CheckNewVersionFwStatus = "N/A";
|
||||
FirmwareUpdate.NewVersionFw = "Unknown";
|
||||
FirmwareUpdate.CheckNewVersionFwStatus = F("N/A");
|
||||
FirmwareUpdate.NewVersionFw = F("Unknown");
|
||||
FirmwareUpdate.OtaUpdateFwUrl = "";
|
||||
FirmwareUpdate.OtaUpdateFwAvailable = false;
|
||||
|
||||
/* connect to server and get json */
|
||||
if (!client.connect("api.github.com", 443)) {
|
||||
FirmwareUpdate.CheckNewVersionFwStatus = "Failed connect to OTA server!";
|
||||
if (!client.connect(OTA_UPDATE_API_SERVER, 443)) {
|
||||
FirmwareUpdate.CheckNewVersionFwStatus = F("Failed connect to OTA server!");
|
||||
SystemLog.AddEvent(LogLevel_Info, FirmwareUpdate.CheckNewVersionFwStatus);
|
||||
|
||||
} else {
|
||||
|
|
@ -181,7 +181,7 @@ void System_CheckNewVersion() {
|
|||
SystemLog.AddEvent(LogLevel_Info, "Assets[" + String(i) + "]: " + String(name));
|
||||
|
||||
/* get FW file and URL */
|
||||
if (strcmp(name, OTA_UPDATE_FW_FILE) == 0) {
|
||||
if (strcmp_P(name, OTA_UPDATE_FW_FILE) == 0) {
|
||||
/* get download URL */
|
||||
const char* download_url = asset["browser_download_url"];
|
||||
FirmwareUpdate.OtaUpdateFwUrl = download_url;
|
||||
|
|
@ -544,6 +544,19 @@ void System_TaskSdCardCheck(void *pvParameters) {
|
|||
SystemLog.ReinitCard();
|
||||
SystemLog.AddEvent(LogLevel_Warning, F("Reinit micro SD card done!"));
|
||||
}
|
||||
|
||||
/* check card free space */
|
||||
if (true == SystemLog.GetCardDetectedStatus()) {
|
||||
SystemLog.AddEvent(LogLevel_Verbose, "Check card free space");
|
||||
SystemLog.CheckCardUsedStatus();
|
||||
}
|
||||
|
||||
/* check maximum log file size */
|
||||
if (true == SystemLog.GetCardDetectedStatus()) {
|
||||
SystemLog.AddEvent(LogLevel_Verbose, "Check maximum log file size");
|
||||
SystemLog.CheckMaxLogFileSize();
|
||||
}
|
||||
|
||||
SystemLog.AddEvent(LogLevel_Verbose, "MicroSdCard task. Stack free size: " + String(uxTaskGetStackHighWaterMark(NULL)) + " bytes");
|
||||
|
||||
/* reset wdg */
|
||||
|
|
@ -649,4 +662,44 @@ void System_TaskWiFiWatchdog(void *pvParameters) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for micro SD card remove files task
|
||||
*
|
||||
* @param void *pvParameters
|
||||
* @return none
|
||||
*/
|
||||
void System_TaskSdCardRemove(void *pvParameters) {
|
||||
SystemLog.AddEvent(LogLevel_Info, "TaskSdCardRemove. core: " + String(xPortGetCoreID()));
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
SdCardRemoveTime = TASK_SDCARD_FILE_REMOVE;
|
||||
|
||||
while (1) {
|
||||
esp_task_wdt_reset();
|
||||
if (0 != StartRemoveSdCard) {
|
||||
if (1 == StartRemoveSdCard) {
|
||||
SdCardRemoveTime = 5000;
|
||||
SystemLog.AddEvent(LogLevel_Info, "Start remove timelaps photo");
|
||||
uint16_t file_count = SystemLog.CountFilesInDir(SD_MMC, TIMELAPS_PHOTO_FOLDER);
|
||||
SystemLog.AddEvent(LogLevel_Info, "Files in dir: " + String(file_count));
|
||||
esp_task_wdt_reset();
|
||||
StartRemoveSdCard = 2;
|
||||
}
|
||||
|
||||
if ( false == SystemLog.RemoveFilesInDir(SD_MMC, TIMELAPS_PHOTO_FOLDER, FILE_REMOVE_MAX_COUNT)) {
|
||||
SystemLog.AddEvent(LogLevel_Info, "Remove files in dir done");
|
||||
StartRemoveSdCard = 0;
|
||||
SdCardRemoveTime = TASK_SDCARD_FILE_REMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
SystemLog.AddEvent(LogLevel_Verbose, "MicroSdCard task. Stack free size: " + String(uxTaskGetStackHighWaterMark(NULL)) + " bytes");
|
||||
|
||||
/* reset wdg */
|
||||
esp_task_wdt_reset();
|
||||
|
||||
/* next start task */
|
||||
vTaskDelayUntil(&xLastWakeTime, SdCardRemoveTime / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
@ -33,10 +33,10 @@
|
|||
#include "serial_cfg.h"
|
||||
#include "sys_led.h"
|
||||
|
||||
#define SYSTEM_MSG_UPDATE_DONE "FW update successfully done! Please reboot the MCU."
|
||||
#define SYSTEM_MSG_UPDATE_FAIL "FW update failed! Please reboot MCU, and try again."
|
||||
#define SYSTEM_MSG_UPDATE_PROCESS "FW update in progress"
|
||||
#define SYSTEM_MSG_UPDATE_NO_FW "No new FW version available!"
|
||||
#define SYSTEM_MSG_UPDATE_DONE F("FW update successfully done! Please reboot the MCU.")
|
||||
#define SYSTEM_MSG_UPDATE_FAIL F("FW update failed! Please reboot MCU, and try again.")
|
||||
#define SYSTEM_MSG_UPDATE_PROCESS F("FW update in progress")
|
||||
#define SYSTEM_MSG_UPDATE_NO_FW F("No new FW version available!")
|
||||
|
||||
void System_Init();
|
||||
void System_LoadCfg();
|
||||
|
|
@ -63,6 +63,7 @@ void System_TaskSerialCfg(void *);
|
|||
void System_TaskStreamTelemetry(void *);
|
||||
void System_TaskSysLed(void *);
|
||||
void System_TaskWiFiWatchdog(void *);
|
||||
void System_TaskSdCardRemove(void *);
|
||||
|
||||
#endif
|
||||
/* EOF */
|
||||
|
|
@ -22,5 +22,9 @@ TaskHandle_t Task_SerialCfg;
|
|||
TaskHandle_t Task_StreamTelemetry;
|
||||
TaskHandle_t Task_SysLed;
|
||||
TaskHandle_t Task_WiFiWatchdog;
|
||||
//TaskHandle_t Task_SdCardFileRemove;
|
||||
|
||||
uint8_t StartRemoveSdCard = 0;
|
||||
uint32_t SdCardRemoveTime = 0;
|
||||
|
||||
/* EOF */
|
||||
|
|
@ -48,6 +48,10 @@ extern TaskHandle_t Task_SerialCfg; ///< task handle for serial
|
|||
extern TaskHandle_t Task_StreamTelemetry; ///< task handle for stream telemetry
|
||||
extern TaskHandle_t Task_SysLed; ///< task handle for system led
|
||||
extern TaskHandle_t Task_WiFiWatchdog; ///< task handle for wifi watchdog
|
||||
//extern TaskHandle_t Task_SdCardFileRemove; ///< task handle for remove file from sd card
|
||||
|
||||
extern uint8_t StartRemoveSdCard;
|
||||
extern uint32_t SdCardRemoveTime;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -74,14 +74,14 @@ void WiFiMngt::Init() {
|
|||
ServiceMode = true;
|
||||
WiFi.softAPConfig(Service_LocalIp, Service_Gateway, Service_Subnet);
|
||||
WiFi.softAP(SericeApSsid.c_str(), SERVICE_WIFI_PASS, SERVICE_WIFI_CHANNEL);
|
||||
WiFiMode = "AP + Client";
|
||||
WiFiMode = F("AP + Client");
|
||||
log->AddEvent(LogLevel_Info, "Service IP Address: http://" + WiFi.softAPIP().toString());
|
||||
|
||||
} else {
|
||||
log->AddEvent(LogLevel_Warning, F("Service AP mode disabled!"));
|
||||
WiFi.mode(WIFI_STA);
|
||||
ServiceMode = false;
|
||||
WiFiMode = "Client";
|
||||
WiFiMode = F("Client");
|
||||
}
|
||||
|
||||
/* Set STA IP method. Static or DHCP */
|
||||
|
|
@ -150,7 +150,7 @@ void WiFiMngt::WifiManagement() {
|
|||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
WiFiStaConnect();
|
||||
//WiFi.begin(WifiSsid, WifiPassword);
|
||||
WiFiMode = "Client";
|
||||
WiFiMode = F("Client");
|
||||
|
||||
#if (WIFI_CLIENT_WAIT_CON == true)
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
$("#content").load(page);
|
||||
setActive(this);
|
||||
});
|
||||
|
||||
$("#content").load("page_config.html", function() {
|
||||
var defaultLink = document.querySelector('a[href="page_config.html"]');
|
||||
setActive(defaultLink);
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav>
|
||||
<img src="esp32_cam.svg" id=logo alt="Logo image" style="margin-left: 10px;" />
|
||||
|
|
@ -36,7 +34,6 @@
|
|||
</ul>
|
||||
</nav>
|
||||
<hr>
|
||||
|
||||
<section class="container">
|
||||
<div class="container_left-half">
|
||||
<article>
|
||||
|
|
@ -52,23 +49,20 @@
|
|||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<br>
|
||||
<cfg>
|
||||
<cfg_bar>
|
||||
<div id="cfg">
|
||||
<div id="cfg_bar">
|
||||
<div id="links">
|
||||
<li ><a href="page_config.html">Camera configuration</a></li>
|
||||
<li ><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
||||
<li ><a href="page_auth.html">Authentication</a></li>
|
||||
<li ><a href="page_system.html">System</a></li>
|
||||
<li><a href="page_config.html">Camera configuration</a></li>
|
||||
<li><a href="page_wifi.html">Wi-Fi configuration</a></li>
|
||||
<li><a href="page_auth.html">Authentication</a></li>
|
||||
<li><a href="page_system.html">System</a></li>
|
||||
</div>
|
||||
</cfg_bar>
|
||||
</cfg>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div id="content">
|
||||
</div>
|
||||
|
||||
<br><br><br><br>
|
||||
<table id=botton><tr>
|
||||
<td><p class=p2>Prusa Connect ESP32 cam</p> </td>
|
||||
|
|
@ -77,7 +71,6 @@
|
|||
<td><a href="https://github.com/Prusa-Development/Prusa-Firmware-ESP32-Cam/" id="github-link"><svg height="25"><image href="github-icon.svg"></svg></a></td>
|
||||
</tr></table>
|
||||
</body>
|
||||
|
||||
<script src="scripts.js"></script>
|
||||
<script>
|
||||
sliderCheck();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<style>@import url("styles.css");</style>
|
||||
<script src="jquery-3.7.0.min.js"></script>
|
||||
|
||||
<body>
|
||||
<center>
|
||||
<table>
|
||||
|
|
@ -13,7 +12,6 @@
|
|||
</table>
|
||||
</center>
|
||||
</body>
|
||||
|
||||
<script src="scripts.js"></script>
|
||||
<script>
|
||||
get_data("auth");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<script src="jquery-3.7.0.min.js"></script>
|
||||
<body>
|
||||
<center><table id="data">
|
||||
<tr><td class="ps3">Basic image settings</td><td></td></tr>
|
||||
<tr><td class="ps3">Basic settings</td><td></td></tr>
|
||||
<tr><td class="pc1">Connect Token</td><td ><input type="text" name="token" id=tokenid > <button class="btn_save" onclick="changeValue(encodeURIComponent(document.getElementById('tokenid').value), 'set_token?token=', 'config')">Save</button></td></tr>
|
||||
<tr><td class="pc1">Fingerprint</td><td class=pc2 id="fingerprint"></td></tr>
|
||||
<tr><td class="pc1">Trigger Interval [s]</td><td ><input type="text" name="refresh" id=refreshid > <button class="btn_save" onclick="changeValue(document.getElementById('refreshid').value, 'set_int?refresh=', 'config')">Save</button></td></tr>
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
<tr><td class="pc1">Saturation</td><td class="pc2">Low <input type="range" class="slider" name="saturation" id=saturationid min="-2" max="2" step="1" onchange="changeValue(this.value, 'set_int?saturation=', 'config')"> High</td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr>
|
||||
<td class="pc1">Image rotation</td><td><label for="image_rotation"></label>
|
||||
<td class="pc1">Image Rotation</td><td><label for="image_rotation"></label>
|
||||
<select class="select" id="image_rotationid" name="image_rotation" onchange="changeValue(this.value, 'set_int?image_rotation=', 'config')">
|
||||
<option value="1">0°</option>
|
||||
<option value="6">90°</option>
|
||||
|
|
@ -44,13 +44,14 @@
|
|||
<tr><td class="pc1">Flash duration</td><td class="pc2">Low <input type="range" class="slider" name="flash_time" id=flash_timeid min="50" max="1500" step="50" onchange="changeValue(this.value, 'set_int?flash_time=', 'config')">High</td></tr>
|
||||
<tr><td class="pc1">Flash duration</td><td class="pc2"><span id="flash_time_value"></span> ms</td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr><td class="pc1">Save images to micro SD</td><td class="pc2"><label class="switch"><input type="checkbox" name="timelaps" id=timelapsid onchange="changeValue(this.checked, 'set_bool?timelaps_enable=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_timelaps"></span></td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
</table></center>
|
||||
|
||||
<center><button class="btn_collapsible">Advanced image settings</button></center>
|
||||
<center><button class="btn_collapsible">Advanced settings</button></center>
|
||||
<div class="content">
|
||||
<center><table id="data">
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr><td class="ps3">Advanced image settings</td><td></td></tr>
|
||||
<tr><td class="ps3">Advanced settings</td><td></td></tr>
|
||||
<tr><td class="pc1">Automatic white balancing</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb" id=awbid onchange="changeValue(this.checked, 'set_bool?awb=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb"></span></td></tr>
|
||||
<tr><td class="pc1">Automatic white balancing gain</td><td class="pc2"><label class="switch"><input type="checkbox" name="awb_gain" id=awb_gainid onchange="changeValue(this.checked, 'set_bool?awb_gain=', 'config')"><span class="checkbox_slider round"></span></label> <span id="status_awb_gain"></span></td></tr>
|
||||
<tr>
|
||||
|
|
@ -81,7 +82,6 @@
|
|||
</table></center>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="scripts.js"></script>
|
||||
<script>
|
||||
get_data("config");
|
||||
|
|
|
|||
|
|
@ -4,16 +4,18 @@
|
|||
<center>
|
||||
<table id="data">
|
||||
<tr><td class="ps3">System status</td><td></td></tr>
|
||||
<tr><td class="ps1">PrusaConnect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
||||
<tr><td class="ps1">Prusa Connect Status</td><td class="ps2" id="last_upload_status"></td></tr>
|
||||
<tr><td class="ps1">Wi-Fi mode</td><td class="ps2" id="wifi_mode"></td></tr>
|
||||
<tr><td class="ps1">Wi-Fi service AP SSID</td><td class="ps2" id="service_ap_ssid"></td></tr>
|
||||
<tr><td class="ps1">Uptime</td><td class="ps2" id="uptime"></td></tr>
|
||||
<tr><td class="ps1">Software version</td><td class="ps2" id="sw_ver"></td></tr>
|
||||
<tr><td class="ps1">Software build</td><td class="ps2" id="sw_build"></td></tr>
|
||||
<tr><td class="ps1">Available software update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr><td class="ps3">Firmware</td><td></td></tr>
|
||||
<tr><td class="ps1">Version</td><td class="ps2" id="sw_ver"></td></tr>
|
||||
<tr><td class="ps1">Build</td><td class="ps2" id="sw_build"></td></tr>
|
||||
<tr><td class="ps1">Available update</td><td class="ps2"><span id="sw_new_ver"></span> <span class="underlined-text" onclick="checkUpdate()">Check update from cloud</span></td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr><td class="ps3">System configuration</td><td></td></tr>
|
||||
<tr><td class="pc1">Cam name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
||||
<tr><td class="pc1">Camera name & mDNS record</td><td ><input type="text" name="mdns" id=mdnsid ><span class=pc1>.local</span> <button class="btn_save" onclick="changeValue(document.getElementById('mdnsid').value, 'set_mdns?mdns=', 'system')">Save</button></td></tr>
|
||||
<tr>
|
||||
<td class="pc1">Log level</td><td><label for="loglevel"></label>
|
||||
<select class="select" id="loglevelid" name="loglevel" onchange="changeValue(this.value, 'set_int?log_level=', 'system')">
|
||||
|
|
@ -25,21 +27,26 @@
|
|||
</td>
|
||||
</tr>
|
||||
<tr><td class="pc1">Get logs</td><td ><button class="btn_update" onclick="window.open('get_logs')">Get logs</button></td></tr>
|
||||
<tr><td style="height: 1px;"></td><td style="height: 1px;"></td></tr>
|
||||
<tr><td class="ps3">Micro SD card</td><td></td></tr>
|
||||
<tr><td class="ps1">Card status</td><td class="ps2" id="sd_status"></td></tr>
|
||||
<tr><td class="ps1">Capacity</td><td class="ps2"><span id="sd_total"></span> MB</td></tr>
|
||||
<tr><td class="ps1">Available</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_free">0%</div></div></td></tr>
|
||||
<tr><td class="ps1">Used</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="progress_bar_sd_used">0%</div></div></td></tr>
|
||||
</table>
|
||||
</center>
|
||||
<br>
|
||||
<center>
|
||||
<table id="update">
|
||||
<tr><td class="ps3">Firmware update</td><td></td></tr>
|
||||
<tr><td class="ps1">Status:</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
||||
<tr><td class="ps1">Processing:</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div><!--<span class="ps2" id="progressValue">0</span>%--></td></tr>
|
||||
<tr><td></td><td style="width:50%"><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
||||
<tr><td class="ps1">Status</td><td><span class="ps2" id="status">Ready</span></td></tr>
|
||||
<tr><td class="ps1">Progress</td><td class="ps2"><div class="progress-container"><div class="progress-bar" id="myProgressBar">0%</div></div></td></tr>
|
||||
<tr><td></td><td><input type="file" id="firmwareInput" accept=".bin"></td></tr>
|
||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from file" onclick="uploadFile()"></td></tr>
|
||||
<tr><td></td><td><input type="submit" class="btn_update" value="Update from cloud" onclick="updateWeb()"></td></tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
|
||||
<script src="scripts.js"></script>
|
||||
<script>
|
||||
var updateCompleted = false;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<style>@import url("styles.css");</style>
|
||||
<script src="jquery-3.7.0.min.js"></script>
|
||||
|
||||
<body>
|
||||
<table id="center_tb">
|
||||
<tr><td></td><td style="width:40%">
|
||||
|
|
@ -11,12 +10,10 @@
|
|||
<p class="w2">IP Address: <span id="ip"></span></p>
|
||||
<p class="w2">mDNS: http://<span id="mdns"></span>.local</p>
|
||||
</td><td></td></tr>
|
||||
|
||||
<tr><td></td><td style="width:40%">
|
||||
<br>
|
||||
<p class="w1">Available networks</p>
|
||||
</td><td></td></tr>
|
||||
|
||||
<tr><td></td><td style="width:40%">
|
||||
<table id="wifi_ntw">
|
||||
<colgroup>
|
||||
|
|
@ -33,12 +30,10 @@
|
|||
</tr>
|
||||
</table>
|
||||
</td><td></td></tr>
|
||||
|
||||
<tr><td></td><td style="width:40%" align="right">
|
||||
<button class="btn" onclick="scanWifi()">Scan Wi-Fi networks</button>
|
||||
<br>
|
||||
</td><td></td></tr>
|
||||
|
||||
<tr><td></td><td style="width:40%">
|
||||
<br>
|
||||
<table>
|
||||
|
|
@ -48,9 +43,7 @@
|
|||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifi(document.getElementById('wifi_ssid_id').value, document.getElementById('wifi_pass_id').value)">Save & Connect</button></td></tr>
|
||||
</table>
|
||||
</td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<br>
|
||||
<center>
|
||||
<button class="btn_collapsible_wifi">Advanced Wi-Fi settings</button>
|
||||
|
|
@ -74,9 +67,7 @@
|
|||
<tr><td></td><td align="center"><button class="btn_save_w" onclick="setWifiNet(document.getElementById('net_ip_id').value, document.getElementById('net_mask_id').value, document.getElementById('net_gw_id').value, document.getElementById('net_dns_id').value)">Save</button></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<script src="scripts.js"></script>
|
||||
<script>
|
||||
setTimeout(function(){GetDataAndPrintTableWiFi();}, 500);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ function get_data(val) {
|
|||
document.getElementById('agc_gainid').value = obj.agc_gain;
|
||||
document.getElementById("flash_time_value").innerText = obj.flash_time;
|
||||
document.getElementById("aec_value_value").innerText = obj.aec_value;
|
||||
document.getElementById('timelapsid').checked = obj.timelaps;
|
||||
$("#status_hmirror").text((obj.hmirror == "true") ? "On" : "Off");
|
||||
$("#status_vflip").text((obj.vflip == "true") ? "On" : "Off");
|
||||
$("#status_lensc").text((obj.lensc == "true") ? "On" : "Off");
|
||||
|
|
@ -59,6 +60,7 @@ function get_data(val) {
|
|||
$("#status_raw_gama").text((obj.raw_gama == "true") ? "On" : "Off");
|
||||
$("#status_aec2").text((obj.aec2 == "true") ? "On" : "Off");
|
||||
$("#status_gain_ctrl").text((obj.gain_ctrl == "true") ? "On" : "Off");
|
||||
$("#status_timelaps").text((obj.timelaps == "true") ? "On" : "Off");
|
||||
sliderCheck();
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +102,19 @@ function get_data(val) {
|
|||
$("#wifi_mode").text(obj.wifi_mode);
|
||||
$("#sw_new_ver").text(obj.sw_new_ver);
|
||||
$("#service_ap_ssid").text(obj.service_ap_ssid);
|
||||
$("#sd_status").text(obj.sd_status);
|
||||
$("#sd_total").text(obj.sd_total);
|
||||
$("#sd_free_p").text(obj.sd_free_p);
|
||||
$("#sd_used_p").text(obj.sd_used_p);
|
||||
|
||||
var sd_free_prog = document.getElementById("progress_bar_sd_free");
|
||||
sd_free_prog.style.width = obj.sd_free_p + "%";
|
||||
sd_free_prog.innerHTML = obj.sd_free_p + "%";
|
||||
|
||||
var sd_free_prog = document.getElementById("progress_bar_sd_used");
|
||||
sd_free_prog.style.width = obj.sd_used_p + "%";
|
||||
sd_free_prog.innerHTML = obj.sd_used_p + "%";
|
||||
|
||||
document.getElementById('mdnsid').value = obj.mdns;
|
||||
document.getElementById('loglevelid').value = obj.log_level;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +1,75 @@
|
|||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/* index styles */
|
||||
.p1 {
|
||||
color: #797979;
|
||||
font: normal normal normal 18px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
.p1 {
|
||||
color: #797979;
|
||||
font: normal normal normal 18px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
.p2 {
|
||||
text-align: left;
|
||||
font: normal normal bold 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
.p2 {
|
||||
text-align: left;
|
||||
font: normal normal bold 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
.p3 {
|
||||
text-align: left;
|
||||
font: normal normal normal 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
.p3 {
|
||||
text-align: left;
|
||||
font: normal normal normal 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
.p4 {
|
||||
text-align: left;
|
||||
font: normal normal normal 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
.p4 {
|
||||
text-align: left;
|
||||
font: normal normal normal 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #808080;
|
||||
opacity: 1;
|
||||
}
|
||||
.p5 {
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
.p5 {
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/20px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
}
|
||||
/* NAVIGATION BAR */
|
||||
nav {
|
||||
display: flex;
|
||||
background-color: transparent;
|
||||
nav {
|
||||
display: flex;
|
||||
background-color: transparent;
|
||||
}
|
||||
.top_bar {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
.top_bar {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.top_bar li {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
.top_bar li {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
}
|
||||
.top_bar li a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.top_bar li a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.top_bar li a:hover {
|
||||
text-decoration: underline #fa6831;
|
||||
text-underline-position: under;
|
||||
text-underline-offset: 8px;
|
||||
text-decoration-thickness: 2px;
|
||||
.top_bar li a:hover {
|
||||
text-decoration: underline #fa6831;
|
||||
text-underline-position: under;
|
||||
text-underline-offset: 8px;
|
||||
text-decoration-thickness: 2px;
|
||||
}
|
||||
#links li a.active {
|
||||
text-decoration: underline #fa6831;
|
||||
text-underline-position: under;
|
||||
text-underline-offset: 8px;
|
||||
text-decoration-thickness: 2px;
|
||||
#links li a.active {
|
||||
text-decoration: underline #fa6831;
|
||||
text-underline-position: under;
|
||||
text-underline-offset: 8px;
|
||||
text-decoration-thickness: 2px;
|
||||
}
|
||||
/* CFG BAR */
|
||||
cfg {
|
||||
#cfg {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
|
|
@ -79,18 +78,18 @@ cfg {
|
|||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
cfg_bar li {
|
||||
#cfg_bar li {
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
font-size: 16px;
|
||||
left: 50%;
|
||||
}
|
||||
cfg_bar li a {
|
||||
#cfg_bar li a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: #212529;
|
||||
}
|
||||
cfg_bar li a:hover {
|
||||
#cfg_bar li a:hover {
|
||||
color: #fa6831;
|
||||
}
|
||||
/* CONTAINER */
|
||||
|
|
@ -99,110 +98,110 @@ cfg_bar li a:hover {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.container_left-half {
|
||||
grid-column: 1;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
.container_left-half {
|
||||
grid-column: 1;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
.container_right-half {
|
||||
grid-column: 2;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 50%;
|
||||
.container_right-half {
|
||||
grid-column: 2;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
width: 50%;
|
||||
}
|
||||
/* CHECKBOX SLIDER */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 17px;
|
||||
vertical-align: middle;
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 17px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.checkbox_slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
.checkbox_slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
.checkbox_slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
.checkbox_slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
input:checked+.checkbox_slider {
|
||||
background-color: #797979;
|
||||
input:checked+.checkbox_slider {
|
||||
background-color: #797979;
|
||||
}
|
||||
input:focus+.checkbox_slider {
|
||||
box-shadow: 0 0 1px #797979;
|
||||
input:focus+.checkbox_slider {
|
||||
box-shadow: 0 0 1px #797979;
|
||||
}
|
||||
input:checked+.checkbox_slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
input:checked+.checkbox_slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
}
|
||||
.checkbox_slider.round {
|
||||
border-radius: 13px;
|
||||
.checkbox_slider.round {
|
||||
border-radius: 13px;
|
||||
}
|
||||
.checkbox_slider.round:before {
|
||||
border-radius: 50%;
|
||||
.checkbox_slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
/* BUTTON */
|
||||
.btn {
|
||||
width: 306px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
.btn {
|
||||
width: 306px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
.btn:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
/* BOTTON table */
|
||||
#botton {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background: #F5F5F5 0% 0% no-repeat padding-box;
|
||||
opacity: 1;
|
||||
bottom: 0;
|
||||
#botton {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background: #F5F5F5 0% 0% no-repeat padding-box;
|
||||
opacity: 1;
|
||||
bottom: 0;
|
||||
}
|
||||
/* ----- styles config ----- */
|
||||
.pc1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
.pc1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
}
|
||||
.pc2 {
|
||||
text-align: left;
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
.pc2 {
|
||||
text-align: left;
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
}
|
||||
.pc3 {
|
||||
.pc3 {
|
||||
text-align: right;
|
||||
font: normal normal normal bold 12px/17px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
|
|
@ -210,148 +209,148 @@ cfg_bar li a:hover {
|
|||
opacity: 1;
|
||||
}
|
||||
/* data table */
|
||||
#data {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
#data {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
#data td, #data th {
|
||||
padding: 8px;
|
||||
#data td, #data th {
|
||||
padding: 8px;
|
||||
}
|
||||
#data th {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
text-align: left;
|
||||
#data th {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
/* BUTTON */
|
||||
.btn_save {
|
||||
width: 69px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
.btn_save {
|
||||
width: 69px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
}
|
||||
.btn_save:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
.btn_save:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
/* RANGE */
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
width: 133px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
||||
outline: none;
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
width: 133px;
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
background: linear-gradient(to right, #d3d3d3 50%, #FA6831 50%);
|
||||
outline: none;
|
||||
}
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #FA6831;
|
||||
cursor: pointer;
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #FA6831;
|
||||
cursor: pointer;
|
||||
}
|
||||
.slider::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #FA6831;
|
||||
cursor: pointer;
|
||||
.slider::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #FA6831;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* ----- styles wifi ----- */
|
||||
.w1 {
|
||||
text-align: left;
|
||||
font: normal normal bold 12px/17px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
.w1 {
|
||||
text-align: left;
|
||||
font: normal normal bold 12px/17px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
.w2 {
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
.w2 {
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
}
|
||||
.w2 span {
|
||||
vertical-align: middle;
|
||||
.w2 span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#center_tb {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: left;
|
||||
#center_tb {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: left;
|
||||
}
|
||||
#wificfg_tb {
|
||||
margin-left: 30%;
|
||||
}
|
||||
/* wifi_ntw table */
|
||||
#wifi_ntw {
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: left;
|
||||
#wifi_ntw {
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: left;
|
||||
}
|
||||
#wifi_ntw td {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
#wifi_ntw td {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
#wifi_ntw tr:nth-child(even) {
|
||||
background: #F8F8F8 0% 0% no-repeat padding-box;
|
||||
#wifi_ntw tr:nth-child(even) {
|
||||
background: #F8F8F8 0% 0% no-repeat padding-box;
|
||||
}
|
||||
#wifi_ntw tr:hover {
|
||||
background-color: #ddd;
|
||||
#wifi_ntw tr:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
#wifi_ntw th {
|
||||
background-color: transparent;
|
||||
text-align: left;
|
||||
font: normal normal bold 13px/11px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
#wifi_ntw th {
|
||||
background-color: transparent;
|
||||
text-align: left;
|
||||
font: normal normal bold 13px/11px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
#wifi_ntw tr {
|
||||
border-bottom: 1px solid #ccc;
|
||||
#wifi_ntw tr {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
#wifi_ntw img {
|
||||
width: 19px;
|
||||
height: 12px;
|
||||
#wifi_ntw img {
|
||||
width: 19px;
|
||||
height: 12px;
|
||||
}
|
||||
/* BUTTON */
|
||||
.btn_save_w {
|
||||
width: 178px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
.btn_save_w {
|
||||
width: 178px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
}
|
||||
.btn_save_w:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
.btn_save_w:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
/* ----- styles auth ----- */
|
||||
.pa1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
.pa1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
}
|
||||
.pa2 {
|
||||
text-align: left;
|
||||
font: normal normal bold 12px/17px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
.pa2 {
|
||||
text-align: left;
|
||||
font: normal normal bold 12px/17px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
.pa3 {
|
||||
text-align: right;
|
||||
|
|
@ -360,56 +359,55 @@ cfg_bar li a:hover {
|
|||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* BUTTON */
|
||||
.btn_save_a {
|
||||
width: 178px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
.btn_save_a {
|
||||
width: 178px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
font: normal normal bold 14px/5px sans-serif;
|
||||
color: #000000;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
}
|
||||
.btn_save_a:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
.btn_save_a:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
.toggle-password {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
.toggle-password {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
.toggle-password img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
.toggle-password img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.password-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.password-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#auth_password.reveal {
|
||||
-webkit-text-security: none;
|
||||
#auth_password.reveal {
|
||||
-webkit-text-security: none;
|
||||
}
|
||||
#auth_password {
|
||||
-webkit-text-security: disc;
|
||||
#auth_password {
|
||||
-webkit-text-security: disc;
|
||||
}
|
||||
/* ----- styles system ----- */
|
||||
.ps1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
.ps1 {
|
||||
text-align: right;
|
||||
font: normal normal normal 11px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #797979;
|
||||
opacity: 1;
|
||||
}
|
||||
.ps2 {
|
||||
text-align: left;
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
.ps2 {
|
||||
text-align: left;
|
||||
font: normal normal normal 12px/5px sans-serif;
|
||||
letter-spacing: 0px;
|
||||
color: #000000;
|
||||
opacity: 1;
|
||||
}
|
||||
.ps3 {
|
||||
text-align: right;
|
||||
|
|
@ -418,38 +416,23 @@ cfg_bar li a:hover {
|
|||
color: #2A2A2A;
|
||||
opacity: 1;
|
||||
}
|
||||
/* data table */
|
||||
#data {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
#data td, #data th {
|
||||
padding: 8px;
|
||||
}
|
||||
#data th {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
/* update table */
|
||||
update {
|
||||
#update {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
#update td, #update th {
|
||||
#update td, #update th {
|
||||
padding: 8px;
|
||||
}
|
||||
#update th {
|
||||
#update th {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
text-align: left;
|
||||
}
|
||||
/* BUTTON */
|
||||
.btn_update {
|
||||
.btn_update {
|
||||
width: 178px;
|
||||
height: 24px;
|
||||
text-align: center;
|
||||
|
|
@ -459,34 +442,33 @@ cfg_bar li a:hover {
|
|||
border-radius: 5px;
|
||||
border: 1px solid #343a40;
|
||||
}
|
||||
.btn_update:hover {
|
||||
.btn_update:hover {
|
||||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
.underlined-text {
|
||||
.underlined-text {
|
||||
text-decoration: underline;
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* progress bar*/
|
||||
.progress-container {
|
||||
width: 100%;
|
||||
.progress-container {
|
||||
width: 30%;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.progress-bar {
|
||||
.progress-bar {
|
||||
width: 0px;
|
||||
height: 15px;
|
||||
background-color: #FA6831;
|
||||
text-align: center;
|
||||
line-height: 15px;
|
||||
color: white;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
/* advanced cam cfg */
|
||||
.content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn_collapsible {
|
||||
width: 300px;
|
||||
height: 24px;
|
||||
|
|
@ -501,12 +483,10 @@ cfg_bar li a:hover {
|
|||
background-color: #FA6831;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* advanced wifi cfg */
|
||||
.content_wifi {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn_collapsible_wifi {
|
||||
width: 300px;
|
||||
height: 24px;
|
||||
|
|
|
|||
Loading…
Reference in New Issue