diff --git a/README.md b/README.md index 2ef2e93..afb4982 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ CMD> You can examine the currently loaded script using the "show script" command. It only displays about 1KB of a script. If you need to see more, use "show script " with a higher starting line. Newly loaded scripts are stored persistently in flash and will be executed after next reset if they contain no syntax errors. "script delete" stops script execution and deleted a script from flash. # NTP Support -NTP time is supported and timestamps are only available if the sync with an NTP server is done. By default the NTP client is enabled and set to "1.pool.ntp.org". It can be changed by setting the config parameter "ntp_server" to a hostname or an IP address. An ntp_server of "none" will disable the NTP client. Also you can set the "ntp_timezone" to an offset from GMT in hours. The system time will be synced with the NTP server every "ntp_interval" seconds. Here it uses NOT the full NTP calculation and clock drift compensation. Instead it will just set the local time to the latest received time. +NTP time is supported and accurate timestamps are available if the sync with an NTP server is done. By default the NTP client is enabled and set to "1.pool.ntp.org". It can be changed by setting the config parameter "ntp_server" to a hostname or an IP address. An ntp_server of "none" will disable the NTP client. Also you can set the "ntp_timezone" to an offset from GMT in hours. The system time will be synced with the NTP server every "ntp_interval" seconds. Here it uses NOT the full NTP calculation and clock drift compensation. Instead it will just set the local time to the latest received time. After NTP sync has been completed successfully once, the local time will be published every second under the topic "$SYS/broker/time" in the format "hh:mm:ss". You can also query the NTP time using the "time" command from the commandline. @@ -180,6 +180,10 @@ After NTP sync has been completed successfully once, the local time will be publ - set ntp_timezone _tz_: sets the timezone in hours offset (default 0) - time: prints the current time as ddd hh:mm:ss +If you don't have internet access but still need a time base e.g. for your script, you can set the time manually (be aware that the local timer of the ESP has a significant drift): +- set ntp_time _hh:mm:ss_: sets the NTP time manually +- set ntp_weekday _ddd_: sets the current day of week ("Mon"-"Sun") + # mDNS mDNS is supported and depending on "mdns_mode" the broker responds on the name "mqtt.local" with one of its two addresses: diff --git a/driver/new_uart.c b/driver/new_uart.c index 5f8b373..55bd4de 100644 --- a/driver/new_uart.c +++ b/driver/new_uart.c @@ -229,6 +229,8 @@ int UART_Recv(uint8 uart_no, char *buffer, int max_buf_len) int ICACHE_FLASH_ATTR UART_Echo(uint8 echo) { echo_on = echo; + + return echo_on; } int UART_Send(uint8 uart_no, char *buffer, int len) @@ -242,6 +244,8 @@ int UART_Send(uint8 uart_no, char *buffer, int len) ch = *(buffer+index); uart_tx_one_char(uart_no, ch); } + + return index; } /*---------------------------------------------------------------------------* diff --git a/firmware/0x00000.bin b/firmware/0x00000.bin index c88f1b8..a7c2c1a 100644 Binary files a/firmware/0x00000.bin and b/firmware/0x00000.bin differ diff --git a/firmware/0x10000.bin b/firmware/0x10000.bin index 83ce99e..0206037 100644 Binary files a/firmware/0x10000.bin and b/firmware/0x10000.bin differ diff --git a/firmware/sha1sums b/firmware/sha1sums index cc2b8fe..cfb3cd8 100644 --- a/firmware/sha1sums +++ b/firmware/sha1sums @@ -1,2 +1,2 @@ -50ff56396a7bdcab8899a4412446d3016a0cdc2c 0x00000.bin -49774bfdcd7aefcde4fd64ac377e1588ad4b8219 0x10000.bin +1ca55cabb786b24fd4683839ce8d226f35d822c1 0x00000.bin +290bdf2cf693375094de994ca9d5dfaa29d448f0 0x10000.bin diff --git a/ntp/ntp.c b/ntp/ntp.c index bfee7d7..2cd66e1 100644 --- a/ntp/ntp.c +++ b/ntp/ntp.c @@ -45,9 +45,9 @@ uint8_t *ICACHE_FLASH_ATTR get_timestr() { } +static uint8_t *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; uint8_t *ICACHE_FLASH_ATTR get_weekday() { struct timeval tv; - static uint8_t *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; get_cur_time(&tv); tv.tv_sec += ntp_timezone * 3600; @@ -183,3 +183,29 @@ void ICACHE_FLASH_ATTR ntp_get_time() { espconn_regist_recvcb(pCon, ntp_udp_recv); espconn_sent(pCon, (uint8 *) & ntp, sizeof(ntp_t)); } + +void ICACHE_FLASH_ATTR set_time_local(uint16_t h, uint16_t m, uint16_t s) { + + // get the according sys_time; + t_offset = get_long_systime(); + + t_tv.tv_sec -= t_tv.tv_sec % (3600 * 24); + t_tv.tv_sec += (h%24)*3600 + (m%60)*60 + s%60; + t_tv.tv_usec = 0; +} + +bool ICACHE_FLASH_ATTR set_weekday_local(char *day) { + int i; + + for (i = 0; i<7; i++) { + if (os_strcmp(day, days[i]) == 0) + break; + } + if (i>=7) + return false; + + t_tv.tv_sec = t_tv.tv_sec % (3600 * 24); + t_tv.tv_sec += (7 + i-3) * (3600 * 24); + + return true; +} diff --git a/ntp/ntp.h b/ntp/ntp.h index c934efb..803ef0d 100644 --- a/ntp/ntp.h +++ b/ntp/ntp.h @@ -26,4 +26,7 @@ void set_timezone(int16_t timezone); uint8_t *get_timestr(); uint8_t *get_weekday(); +void set_time_local(uint16_t h, uint16_t m, uint16_t s); +bool set_weekday_local(char *day); + #endif diff --git a/user/cli.c b/user/cli.c index f603a34..32f4821 100644 --- a/user/cli.c +++ b/user/cli.c @@ -173,7 +173,7 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn) { #endif #endif #ifdef NTP - os_sprintf_flash(response, "time\r\nset [ntp_server|ntp_interval|ntp_timezone] \r\n"); + os_sprintf_flash(response, "time\r\nset [ntp_server|ntp_interval|ntp_timezone|ntp_time|ntp_weekday] \r\n"); to_console(response); #endif #ifdef MQTT_CLIENT @@ -189,6 +189,9 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn) { ip_addr_t i_ip; if (nTokens == 1 || (nTokens == 2 && strcmp(tokens[1], "config") == 0)) { + os_sprintf(response, "Version %s (build: %s)\r\n", ESP_UBROKER_VERSION, __TIMESTAMP__); + to_console(response); + os_sprintf(response, "STA: SSID:%s PW:%s%s\r\n", config.ssid, config.locked ? "***" : (char *)config.password, config.auto_connect ? "" : " [AutoConnect:0]"); @@ -296,7 +299,7 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn) { os_sprintf(response, "Free mem: %d\r\n", system_get_free_heap_size()); to_console(response); #ifdef SCRIPTED - os_sprintf(response, "Interpreter loop: %d us\r\n", loop_time); + os_sprintf(response, "Interpreter loop: %d (%d us)\r\n", loop_count, loop_time); to_console(response); #endif if (connected) { @@ -1001,6 +1004,27 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn) { os_sprintf(response, "NTP timezone set to %d h\r\n", config.ntp_timezone); goto command_handled; } + + if (strcmp(tokens[1], "ntp_time") == 0) { + if (strlen(tokens[2]) != 8 || tokens[2][2] != ':' || tokens[2][5] != ':') { + os_sprintf_flash(response, "Time format hh:mm:ss\r\n"); + goto command_handled; + } + tokens[2][2] = '\0'; + tokens[2][5] = '\0'; + set_time_local(atoi(tokens[2]), atoi(&tokens[2][3]), atoi(&tokens[2][6])); + os_sprintf(response, "Time set to %s \r\n", get_timestr()); + goto command_handled; + } + + if (strcmp(tokens[1], "ntp_weekday") == 0) { + if (set_weekday_local(tokens[2])) { + os_sprintf(response, "Weekday set to %s\r\n", get_weekday()); + } else { + os_sprintf_flash(response, "Set weekday failed\r\n"); + } + goto command_handled; + } #endif #ifdef MQTT_CLIENT if (strcmp(tokens[1], "mqtt_host") == 0) { diff --git a/user/config_flash.c b/user/config_flash.c index 363c105..d43c7fe 100644 --- a/user/config_flash.c +++ b/user/config_flash.c @@ -7,7 +7,7 @@ * time at least. When you want to change some data in flash, you have to * erase the whole sector, and then write it back with the new data. *--------------------------------------------------------------------------*/ -void config_load_default(sysconfig_p config) { +void ICACHE_FLASH_ATTR config_load_default(sysconfig_p config) { uint8_t mac[6]; os_memset(config, 0, sizeof(sysconfig_t)); @@ -70,7 +70,7 @@ void config_load_default(sysconfig_p config) { #endif } -int config_load(sysconfig_p config) { +int ICACHE_FLASH_ATTR config_load(sysconfig_p config) { if (config == NULL) return -1; uint16_t base_address = FLASH_BLOCK_NO; @@ -95,25 +95,25 @@ int config_load(sysconfig_p config) { return 0; } -void config_save(sysconfig_p config) { +void ICACHE_FLASH_ATTR config_save(sysconfig_p config) { uint16_t base_address = FLASH_BLOCK_NO; os_printf("Saving configuration\r\n"); spi_flash_erase_sector(base_address); spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32 *) config, sizeof(sysconfig_t)); } -void blob_save(uint8_t blob_no, uint32_t * data, uint16_t len) { +void ICACHE_FLASH_ATTR blob_save(uint8_t blob_no, uint32_t * data, uint16_t len) { uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no; spi_flash_erase_sector(base_address); spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, data, len); } -void blob_load(uint8_t blob_no, uint32_t * data, uint16_t len) { +void ICACHE_FLASH_ATTR blob_load(uint8_t blob_no, uint32_t * data, uint16_t len) { uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no; spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, data, len); } -void blob_zero(uint8_t blob_no, uint16_t len) { +void ICACHE_FLASH_ATTR blob_zero(uint8_t blob_no, uint16_t len) { int i; uint8_t z[len]; os_memset(z, 0, len); diff --git a/user/json_path.c b/user/json_path.c index a2f8cfb..a2c5ae4 100644 --- a/user/json_path.c +++ b/user/json_path.c @@ -13,7 +13,7 @@ bool ICACHE_FLASH_ATTR find_next_pair(struct jsonparse_state *state, char *name, int json_type; //os_printf ("name: %s level: %d\r\n", name, level); - while(json_type = jsonparse_next(state)) { + while((json_type = jsonparse_next(state))) { //os_printf ("json_type: %d json_level: %d\r\n", json_type, state->depth); if (state->depth < level-1) return false; @@ -87,7 +87,7 @@ void ICACHE_FLASH_ATTR json_path(char *json, char *path, char *buf, int *buf_siz } level -= 2; - while (json_type = jsonparse_next(&state)) { + while ((json_type = jsonparse_next(&state))) { //os_printf ("level: %d json_type: %d json_level: %d\r\n", level, json_type, state.depth); if (state.depth < level) { *buf_size = 0; diff --git a/user/lang.c b/user/lang.c index 0fdc373..00e3ec3 100644 --- a/user/lang.c +++ b/user/lang.c @@ -494,6 +494,7 @@ int ICACHE_FLASH_ATTR parse_statement(int next_token) { } } + loop_count++; lang_debug("Interpreter loop: %d us\r\n", (system_get_time()-start)); if (interpreter_status == INIT) loop_time = system_get_time()-start; @@ -823,7 +824,7 @@ int ICACHE_FLASH_ATTR parse_action(int next_token, bool doit) { } else if (is_token(next_token, "if")) { - uint32_t if_val; + uint32_t if_val = 0; char *if_char; int if_len; Value_Type if_type; diff --git a/user/lang.h b/user/lang.h index 36dc991..eedf627 100644 --- a/user/lang.h +++ b/user/lang.h @@ -22,6 +22,7 @@ extern bool lang_logging; uint8_t tmp_buffer[128]; uint32_t loop_time; +uint32_t loop_count; int text_into_tokens(char *str); void free_tokens(void); diff --git a/user/user_config.h b/user/user_config.h index 768a5ee..d21be97 100644 --- a/user/user_config.h +++ b/user/user_config.h @@ -1,6 +1,8 @@ #ifndef _USER_CONFIG_ #define _USER_CONFIG_ +#define ESP_UBROKER_VERSION "V2.0.1" + #define WIFI_SSID "ssid" #define WIFI_PASSWORD "password" diff --git a/user/user_main.c b/user/user_main.c index 36674b7..9fdff29 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -299,6 +299,7 @@ void ICACHE_FLASH_ATTR serial_out(uint8_t *str) { bool ICACHE_FLASH_ATTR delete_retainedtopics() { clear_retainedtopics(); blob_zero(RETAINED_SLOT, MAX_RETAINED_LEN); + return true; } bool ICACHE_FLASH_ATTR save_retainedtopics() { @@ -770,7 +771,7 @@ void user_init() { // Temporarily initialize the UART with 115200 UART_init_console(BIT_RATE_115200, 0, console_rx_buffer, console_tx_buffer); - os_printf("\r\n\r\nWiFi Router/MQTT Broker V2.0 starting\r\n"); + os_printf("\r\n\r\nuMQTT Broker %s starting\r\n", ESP_UBROKER_VERSION); // Load config int config_res = config_load(&config); @@ -781,6 +782,7 @@ void user_init() { } #ifdef SCRIPTED + loop_count = loop_time = 0; script_enabled = false; if ((config_res == 0) && read_script()) { if (interpreter_syntax_check() != -1) {