diff --git a/firmware/Makefile b/firmware/Makefile index e7047ae..2f6546c 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -2,9 +2,6 @@ PROGRAM=fiatlux EXTRA_CFLAGS=-O3 -Ifsdata -#Enable debugging -#EXTRA_CFLAGS+=-DLWIP_DEBUG=1 -DHTTPD_DEBUG=LWIP_DBG_ON - EXTRA_COMPONENTS=extras/i2s_dma extras/ws2812_i2s extras/dhcpserver extras/mbedtls extras/httpd extras/sntp extras/cpp_support LIBS = hal m diff --git a/firmware/fsdata/fs/index.html b/firmware/fsdata/fs/index.html index 5f05ada..ad6aff1 100644 --- a/firmware/fsdata/fs/index.html +++ b/firmware/fsdata/fs/index.html @@ -7,9 +7,232 @@ -
-

static web page

+ +
+
+

Status

+
+
+
+
+

System

+
+
+
+ Chip ID + N/A +
+
+ Hostname + N/A +
+
+ Firmware Version + N/A +
+
+ Flash ID + N/A +
+
+ Flash size + N/A KiB +
+
+ Free heap + N/A bytes +
+
+ Uptime + N/A s +
+
+
+
+
+
+
+

Network current connection

+
+
+
+ Mode + N/A +
+
+ Station SSID + N/A +
+
+ Station IP + N/A +
+
+ Station MAC + N/A +
+
+ AP SSID + N/A +
+
+ AP IP + N/A +
+
+ AP MAC + N/A +
+
+
+
+
+
+
+

Power

