diff --git a/code/components/esp32-camera-master/examples/take_picture.c b/code/components/esp32-camera-master/examples/take_picture.c index 96b224fd..8a22e8c3 100644 --- a/code/components/esp32-camera-master/examples/take_picture.c +++ b/code/components/esp32-camera-master/examples/take_picture.c @@ -29,7 +29,7 @@ // ================================ CODE ====================================== -#include +#include #include #include #include diff --git a/code/components/jomjol_controlGPIO/CMakeLists.txt b/code/components/jomjol_controlGPIO/CMakeLists.txt index 99cb4f80..66b7408c 100644 --- a/code/components/jomjol_controlGPIO/CMakeLists.txt +++ b/code/components/jomjol_controlGPIO/CMakeLists.txt @@ -4,6 +4,6 @@ list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/proto idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES esp_http_server jomjol_logfile jomjol_configfile jomjol_mqtt) + REQUIRES esp_http_server jomjol_logfile jomjol_configfile jomjol_mqtt jomjol_flowcontroll) diff --git a/code/components/jomjol_controlGPIO/server_GPIO.cpp b/code/components/jomjol_controlGPIO/server_GPIO.cpp index f318e20a..43423f44 100644 --- a/code/components/jomjol_controlGPIO/server_GPIO.cpp +++ b/code/components/jomjol_controlGPIO/server_GPIO.cpp @@ -20,10 +20,12 @@ #include "configFile.h" #include "Helper.h" #include "interface_mqtt.h" +#include "ClassFlowMQTT.h" static const char *TAG_SERVERGPIO = "server_GPIO"; +QueueHandle_t gpio_queue_handle = NULL; -// #define DEBUG_DETAIL_ON +#define DEBUG_DETAIL_ON GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable) { @@ -32,13 +34,11 @@ GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_i _mode = mode; _interruptType = interruptType; _mqttTopic = mqttTopic; - - //initGPIO(); } GpioPin::~GpioPin() { - ESP_LOGI(TAG_SERVERGPIO,"reset GPIO pin %d", _gpio); + ESP_LOGD(TAG_SERVERGPIO,"reset GPIO pin %d", _gpio); if (_interruptType != GPIO_INTR_DISABLE) { //hook isr handler for specific gpio pin gpio_isr_handler_remove(_gpio); @@ -48,13 +48,37 @@ GpioPin::~GpioPin() static void IRAM_ATTR gpio_isr_handler(void* arg) { - GpioPin* gpioPin = (GpioPin*) arg; - gpioPin->gpioInterrupt(); + GpioResult gpioResult; + gpioResult.gpio = *(gpio_num_t*) arg; + gpioResult.value = gpio_get_level(gpioResult.gpio) == 1; + BaseType_t ContextSwitchRequest = pdFALSE; + + xQueueSendToBackFromISR(gpio_queue_handle,(void*)&gpioResult,&ContextSwitchRequest); + + if(ContextSwitchRequest){ + taskYIELD(); + } } -void GpioPin::gpioInterrupt () { +static void gpioInterruptTask(void *arg) { + while(1){ + if(uxQueueMessagesWaiting(gpio_queue_handle)){ + while(uxQueueMessagesWaiting(gpio_queue_handle)){ + GpioResult gpioResult; + xQueueReceive(gpio_queue_handle,(void*)&gpioResult,10); + ESP_LOGD(TAG_SERVERGPIO,"gpio: %d state: %d", gpioResult.gpio, gpioResult.value); + ((GpioHandler*)arg)->gpioInterrupt(&gpioResult); + } + } + vTaskDelay(pdMS_TO_TICKS(1000)); + } +} + +void GpioPin::gpioInterrupt(bool value) { if (_mqttTopic != "") { - MQTTPublish(_mqttTopic, (gpio_get_level(_gpio) == 1) ? "true" : "false"); + ESP_LOGD(TAG_SERVERGPIO, "gpioInterrupt %s %d", _mqttTopic.c_str(), value); + + MQTTPublish(_mqttTopic, value ? "true" : "false"); } } @@ -64,7 +88,7 @@ void GpioPin::init() //set interrupt io_conf.intr_type = _interruptType; //set as output mode - io_conf.mode = _mode == GPIO_PIN_MODE_OUTPUT ? gpio_mode_t::GPIO_MODE_OUTPUT : gpio_mode_t::GPIO_MODE_INPUT; + io_conf.mode = (_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_BUILT_IN_FLASH_LED) ? gpio_mode_t::GPIO_MODE_OUTPUT : gpio_mode_t::GPIO_MODE_INPUT; //bit mask of the pins that you want to set,e.g.GPIO18/19 io_conf.pin_bit_mask = (1ULL << _gpio); //set pull-down mode @@ -76,10 +100,10 @@ void GpioPin::init() if (_interruptType != GPIO_INTR_DISABLE) { //hook isr handler for specific gpio pin - gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*) this); + gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*)&_gpio); } - if ((_mqttTopic != "") && ((_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_OUTPUT_PWM))) { + if ((_mqttTopic != "") && ((_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_OUTPUT_PWM) || (_mode == GPIO_PIN_MODE_BUILT_IN_FLASH_LED))) { std::function f = std::bind(&GpioPin::handleMQTT, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); MQTTregisterSubscribeFunction(_mqttTopic, f); } @@ -94,34 +118,38 @@ bool GpioPin::getValue(std::string* errorText) return gpio_get_level(_gpio) == 1; } -void GpioPin::setValue(bool value, std::string* errorText) +void GpioPin::setValue(bool value, gpio_set_source setSource, std::string* errorText) { - printf("setValue %d\r\n", value); - - if ((_mode != GPIO_PIN_MODE_OUTPUT) && (_mode != GPIO_PIN_MODE_OUTPUT_PWM)) { + ESP_LOGD(TAG_SERVERGPIO, "GpioPin::setValue %d\r\n", value); + + if ((_mode != GPIO_PIN_MODE_OUTPUT) && (_mode != GPIO_PIN_MODE_OUTPUT_PWM) && (_mode != GPIO_PIN_MODE_BUILT_IN_FLASH_LED)) { (*errorText) = "GPIO is not in output mode"; } else { gpio_set_level(_gpio, value); + + if ((_mqttTopic != "") && (setSource != GPIO_SET_SOURCE_MQTT)) { + MQTTPublish(_mqttTopic, value ? "true" : "false"); + } } } bool GpioPin::handleMQTT(std::string, char* data, int data_len) { - printf("handleMQTT data %.*s\r\n", data_len, data); - + ESP_LOGD(TAG_SERVERGPIO, "GpioPin::handleMQTT data %.*s\r\n", data_len, data); + std::string dataStr(data, data_len); dataStr = toLower(dataStr); std::string errorText = ""; if ((dataStr == "true") || (dataStr == "1")) { - setValue(true, &errorText); + setValue(true, GPIO_SET_SOURCE_MQTT, &errorText); } else if ((dataStr == "false") || (dataStr == "0")) { - setValue(false, &errorText); + setValue(false, GPIO_SET_SOURCE_MQTT, &errorText); } else { errorText = "wrong value "; errorText.append(data, data_len); } if (errorText != "") { - printf(errorText.c_str()); + ESP_LOGE(TAG_SERVERGPIO, "%s", errorText.c_str()); } return (errorText == ""); @@ -130,14 +158,15 @@ bool GpioPin::handleMQTT(std::string, char* data, int data_len) { esp_err_t callHandleHttpRequest(httpd_req_t *req) { - ESP_LOGI(TAG_SERVERGPIO,"callHandleHttpRequest"); + ESP_LOGD(TAG_SERVERGPIO,"callHandleHttpRequest"); + GpioHandler *gpioHandler = (GpioHandler*)req->user_ctx; return gpioHandler->handleHttpRequest(req); } void taskGpioHandler(void *pvParameter) { - ESP_LOGI(TAG_SERVERGPIO,"taskGpioHandler"); + ESP_LOGD(TAG_SERVERGPIO,"taskGpioHandler"); ((GpioHandler*)pvParameter)->init(); } @@ -177,15 +206,26 @@ void GpioHandler::init() for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { it->second->init(); + + if ((it->second->getInterruptType() != GPIO_INTR_DISABLE) && (gpio_queue_handle == NULL)) { + gpio_queue_handle = xQueueCreate(10,sizeof(GpioResult)); + xTaskCreate(gpioInterruptTask, "GPIO Task", configMINIMAL_STACK_SIZE * 64, (void *)this, 10, NULL); + } } ESP_LOGI(TAG_SERVERGPIO, "GPIO init comleted"); } -void GpioHandler::destroy() { +void GpioHandler::deinit() { clear(); } +void GpioHandler::gpioInterrupt(GpioResult* gpioResult) { + if ((gpioMap != NULL) && (gpioMap->find(gpioResult->gpio) != gpioMap->end())) { + (*gpioMap)[gpioResult->gpio]->gpioInterrupt(gpioResult->value); + } +} + bool GpioHandler::readConfig() { if (!gpioMap->empty()) @@ -202,6 +242,7 @@ bool GpioHandler::readConfig() if (eof) return false; + _isEnabled = true; std::string mainTopicMQTT = ""; bool registerISR = false; while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line)) @@ -212,11 +253,11 @@ bool GpioHandler::readConfig() // if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2)) // { // std::string gpioStr = pieces_match[1]; - printf("conf param %s\r\n", toUpper(zerlegt[0]).c_str()); + ESP_LOGD(TAG_SERVERGPIO, "conf param %s\r\n", toUpper(zerlegt[0]).c_str()); if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") { - printf("MAINTOPICMQTT found\r\n"); + ESP_LOGD(TAG_SERVERGPIO, "MAINTOPICMQTT found\r\n"); mainTopicMQTT = zerlegt[1]; - } else if (zerlegt[0].rfind("IO", 0) == 0) + } else if ((zerlegt[0].rfind("IO", 0) == 0) && (zerlegt.size() >= 6)) { ESP_LOGI(TAG_SERVERGPIO,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str()); std::string gpioStr = zerlegt[0].substr(2, 2); @@ -226,8 +267,14 @@ bool GpioHandler::readConfig() uint16_t dutyResolution = (uint8_t)atoi(zerlegt[3].c_str()); bool mqttEnabled = toLower(zerlegt[4]) == "true"; bool httpEnabled = toLower(zerlegt[5]) == "true"; - std::string mqttTopic = mqttEnabled ? (mainTopicMQTT + "/" + zerlegt[6]) : ""; - GpioPin* gpioPin = new GpioPin(gpioNr, zerlegt[6].c_str(), pinMode, intType,dutyResolution, mqttTopic, httpEnabled); + char gpioName[100]; + if (zerlegt.size() >= 7) { + strcpy(gpioName, trim(zerlegt[6]).c_str()); + } else { + sprintf(gpioName, "GPIO%d", gpioNr); + } + std::string mqttTopic = mqttEnabled ? (mainTopicMQTT + "/" + gpioName) : ""; + GpioPin* gpioPin = new GpioPin(gpioNr, gpioName, pinMode, intType,dutyResolution, mqttTopic, httpEnabled); (*gpioMap)[gpioNr] = gpioPin; if (intType != GPIO_INTR_DISABLE) { @@ -246,10 +293,14 @@ bool GpioHandler::readConfig() void GpioHandler::clear() { - for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { - delete it->second; + ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::clear\r\n"); + + if (gpioMap != NULL) { + for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { + delete it->second; + } + gpioMap->clear(); } - gpioMap->clear(); // gpio_uninstall_isr_service(); can't uninstall, isr service is used by camera } @@ -268,7 +319,13 @@ void GpioHandler::registerGpioUri() esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) { - ESP_LOGI(TAG_SERVERGPIO, "handleHttpRequest"); + ESP_LOGD(TAG_SERVERGPIO, "handleHttpRequest"); + + if (gpioMap == NULL) { + std::string resp_str = "GPIO handler not initialized"; + httpd_resp_send(req, resp_str.c_str(), resp_str.length()); + return ESP_OK; + } #ifdef DEBUG_DETAIL_ON LogFile.WriteHeapInfo("handler_switch_GPIO - Start"); @@ -279,14 +336,13 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) char _valueGPIO[30]; char _valueStatus[30]; std::string gpio, status; - printf("-1-\r\n"); if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) { - printf("Query: "); printf(_query); printf("\r\n"); + ESP_LOGD(TAG_SERVERGPIO, "Query: %s", _query); if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK) { - printf("GPIO is found "); printf(_valueGPIO); printf("\r\n"); + ESP_LOGD(TAG_SERVERGPIO, "GPIO is found %s", _valueGPIO); gpio = std::string(_valueGPIO); } else { std::string resp_str = "GPIO No is not defined"; @@ -295,7 +351,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) } if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK) { - printf("Status is found "); printf(_valueStatus); printf("\r\n"); + ESP_LOGD(TAG_SERVERGPIO, "Status is found %s", _valueStatus); status = std::string(_valueStatus); } } else { @@ -303,7 +359,6 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) httpd_resp_send(req, resp_str, strlen(resp_str)); return ESP_OK; } - printf("-2-\r\n"); status = toUpper(status); if ((status != "HIGH") && (status != "LOW") && (status != "TRUE") && (status != "FALSE") && (status != "0") && (status != "1") && (status != "")) @@ -313,7 +368,6 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) httpd_resp_sendstr_chunk(req, NULL); return ESP_OK; } - printf("-3-\r\n"); int gpionum = stoi(gpio); @@ -334,8 +388,6 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) return ESP_OK; } - printf("-4-\r\n"); - if (status == "") { std::string resp_str = ""; @@ -349,18 +401,39 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) else { std::string resp_str = ""; - (*gpioMap)[gpio_num]->setValue((status == "HIGH") || (status == "TRUE") || (status == "1"), &resp_str); + (*gpioMap)[gpio_num]->setValue((status == "HIGH") || (status == "TRUE") || (status == "1"), GPIO_SET_SOURCE_HTTP, &resp_str); if (resp_str == "") { resp_str = "GPIO" + std::to_string(gpionum) + " switched to " + status; } httpd_resp_sendstr_chunk(req, resp_str.c_str()); httpd_resp_sendstr_chunk(req, NULL); } - printf("-5-\r\n"); return ESP_OK; }; +void GpioHandler::flashLightEnable(bool value) +{ + ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::flashLightEnable %s\r\n", value ? "true" : "false"); + + if (gpioMap != NULL) { + for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) + { + if (it->second->getMode() == GPIO_PIN_MODE_BUILT_IN_FLASH_LED) //|| (it->second->getMode() == GPIO_PIN_MODE_EXTERNAL_FLASH_PWM) || (it->second->getMode() == GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X)) + { + std::string resp_str = ""; + it->second->setValue(value, GPIO_SET_SOURCE_INTERNAL, &resp_str); + + if (resp_str == "") { + ESP_LOGD(TAG_SERVERGPIO, "Flash light pin GPIO %d switched to %s\r\n", (int)it->first, (value ? "on" : "off")); + } else { + ESP_LOGE(TAG_SERVERGPIO, "Can't set flash light pin GPIO %d. Error: %s\r\n", (int)it->first, resp_str.c_str()); + } + } + } + } +} + gpio_num_t GpioHandler::resolvePinNr(uint8_t pinNr) { switch(pinNr) { @@ -388,6 +461,7 @@ gpio_pin_mode_t GpioHandler::resolvePinMode(std::string input) if( input == "input-pullup" ) return GPIO_PIN_MODE_INPUT_PULLUP; if( input == "input-pulldown" ) return GPIO_PIN_MODE_INPUT_PULLDOWN; if( input == "output" ) return GPIO_PIN_MODE_OUTPUT; + if( input == "built-in-led" ) return GPIO_PIN_MODE_BUILT_IN_FLASH_LED; if( input == "output-pwm" ) return GPIO_PIN_MODE_OUTPUT_PWM; if( input == "external-flash-pwm" ) return GPIO_PIN_MODE_EXTERNAL_FLASH_PWM; if( input == "external-flash-ws281x" ) return GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X; diff --git a/code/components/jomjol_controlGPIO/server_GPIO.h b/code/components/jomjol_controlGPIO/server_GPIO.h index 7abc9ff3..90e8f4c9 100644 --- a/code/components/jomjol_controlGPIO/server_GPIO.h +++ b/code/components/jomjol_controlGPIO/server_GPIO.h @@ -15,11 +15,22 @@ typedef enum { GPIO_PIN_MODE_INPUT_PULLUP = 0x2, GPIO_PIN_MODE_INPUT_PULLDOWN = 0x3, GPIO_PIN_MODE_OUTPUT = 0x4, - GPIO_PIN_MODE_OUTPUT_PWM = 0x5, - GPIO_PIN_MODE_EXTERNAL_FLASH_PWM = 0x5, - GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X = 0x5, + GPIO_PIN_MODE_BUILT_IN_FLASH_LED = 0x5, + GPIO_PIN_MODE_OUTPUT_PWM = 0x6, + GPIO_PIN_MODE_EXTERNAL_FLASH_PWM = 0x7, + GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X = 0x8, } gpio_pin_mode_t; +struct GpioResult { + gpio_num_t gpio; + bool value; +}; + +typedef enum { + GPIO_SET_SOURCE_INTERNAL = 0, + GPIO_SET_SOURCE_MQTT = 1, + GPIO_SET_SOURCE_HTTP = 2, +} gpio_set_source; class GpioPin { public: @@ -27,10 +38,12 @@ public: ~GpioPin(); bool getValue(std::string* errorText); - void setValue(bool value, std::string* errorText); + void setValue(bool value, gpio_set_source setSource, std::string* errorText); void init(); bool handleMQTT(std::string, char* data, int data_len); - void gpioInterrupt(); + void gpioInterrupt(bool value); + gpio_int_type_t getInterruptType() { return _interruptType; } + gpio_pin_mode_t getMode() { return _mode; } private: gpio_num_t _gpio; @@ -49,15 +62,19 @@ public: ~GpioHandler(); void init(); - void destroy(); + void deinit(); void registerGpioUri(); - esp_err_t handleHttpRequest(httpd_req_t *req); + esp_err_t handleHttpRequest(httpd_req_t *req); + void gpioInterrupt(GpioResult* gpioResult); + void flashLightEnable(bool value); + bool isEnabled() { return _isEnabled; } private: std::string _configFile; httpd_handle_t _httpServer; std::map *gpioMap = NULL; TaskHandle_t xHandletaskGpioHandler = NULL; + bool _isEnabled = false; bool readConfig(); void clear(); diff --git a/code/components/jomjol_controlcamera/ClassControllCamera.cpp b/code/components/jomjol_controlcamera/ClassControllCamera.cpp index f6be55f8..2f145f8a 100644 --- a/code/components/jomjol_controlcamera/ClassControllCamera.cpp +++ b/code/components/jomjol_controlcamera/ClassControllCamera.cpp @@ -10,12 +10,13 @@ #include "CImageBasis.h" #include "server_ota.h" +#include "server_main.h" #define BOARD_ESP32CAM_AITHINKER -#include +#include #include #include #include @@ -229,7 +230,9 @@ void CCamera::EnableAutoExposure(int flashdauer) camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { - ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); + ESP_LOGE(TAGCAMERACLASS, "EnableAutoExposure: Camera Capture Failed"); + LEDOnOff(false); + LightOnOff(false); doReboot(); } esp_camera_fb_return(fb); @@ -273,8 +276,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay) camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { - ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); + ESP_LOGE(TAGCAMERACLASS, "CaptureToBasisImage: Camera Capture Failed"); LEDOnOff(false); + LightOnOff(false); doReboot(); return ESP_FAIL; @@ -359,8 +363,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay) camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { - ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); - ESP_LOGE(TAGCAMERACLASS, "Reboot ?????"); + ESP_LOGE(TAGCAMERACLASS, "CaptureToFile: Camera Capture Failed"); LEDOnOff(false); LightOnOff(false); doReboot(); @@ -452,7 +455,8 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay) fb = esp_camera_fb_get(); if (!fb) { - ESP_LOGE(TAGCAMERACLASS, "Camera capture failed"); + ESP_LOGE(TAGCAMERACLASS, "CaptureToHTTP: Camera capture failed"); + LEDOnOff(false); LightOnOff(false); httpd_resp_send_500(req); // doReboot(); @@ -493,15 +497,20 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay) void CCamera::LightOnOff(bool status) { - // Init the GPIO - gpio_pad_select_gpio(FLASH_GPIO); - /* Set the GPIO as a push/pull output */ - gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT); + GpioHandler* gpioHandler = gpio_handler_get(); + if ((gpioHandler != NULL) && (gpioHandler->isEnabled())) { + gpioHandler->flashLightEnable(status); + } else { + // Init the GPIO + gpio_pad_select_gpio(FLASH_GPIO); + /* Set the GPIO as a push/pull output */ + gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT); - if (status) - gpio_set_level(FLASH_GPIO, 1); - else - gpio_set_level(FLASH_GPIO, 0); + if (status) + gpio_set_level(FLASH_GPIO, 1); + else + gpio_set_level(FLASH_GPIO, 0); + } } void CCamera::LEDOnOff(bool status) diff --git a/code/components/jomjol_fileserver_ota/server_file.cpp b/code/components/jomjol_fileserver_ota/server_file.cpp index 232e75e8..0a5a157e 100644 --- a/code/components/jomjol_fileserver_ota/server_file.cpp +++ b/code/components/jomjol_fileserver_ota/server_file.cpp @@ -502,10 +502,8 @@ static esp_err_t upload_post_handler(httpd_req_t *req) if (strcmp(filepath, CONFIG_FILE) == 0) { printf("New config foung. Reload handler."); + gpio_handler_deinit(); MQTTdestroy(); - if (gpioHandler != NULL) { - gpioHandler->destroy(); - } } return ESP_OK; diff --git a/code/components/jomjol_fileserver_ota/server_ota.cpp b/code/components/jomjol_fileserver_ota/server_ota.cpp index 378e2c5f..247efb04 100644 --- a/code/components/jomjol_fileserver_ota/server_ota.cpp +++ b/code/components/jomjol_fileserver_ota/server_ota.cpp @@ -12,7 +12,7 @@ #include "freertos/task.h" #include "esp_system.h" #include "esp_event.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include #include "esp_http_client.h" @@ -28,6 +28,7 @@ #include "server_tflite.h" #include "server_file.h" +#include "server_main.h" #include "ClassLogFile.h" @@ -375,6 +376,8 @@ esp_err_t handler_ota_update(httpd_req_t *req) const char* resp_str; + KillTFliteTasks(); + gpio_handler_deinit(); if (ota_example_task(fn)) { resp_str = "Firmware Update Successfull!