+
+
+
+ Input + 5V12V +
+
+ Output + 11.2V +
+
+ +
+
+
+
+ + diff --git a/firmware/web.cpp b/firmware/web.cpp index ddfb577..f324bc8 100644 --- a/firmware/web.cpp +++ b/firmware/web.cpp @@ -23,11 +23,240 @@ extern "C" { #include } +#define vTaskDelayMs(ms) vTaskDelay((ms) / portTICK_PERIOD_MS) + +struct { + bool global; + bool connection; + bool wifi; +} has_changed; + +void websocket_task(void *pvParameter) { + auto *pcb = (struct tcp_pcb *) pvParameter; + + size_t connstarttime = xTaskGetTickCount(); + has_changed = {true, true, true}; + + for (;;) { + if(pcb == NULL || pcb->state != ESTABLISHED) { + printf("Connection closed, deleting task\n"); + break; + } + + //Global Info + if(has_changed.global) { + has_changed.global = false; + timeval tv; + gettimeofday(&tv, NULL); + int uptime = xTaskGetTickCount() * portTICK_PERIOD_MS / 1000; + int heap = (int) xPortGetFreeHeapSize(); + uint32_t chip_id = sdk_system_get_chip_id(); + uint32_t flash_id = sdk_spi_flash_get_id(); + uint32_t flash_size = sdk_flashchip.chip_size >> 10; + char *hostname = NULL; + + sysparam_get_string("hostname", &hostname); + /* Generate response in JSON format */ + char response[160]; + size_t len = snprintf(response, sizeof(response), + "{\"walltime\" : \"%d\"," + "\"uptime\" : \"%d\"," + " \"heap\" : \"%d\"," + " \"chipid\" : \"%08x\"," + " \"flashid\" : \"0x%08x\"," + " \"flashsize\" : \"%u\"," + " \"hostname\" : \"%s\"" + "}", (int) tv.tv_sec, uptime, heap, chip_id, flash_id, flash_size, hostname); + free(hostname); + if(len < sizeof(response)) { + LOCK_TCPIP_CORE(); + websocket_write(pcb, (unsigned char *) response, len, WS_TEXT_MODE); + UNLOCK_TCPIP_CORE(); + } else + printf("buffer too small 1"); + vTaskDelayMs(2000); + } + + //Connection Info + if(has_changed.connection) { + has_changed.connection = false; + timeval tv; + gettimeofday(&tv, NULL); + int connuptime = (xTaskGetTickCount() - connstarttime) * portTICK_PERIOD_MS / 1000; + + printf("conn %d: " + IPSTR + " <-> " + IPSTR + " \n", pcb->netif_idx, IP2STR(&pcb->local_ip), IP2STR(&pcb->remote_ip)); + char response[160]; + size_t len = snprintf(response, sizeof(response), + "{\"connage\" : \"%d\"," + "\"clientip\" : \"" + IPSTR + "\"" + "}", connuptime, IP2STR(&pcb->remote_ip)); + if(len < sizeof(response)) { + LOCK_TCPIP_CORE(); + websocket_write(pcb, (unsigned char *) response, len, WS_TEXT_MODE); + UNLOCK_TCPIP_CORE(); + } else + printf("buffer too small 1"); + vTaskDelayMs(2000); + } + + if(has_changed.wifi) { + has_changed.wifi = false; + uint8_t opmode = sdk_wifi_get_opmode(); + const char *opmode_str = "??"; + switch (opmode) { + case NULL_MODE: + opmode_str = "Null"; + break; + case STATION_MODE: + opmode_str = "Station"; + break; + case SOFTAP_MODE: + opmode_str = "SoftAP"; + break; + case STATIONAP_MODE: + opmode_str = "StationAP"; + break; + default: + break; + } + + + /*struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + if (getpeername(s, (struct sockaddr *)&addr, &addr_len) == 0) { + printf("peer\n"); + }*/ + + + if(opmode == SOFTAP_MODE || opmode == STATIONAP_MODE) { + uint8_t hwaddr[6]; + sdk_wifi_get_macaddr(SOFTAP_IF, hwaddr); + ip_info info; + sdk_wifi_get_ip_info(SOFTAP_IF, &info); + + char *apssid = NULL; + sysparam_get_string("wifi_ap_ssid", &apssid); + + /* Generate response in JSON format */ + char response[128]; + size_t len = snprintf(response, sizeof(response), + "{\"opmode\" : \"%s\"," + " \"apssid\" : \"%s\"," + " \"apip\" : \"" + IPSTR + "\"," + " \"apmac\" : \"" + MACSTR + "\"" + "}", opmode_str, apssid, IP2STR(&info.ip), MAC2STR(hwaddr)); + free(apssid); + if(len < sizeof(response)) { + LOCK_TCPIP_CORE(); + websocket_write(pcb, (unsigned char *) response, len, WS_TEXT_MODE); + UNLOCK_TCPIP_CORE(); + } else + printf("buffer too small 2"); + } + + vTaskDelayMs(2000); + + if(opmode == STATION_MODE || opmode == STATIONAP_MODE) { + uint8_t hwaddr[6]; + sdk_wifi_get_macaddr(STATION_IF, hwaddr); + ip_info info; + sdk_wifi_get_ip_info(STATION_IF, &info); + char *stassid = nullptr; + sysparam_get_string("wifi_sta_ssid", &stassid); + + /* Generate response in JSON format */ + char response[128]; + size_t len = snprintf(response, sizeof(response), + "{\"opmode\" : \"%s\"," + " \"stassid\" : \"%s\"," + " \"staip\" : \"" + IPSTR + "\"," + " \"stamac\" : \"" + MACSTR + "\"" + "}", opmode_str, stassid, IP2STR(&info.ip), MAC2STR(hwaddr)); + free(stassid); + if(len < sizeof(response)) { + LOCK_TCPIP_CORE(); + websocket_write(pcb, (unsigned char *) response, len, WS_TEXT_MODE); + UNLOCK_TCPIP_CORE(); + } else + printf("buffer too small 3"); + } + + } + + vTaskDelayMs(500); + { + uint8_t response[3]; + uint16_t val = 0; + val = sdk_system_adc_read(); + response[2] = (uint8_t) val; + response[1] = val >> 8; + response[0] = 'V'; + websocket_write(pcb, response, 3, WS_BIN_MODE); + } + vTaskDelayMs(500); + } + + vTaskDelete(NULL); +} + +/** + * This function is called when websocket frame is received. + * + * Note: this function is executed on TCP thread and should return as soon + * as possible. + */ +void websocket_cb(struct tcp_pcb *pcb, char *data, u16_t data_len, uint8_t mode) { + + uint8_t response[3]; + uint16_t val = 0; + char cmd = '0'; + + switch (data[0]) { + default: + printf("[websocket_callback]:\n%.*s\n", (int) data_len, (char *) data); + printf("Unknown command\n"); + val = 0; + break; + } + + response[2] = (uint8_t) val; + response[1] = val >> 8; + response[0] = cmd; + + websocket_write(pcb, response, 3, WS_BIN_MODE); +} + +/** + * This function is called when new websocket is open and + * creates a new websocket_task if requested URI equals '/stream'. + */ +void websocket_open_cb(struct tcp_pcb *pcb, const char *uri) { + printf("WS URI: %s\n", uri); + if(!strcmp(uri, "/stream")) { + xTaskCreate(&websocket_task, "websocket_task", 512, (void *) pcb, 3, nullptr); + } +} extern "C" [[noreturn]] void httpd_task(void *pvParameters) { while(!uxSemaphoreGetCount( wifi_available_semaphore )) vTaskDelay(500 / portTICK_PERIOD_MS); + + websocket_register_callbacks((tWsOpenHandler) websocket_open_cb, (tWsHandler) websocket_cb); httpd_init(); for (;;) diff --git a/pcb/.gitignore b/pcb/.gitignore index 2043655..b2abd3a 100644 --- a/pcb/.gitignore +++ b/pcb/.gitignore @@ -31,5 +31,6 @@ fp-info-cache *.wrl *.step +*-bak gen/ gen.zip