You can restart now."; @@ -401,8 +404,6 @@ void hard_restart() { void task_reboot(void *pvParameter) { - - while(1) { vTaskDelay(5000 / portTICK_PERIOD_MS); @@ -414,12 +415,14 @@ void task_reboot(void *pvParameter) } void doReboot(){ - LogFile.WriteToFile("Reboot - now"); - KillTFliteTasks(); + ESP_LOGI(TAGPARTOTA, "Reboot in 5sec"); + LogFile.WriteToFile("Reboot in 5sec"); xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL); + // KillTFliteTasks(); // kills itself + gpio_handler_destroy(); vTaskDelay(5000 / portTICK_PERIOD_MS); esp_restart(); - hard_restart(); + hard_restart(); } diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index 7484a7f9..b266ed1a 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -442,7 +442,7 @@ int ClassFlowControll::CleanTempFolder() { esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req) { - return flowmakeimage->SendRawJPG(req); + return flowmakeimage != NULL ? flowmakeimage->SendRawJPG(req) : ESP_FAIL; } diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp index 022cbf1e..20baa4e4 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp @@ -1,6 +1,8 @@ +#include #include "ClassFlowMQTT.h" #include "Helper.h" +#include "time_sntp.h" #include "interface_mqtt.h" #include "ClassFlowPostProcessing.h" @@ -13,6 +15,8 @@ void ClassFlowMQTT::SetInitialParameter(void) topicError = ""; topicRate = ""; topicTimeStamp = ""; + topicUptime = ""; + topicFreeMem = ""; clientname = "watermeter"; OldValue = ""; flowpostprocessing = NULL; @@ -104,6 +108,14 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) { this->topicTimeStamp = zerlegt[1]; } + if ((toUpper(zerlegt[0]) == "TOPICUPTIME") && (zerlegt.size() > 1)) + { + this->topicUptime = zerlegt[1]; + } + if ((toUpper(zerlegt[0]) == "TOPICFREEMEM") && (zerlegt.size() > 1)) + { + this->topicFreeMem = zerlegt[1]; + } if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1)) { @@ -169,6 +181,18 @@ bool ClassFlowMQTT::doFlow(string zwtime) MQTTPublish(topicTimeStamp, resulttimestamp); } + if (topicUptime.length() > 0) { + char uptimeStr[11]; + sprintf(uptimeStr, "%ld", (long)getUpTime()); + MQTTPublish(topicUptime, uptimeStr); + } + + if (topicFreeMem.length() > 0) { + char freeheapmem[11]; + sprintf(freeheapmem, "%zu", esp_get_free_heap_size()); + MQTTPublish(topicFreeMem, freeheapmem); + } + OldValue = result; return true; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h index 99035659..75c2fc1f 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h @@ -9,7 +9,7 @@ class ClassFlowMQTT : public ClassFlow { protected: - std::string uri, topic, topicError, clientname, topicRate, topicTimeStamp; + std::string uri, topic, topicError, clientname, topicRate, topicTimeStamp, topicUptime, topicFreeMem; std::string OldValue; ClassFlowPostProcessing* flowpostprocessing; std::string user, password; diff --git a/code/components/jomjol_tfliteclass/server_tflite.cpp b/code/components/jomjol_tfliteclass/server_tflite.cpp index cf4a0feb..0edea02b 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.cpp +++ b/code/components/jomjol_tfliteclass/server_tflite.cpp @@ -18,8 +18,9 @@ #include "ClassFlowControll.h" #include "ClassLogFile.h" +#include "server_main.h" -//#define DEBUG_DETAIL_ON +#define DEBUG_DETAIL_ON ClassFlowControll tfliteflow; @@ -68,9 +69,11 @@ void KillTFliteTasks() #ifdef DEBUG_DETAIL_ON printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow); #endif - if (xHandleblink_task_doFlow) + if (xHandleblink_task_doFlow != NULL) { - vTaskDelete(xHandleblink_task_doFlow); + TaskHandle_t xHandleblink_task_doFlowTmp = xHandleblink_task_doFlow; + xHandleblink_task_doFlow = NULL; + vTaskDelete(xHandleblink_task_doFlowTmp); #ifdef DEBUG_DETAIL_ON printf("Killed: xHandleblink_task_doFlow\n"); #endif @@ -79,9 +82,11 @@ void KillTFliteTasks() #ifdef DEBUG_DETAIL_ON printf("Handle: xHandletask_autodoFlow: %ld\n", (long) xHandletask_autodoFlow); #endif - if (xHandletask_autodoFlow) + if (xHandletask_autodoFlow != NULL) { - vTaskDelete(xHandletask_autodoFlow); + TaskHandle_t xHandletask_autodoFlowTmp = xHandletask_autodoFlow; + xHandletask_autodoFlow = NULL; + vTaskDelete(xHandletask_autodoFlowTmp); #ifdef DEBUG_DETAIL_ON printf("Killed: xHandletask_autodoFlow\n"); #endif @@ -538,16 +543,15 @@ void task_autodoFlow(void *pvParameter) printf("task_autodoFlow: start\r\n"); doInit(); - printf("-a-\r\n"); + gpio_handler_init(); + auto_isrunning = tfliteflow.isAutoStart(auto_intervall); - printf("-b-\r\n"); if (isSetupModusActive()) { auto_isrunning = false; std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT); tfliteflow.doFlowMakeImageOnly(zw_time); } - printf("-c-\r\n"); while (auto_isrunning) { std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds); @@ -590,7 +594,6 @@ void task_autodoFlow(void *pvParameter) vTaskDelay( xDelay ); } } - printf("-d-\r\n"); vTaskDelete(NULL); //Delete this task if it exits from the loop above xHandletask_autodoFlow = NULL; printf("task_autodoFlow: end\r\n"); diff --git a/code/components/jomjol_time_sntp/time_sntp.cpp b/code/components/jomjol_time_sntp/time_sntp.cpp index 4e7b769f..240a36d9 100644 --- a/code/components/jomjol_time_sntp/time_sntp.cpp +++ b/code/components/jomjol_time_sntp/time_sntp.cpp @@ -131,4 +131,12 @@ static void initialize_sntp(void) void setBootTime() { time(&bootTime); +} + +time_t getUpTime() +{ + time_t now; + time(&now); + + return now - bootTime; } \ No newline at end of file diff --git a/code/components/jomjol_time_sntp/time_sntp.h b/code/components/jomjol_time_sntp/time_sntp.h index 975c6056..c56e6c91 100644 --- a/code/components/jomjol_time_sntp/time_sntp.h +++ b/code/components/jomjol_time_sntp/time_sntp.h @@ -21,3 +21,4 @@ void setTimeZone(std::string _tzstring); void reset_servername(std::string _servername); void setBootTime(); +time_t getUpTime(); diff --git a/code/main/main.cpp b/code/main/main.cpp index c43ee16e..cbc2d550 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -3,7 +3,6 @@ #include "freertos/task.h" #include "freertos/event_groups.h" -#include "defines.h" #include "driver/gpio.h" #include "sdkconfig.h" @@ -20,6 +19,7 @@ #include "connect_wlan.h" #include "read_wlanini.h" +#include "server_main.h" #include "server_tflite.h" #include "server_file.h" #include "server_ota.h" @@ -38,7 +38,7 @@ static const char *TAGMAIN = "main"; -#define FLASH_GPIO GPIO_NUM_4 +//#define FLASH_GPIO GPIO_NUM_4 bool Init_NVS_SDCard() { @@ -107,9 +107,9 @@ bool Init_NVS_SDCard() // Init the GPIO // Flash ausschalten - gpio_pad_select_gpio(FLASH_GPIO); - gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT); - gpio_set_level(FLASH_GPIO, 0); + // gpio_pad_select_gpio(FLASH_GPIO); + // gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT); + // gpio_set_level(FLASH_GPIO, 0); return true; } @@ -138,7 +138,7 @@ void task_NoSDBlink(void *pvParameter) esp_err_t handler_gpio(httpd_req_t *req) { printf("freemem -3-: %u\n", esp_get_free_heap_size()); - gpioHandler->init(); + gpio_handler_init(); printf("freemem -4-: %u\n", esp_get_free_heap_size()); char resp_str [30]; @@ -219,14 +219,9 @@ extern "C" void app_main(void) camuri.user_ctx = (void*)server; httpd_register_uri_handler(server, &camuri); -#ifdef __SD_USE_ONE_LINE_MODE__ - printf("freemem -1-: %u\n", esp_get_free_heap_size()); - gpioHandler = new GpioHandler(CONFIG_FILE, server); - printf("freemem -2-: %u\n", esp_get_free_heap_size()); -#endif + gpio_handler_create(); printf("vor reg server main\n"); - register_server_main_uri(server, "/sdcard"); printf("vor dotautostart\n"); diff --git a/code/main/server_main.cpp b/code/main/server_main.cpp index 3c88b633..300f8c3e 100644 --- a/code/main/server_main.cpp +++ b/code/main/server_main.cpp @@ -2,6 +2,7 @@ #include +#include "defines.h" #include "server_help.h" #include "ClassLogFile.h" @@ -24,6 +25,8 @@ std::string starttime = ""; static const char *TAG_SERVERMAIN = "server-main"; +static GpioHandler *gpioHandler = NULL; + /* An HTTP GET handler */ esp_err_t info_get_handler(httpd_req_t *req) @@ -300,7 +303,9 @@ esp_err_t sysinfo_handler(httpd_req_t *req) std::string gitbranch = libfive_git_branch(); std::string gitbasebranch = git_base_branch(); std::string htmlversion = getHTMLversion(); - + char freeheapmem[11]; + sprintf(freeheapmem, "%zu", esp_get_free_heap_size()); + tcpip_adapter_ip_info_t ip_info; ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info)); const char *hostname; @@ -315,7 +320,8 @@ esp_err_t sysinfo_handler(httpd_req_t *req) \"html\" : \"" + htmlversion + "\",\ \"cputemp\" : \"" + cputemp + "\",\ \"hostname\" : \"" + hostname + "\",\ - \"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\"\ + \"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\",\ + \"freeHeapMem\" : \"" + freeheapmem + "\"\ }\ ]"; @@ -449,4 +455,34 @@ void connect_handler(void* arg, esp_event_base_t event_base, } } +void gpio_handler_create() +{ + if (gpioHandler == NULL) + gpioHandler = new GpioHandler(CONFIG_FILE, server); +} +void gpio_handler_init() +{ + if (gpioHandler != NULL) { + gpioHandler->init(); + } +} + +void gpio_handler_deinit() { + if (gpioHandler != NULL) { + gpioHandler->deinit(); + } +} + +void gpio_handler_destroy() +{ + if (gpioHandler != NULL) { + delete gpioHandler; + gpioHandler = NULL; + } +} + +GpioHandler* gpio_handler_get() +{ + return gpioHandler; +} diff --git a/code/main/server_main.h b/code/main/server_main.h index 8d92929d..ac43ee61 100644 --- a/code/main/server_main.h +++ b/code/main/server_main.h @@ -16,10 +16,15 @@ extern httpd_handle_t server; -static GpioHandler *gpioHandler = NULL; +void gpio_handler_create(); +void gpio_handler_init(); +void gpio_handler_deinit(); +void gpio_handler_destroy(); +GpioHandler* gpio_handler_get(); httpd_handle_t start_webserver(void); void register_server_main_uri(httpd_handle_t server, const char *base_path); + #endif diff --git a/code/main/version.cpp b/code/main/version.cpp index 22d1aea1..79c153d4 100644 --- a/code/main/version.cpp +++ b/code/main/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="d995c31"; +const char* GIT_REV="7b8f10a"; const char* GIT_TAG=""; const char* GIT_BRANCH="gpio-handler"; -const char* BUILD_TIME="2021-06-21 23:55"; \ No newline at end of file +const char* BUILD_TIME="2021-07-03 00:47"; \ No newline at end of file diff --git a/code/version.cpp b/code/version.cpp index 22d1aea1..a92ef974 100644 --- a/code/version.cpp +++ b/code/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="d995c31"; +const char* GIT_REV="7b8f10a"; const char* GIT_TAG=""; const char* GIT_BRANCH="gpio-handler"; -const char* BUILD_TIME="2021-06-21 23:55"; \ No newline at end of file +const char* BUILD_TIME="2021-07-03 00:46"; \ No newline at end of file diff --git a/firmware/bootloader.bin b/firmware/bootloader.bin index 941e0f74..1451c42e 100644 Binary files a/firmware/bootloader.bin and b/firmware/bootloader.bin differ diff --git a/firmware/firmware.bin b/firmware/firmware.bin index 88238056..737dba82 100644 Binary files a/firmware/firmware.bin and b/firmware/firmware.bin differ diff --git a/firmware/html.zip b/firmware/html.zip index f2a9bf14..3662fc19 100644 Binary files a/firmware/html.zip and b/firmware/html.zip differ diff --git a/sd-card/html/edit_config_param.html b/sd-card/html/edit_config_param.html index 5af2ca08..402baf49 100644 --- a/sd-card/html/edit_config_param.html +++ b/sd-card/html/edit_config_param.html @@ -574,7 +574,21 @@ textarea { - MQTT topic, ESP uptime of last flow + MQTT topic, ESP uptime after last flow + + + + + + + + TopicFreeMem + + + + + + MQTT topic, ESP free heap memory after last flow @@ -654,7 +668,12 @@ textarea { -

GPIO Settings

+ +

+ GPIO Settings + Enabling GPIO handler, disable by default integrated flash light. Please enable it with GPIO4 settings. +

+ @@ -671,6 +690,396 @@ textarea { MQTT main topic for GPIO + + + + + + + + GPIO 0 state + + + + + + + + GPIO 0 Usable with restrictions.
+ Must be disabled when camera is used.
+ Pin is used to activate flash mode and must therefore be HIGH when booting. + + + + + + GPIO 0 use interrupt + + + + + + + + GPIO 0 enable interrupt trigger + + + + + + GPIO 0 PWM duty resolution + + + + + + GPIO 0 LEDC PWM duty resolution in bit + + + + + + GPIO 0 enable MQTT + + + + + + GPIO 0 enable MQTT publishing/subscribing + + + + + + GPIO 0 enable HTTP + + + + + + GPIO 0 enable HTTP write/read + + + + + + GPIO 0 name + + + + + + GPIO 0 MQTT topic name (empty = GPIO0). Allowed characters (a-z, A-Z, 0-9, _, -) + + + + + + + + + + + GPIO 1 state + + + + + + + + GPIO 1
Used by default for serial communication as TX pin.
Required for seriales monitor.
+ + + + + + GPIO 1 use interrupt + + + + + + + + GPIO 1 enable interrupt trigger + + + + + + GPIO 1 PWM duty resolution + + + + + + GPIO 1 LEDC PWM duty resolution in bit + + + + + + GPIO 1 enable MQTT + + + + + + GPIO 1 enable MQTT publishing/subscribing + + + + + + GPIO 1 enable HTTP + + + + + + GPIO 1 enable HTTP write/read + + + + + + GPIO 1 name + + + + + + GPIO 1 MQTT topic name (empty = GPIO1). Allowed characters (a-z, A-Z, 0-9, _, -) + + + + + + + + + + + GPIO 3 state + + + + + + + + GPIO 3 Used by default for serial communication as RX pin. + + + + + + GPIO 3 use interrupt + + + + + + + + GPIO 3 Used by default for serial communication as RX pin. + + + + + + GPIO 3 PWM duty resolution + + + + + + GPIO 3 LEDC PWM duty resolution in bit + + + + + + GPIO 3 enable MQTT + + + + + + GPIO 3 enable MQTT publishing/subscribing + + + + + + GPIO 3 enable HTTP + + + + + + GPIO 3 enable HTTP write/read + + + + + + GPIO 3 name + + + + + + GPIO 3 MQTT topic name (empty = GPIO3). Allowed characters (a-z, A-Z, 0-9, _, -) + + + + + + + + + + + GPIO 4 state + + + + + + + + GPIO 4 Usable with restrictions.
+ Pin is used for build-in flash light. + + + + + + GPIO 4 use interrupt + + + + + + + + GPIO 4 enable interrupt trigger + + + + + + GPIO 4 PWM duty resolution + + + + + + GPIO 4 LEDC PWM duty resolution in bit + + + + + + GPIO 4 enable MQTT + + + + + + GPIO 4 enable MQTT publishing/subscribing + + + + + + GPIO 4 enable HTTP + + + + + + GPIO 4 enable HTTP write/read + + + + + + GPIO 4 name + + + + + + GPIO 4 MQTT topic name (empty = GPIO4). Allowed characters (a-z, A-Z, 0-9, _, -) + + + + + @@ -706,6 +1115,9 @@ textarea { + + + @@ -758,10 +1170,12 @@ textarea { - GPIO 12 MQTT topic name (empty = gpio12). Allowed characters (a-z, A-Z, 0-9, _, -) + GPIO 12 MQTT topic name (empty = GPIO12). Allowed characters (a-z, A-Z, 0-9, _, -) + + @@ -795,8 +1209,11 @@ textarea { @@ -849,9 +1266,10 @@ textarea { - GPIO 13 MQTT topic name (empty = gpio13). Allowed characters (a-z, A-Z, 0-9, _, -) + GPIO 13 MQTT topic name (empty = GPIO13). Allowed characters (a-z, A-Z, 0-9, _, -) +

Debug

@@ -1204,11 +1622,16 @@ function UpdateInput() { WriteParameter(param, category, "MQTT", "TopicRate", true); WriteParameter(param, category, "MQTT", "TopicTimeStamp", true); WriteParameter(param, category, "MQTT", "TopicUptime", true); + WriteParameter(param, category, "MQTT", "TopicFreeMem", true); WriteParameter(param, category, "MQTT", "ClientID", true); WriteParameter(param, category, "MQTT", "user", true); WriteParameter(param, category, "MQTT", "password", true); WriteParameter(param, category, "GPIO", "MainTopicMQTT", true); + WriteParameter(param, category, "GPIO", "IO0", true); + WriteParameter(param, category, "GPIO", "IO1", true); + WriteParameter(param, category, "GPIO", "IO3", true); + WriteParameter(param, category, "GPIO", "IO4", true); WriteParameter(param, category, "GPIO", "IO12", true); WriteParameter(param, category, "GPIO", "IO13", true); @@ -1269,11 +1692,16 @@ function ReadParameterAll() ReadParameter(param, "MQTT", "TopicRate", true); ReadParameter(param, "MQTT", "TopicTimeStamp", true); ReadParameter(param, "MQTT", "TopicUptime", true); + ReadParameter(param, "MQTT", "TopicFreeMem", true); ReadParameter(param, "MQTT", "ClientID", true); ReadParameter(param, "MQTT", "user", true); ReadParameter(param, "MQTT", "password", true); ReadParameter(param, "GPIO", "MainTopicMQTT", true); + ReadParameter(param, "GPIO", "IO0", true); + ReadParameter(param, "GPIO", "IO1", true); + ReadParameter(param, "GPIO", "IO3", true); + ReadParameter(param, "GPIO", "IO4", true); ReadParameter(param, "GPIO", "IO12", true); ReadParameter(param, "GPIO", "IO13", true); diff --git a/sd-card/html/gethost.js b/sd-card/html/gethost.js index 40a7c87a..0710aba1 100644 --- a/sd-card/html/gethost.js +++ b/sd-card/html/gethost.js @@ -5,11 +5,12 @@ function gethost_Version(){ function getbasepath(){ var host = window.location.hostname; - if ((host == "127.0.0.1") || (host == "localhost")) + if ((host == "127.0.0.1") || (host == "localhost") || (host == "")) { // host = "http://192.168.2.118"; // jomjol interner test // host = "http://192.168.178.26"; // jomjol interner test - host = "http://192.168.178.22"; // jomjol interner Real +// host = "http://192.168.178.22"; // jomjol interner Real + host = "http://192.168.43.191"; // host = "."; // jomjol interner localhost } diff --git a/sd-card/html/readconfigparam.js b/sd-card/html/readconfigparam.js index 9500b883..45ebb507 100644 --- a/sd-card/html/readconfigparam.js +++ b/sd-card/html/readconfigparam.js @@ -87,6 +87,7 @@ function ParseConfig() { ParamAddValue(param, catname, "TopicRate"); ParamAddValue(param, catname, "TopicTimeStamp"); ParamAddValue(param, catname, "TopicUptime", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]); + ParamAddValue(param, catname, "TopicFreeMem", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]); ParamAddValue(param, catname, "ClientID"); ParamAddValue(param, catname, "user"); ParamAddValue(param, catname, "password"); @@ -97,6 +98,10 @@ function ParseConfig() { category[catname]["found"] = false; param[catname] = new Object(); ParamAddValue(param, catname, "MainTopicMQTT", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]); + ParamAddValue(param, catname, "IO0", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]); + ParamAddValue(param, catname, "IO1", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]); + ParamAddValue(param, catname, "IO3", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]); + ParamAddValue(param, catname, "IO4", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]); ParamAddValue(param, catname, "IO12", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]); ParamAddValue(param, catname, "IO13", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);