diff --git a/README.md b/README.md index fe0edcd..79a6fc0 100644 --- a/README.md +++ b/README.md @@ -54,19 +54,19 @@ SoftwareSerial | ❌ | ❌ SPI | ❌ | ❌ Wire | ❗ | ❌ **OTHER LIBRARIES** | | -Wi-Fi STA/AP/Mixed | ✔️ | ❌ +Wi-Fi STA/AP/Mixed | ✔️ | ❗/❌/❌ Wi-Fi Events | ✔️ | ❌ -TCP Client (SSL) | ✔️ (✔️) | ❌ -TCP Server | ✔️ | ❌ +TCP Client (SSL) | ✔️ (✔️) | ❓ +TCP Server | ✔️ | ❓ IPv6 | ❌ | ❌ -HTTP Client (SSL) | ✔️ (✔️) | ❌ -HTTP Server | ✔️ | ❌ +HTTP Client (SSL) | ✔️ (✔️) | ❓ +HTTP Server | ✔️ | ❓ NVS / Preferences | ❌ | ❌ SPIFFS | ❌ | ❌ BLE | - | ❌ NTP | ❌ | ❌ OTA | ✔️ | ❌ -MDNS | ✔️ | ❌ +MDNS | ✔️ | ❓ MQTT | ✅ | ❌ SD | ❌ | ❌ diff --git a/arduino/beken-72xx/libraries/WiFi/WiFi.cpp b/arduino/beken-72xx/libraries/WiFi/WiFi.cpp index 424f44a..b88a652 100644 --- a/arduino/beken-72xx/libraries/WiFi/WiFi.cpp +++ b/arduino/beken-72xx/libraries/WiFi/WiFi.cpp @@ -10,6 +10,29 @@ WiFiClass::~WiFiClass() { vSemaphoreDelete(data.scanSem); } +WiFiStatus eventTypeToStatus(uint8_t type) { + // rw_msg_pub.h:9 + switch (type) { + case RW_EVT_STA_IDLE: + return WL_IDLE_STATUS; + return WL_NO_SSID_AVAIL; + case RW_EVT_STA_CONNECTING: + case RW_EVT_STA_CONNECTED: + return WL_SCAN_COMPLETED; + case RW_EVT_STA_GOT_IP: + return WL_CONNECTED; + case RW_EVT_STA_PASSWORD_WRONG: + case RW_EVT_STA_NO_AP_FOUND: + case RW_EVT_STA_ASSOC_FULL: + case RW_EVT_STA_CONNECT_FAILED: + return WL_CONNECT_FAILED; + case RW_EVT_STA_BEACON_LOSE: + return WL_CONNECTION_LOST; + case RW_EVT_STA_DISCONNECTED: + return WL_DISCONNECTED; + } +} + WiFiAuthMode securityTypeToAuthMode(uint8_t type) { // wlan_ui_pub.h:62 switch (type) { diff --git a/arduino/beken-72xx/libraries/WiFi/WiFi.h b/arduino/beken-72xx/libraries/WiFi/WiFi.h index 17b0c8f..8d5fcad 100644 --- a/arduino/beken-72xx/libraries/WiFi/WiFi.h +++ b/arduino/beken-72xx/libraries/WiFi/WiFi.h @@ -4,3 +4,7 @@ #include #include + +#include "WiFiClient.h" +#include "WiFiClientSecure.h" +#include "WiFiServer.h" diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiClient.h b/arduino/beken-72xx/libraries/WiFi/WiFiClient.h new file mode 100644 index 0000000..eb27361 --- /dev/null +++ b/arduino/beken-72xx/libraries/WiFi/WiFiClient.h @@ -0,0 +1,8 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */ + +#pragma once + +#include +#include + +typedef LwIPClient WiFiClient; diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiClientSecure.h b/arduino/beken-72xx/libraries/WiFi/WiFiClientSecure.h new file mode 100644 index 0000000..3addedf --- /dev/null +++ b/arduino/beken-72xx/libraries/WiFi/WiFiClientSecure.h @@ -0,0 +1,8 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-05-04. */ + +#pragma once + +#include +#include + +typedef MbedTLSClient WiFiClientSecure; diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiData.h b/arduino/beken-72xx/libraries/WiFi/WiFiData.h index 57b688e..e928862 100644 --- a/arduino/beken-72xx/libraries/WiFi/WiFiData.h +++ b/arduino/beken-72xx/libraries/WiFi/WiFiData.h @@ -12,5 +12,11 @@ extern "C" { } // extern "C" typedef struct { + char ssid[32 + 1]; + char pass[64 + 1]; + uint32_t ipSta[4]; + uint32_t ipAp[4]; SemaphoreHandle_t scanSem; + void *statusIp; + void *statusLink; } WiFiData; diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp b/arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp index 5302079..758e729 100644 --- a/arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp +++ b/arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp @@ -5,6 +5,11 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) { __wrap_bk_printf_disable(); + if (mode && !data.statusIp) { + data.statusIp = (IPStatusTypedef *)malloc(sizeof(IPStatusTypedef)); + data.statusLink = (LinkStatusTypeDef *)malloc(sizeof(LinkStatusTypeDef)); + } + if (!__bk_rf_is_init) { LT_D_WG("Initializing func&app"); func_init_extended(); @@ -32,6 +37,13 @@ bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) { bk_wlan_stop(BK_SOFT_AP); } + if (!mode) { + free(data.statusIp); + free(data.statusLink); + data.statusIp = NULL; + data.statusLink = NULL; + } + LT_HEAP_I(); __wrap_bk_printf_enable(); @@ -46,10 +58,16 @@ WiFiMode WiFiClass::getMode() { } WiFiStatus WiFiClass::status() { - // wpa_suppliant_ctrl_get_wpas()->disconnected; - if (wpas_connect_ssid && wpas_connect_ssid->ssid_len) { - return WL_CONNECTED; - } else { - return WL_DISCONNECTED; - } + auto status = mhdr_get_station_status(); + LT_D_WG("mhdr_get_station_status()=%d", status); + return eventTypeToStatus(status); +} + +IPAddress WiFiClass::hostByName(const char *hostname) { + ip_addr_t ip; + int ret = netconn_gethostbyname(hostname, &ip); + if (ret == ERR_OK) { + return ip.addr; + } + return IPAddress(); } diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiPriv.h b/arduino/beken-72xx/libraries/WiFi/WiFiPriv.h index 88f5139..5c97724 100644 --- a/arduino/beken-72xx/libraries/WiFi/WiFiPriv.h +++ b/arduino/beken-72xx/libraries/WiFi/WiFiPriv.h @@ -2,14 +2,19 @@ #pragma once -#include "WiFi.h" +#include extern "C" { +#include +#include +#include + #include #include #include +#include #include #include #include @@ -23,6 +28,10 @@ extern void bk_wlan_ap_init(network_InitTypeDef_st *inNetworkInitPara); // func/hostapd-2.5/wpa_supplicant/main_supplicant.c extern struct wpa_ssid_value *wpas_connect_ssid; +// func/lwip_intf/lwip-2.0.2/port/net.c +extern struct netif *net_get_sta_handle(void); +extern struct netif *net_get_uap_handle(void); + // app/param_config.c extern general_param_t *g_wlan_general_param; extern ap_param_t *g_ap_param_ptr; @@ -30,6 +39,19 @@ extern sta_param_t *g_sta_param_ptr; extern uint8_t system_mac[6]; // WiFi.cpp +WiFiStatus eventTypeToStatus(uint8_t type); WiFiAuthMode securityTypeToAuthMode(uint8_t type); +#define ADDR_STA_IP data.ipSta[0] +#define ADDR_STA_MASK data.ipSta[1] +#define ADDR_STA_GW data.ipSta[2] +#define ADDR_STA_DNS data.ipSta[3] +#define ADDR_AP_IP data.ipAp[0] +#define ADDR_AP_MASK data.ipAp[1] +#define ADDR_AP_GW data.ipAp[2] +#define ADDR_AP_DNS data.ipAp[3] + +#define IP_STATUS ((IPStatusTypedef *)data.statusIp) +#define LINK_STATUS ((LinkStatusTypeDef *)data.statusLink) + } // extern "C" diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiSTA.cpp b/arduino/beken-72xx/libraries/WiFi/WiFiSTA.cpp new file mode 100644 index 0000000..231c24a --- /dev/null +++ b/arduino/beken-72xx/libraries/WiFi/WiFiSTA.cpp @@ -0,0 +1,209 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */ + +#include "WiFiPriv.h" + +WiFiStatus +WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) { + enableSTA(true); + + if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) { + LT_W("SSID not specified or too long"); + return WL_CONNECT_FAILED; + } + + if (passphrase && strlen(passphrase) > 64) { + LT_W("Passphrase too long"); + return WL_CONNECT_FAILED; + } + + // store the network data for later + strcpy(data.ssid, ssid); + if (passphrase) + strcpy(data.pass, passphrase); + else + data.pass[0] = 0; + + if (reconnect(bssid)) + return WL_CONNECTED; + + return WL_CONNECT_FAILED; +} + +bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) { + ADDR_STA_IP = (uint32_t)localIP; + ADDR_STA_GW = (uint32_t)gateway; + ADDR_STA_MASK = (uint32_t)subnet; + ADDR_STA_DNS = (uint32_t)dns1; + + if (status() == WL_CONNECTED) { + IPStatusTypedef config; + config.dhcp = !localIP[0]; + if (localIP) { + sprintf(config.ip, "%u.%u.%u.%u", ADDR_STA_IP); + sprintf(config.mask, "%u.%u.%u.%u", ADDR_STA_MASK); + sprintf(config.gate, "%u.%u.%u.%u", ADDR_STA_GW); + } + if (dns1) + sprintf(config.dns, "%u.%u.%u.%u", ADDR_STA_DNS); + bk_wlan_set_ip_status(&config, BK_STATION); + } + return true; +} + +bool WiFiClass::reconnect(const uint8_t *bssid) { + if (!bssid && !data.ssid[0]) { + LT_E("(B)SSID not specified"); + goto error; + } + + LT_D_WG("Connecting to " MACSTR, MAC2STR(bssid)); + + network_InitTypeDef_st config; + memset(&config, 0, sizeof(network_InitTypeDef_st)); + // network_InitTypeDef_adv_st config; + // memset(&config, 0, sizeof(network_InitTypeDef_adv_st)); + + config.wifi_mode = BK_STATION; + config.wifi_retry_interval = 100; + // config.ap_info.security = BK_SECURITY_TYPE_WPA2_MIXED; + // config.ap_info.channel = 6; + strcpy(config.wifi_ssid, data.ssid); + // strcpy(config.ap_info.ssid, data.ssid); + strcpy(config.wifi_key, data.pass); + // strcpy(config.key, data.pass); + // config.key_len = strlen(data.pass); + if (bssid) + memcpy(config.wifi_bssid, bssid, 6); + // memcpy(config.ap_info.bssid, bssid, 6); + + if (ADDR_STA_IP && ADDR_STA_MASK && ADDR_STA_GW) { + config.dhcp_mode = DHCP_DISABLE; + sprintf(config.local_ip_addr, "%u.%u.%u.%u", ADDR_STA_IP); + sprintf(config.net_mask, "%u.%u.%u.%u", ADDR_STA_MASK); + sprintf(config.gateway_ip_addr, "%u.%u.%u.%u", ADDR_STA_GW); + LT_D_WG("Static IP: %s / %s / %s", config.local_ip_addr, config.net_mask, config.gateway_ip_addr); + } else { + config.dhcp_mode = DHCP_CLIENT; + LT_D_WG("Using DHCP"); + } + + if (ADDR_STA_DNS) { + sprintf(config.dns_server_ip_addr, "%u.%u.%u.%u", ADDR_STA_DNS); + LT_D_WG("Static DNS: %s", config.dns_server_ip_addr); + } + + LT_D_WG("Starting WiFi..."); + bk_wlan_start_sta(&config); + LT_D_WG("bk_wlan_start() OK"); + return true; + +error: + return false; +} + +bool WiFiClass::disconnect(bool wifiOff) { + bk_wlan_connection_loss(); + return true; +} + +bool WiFiClass::setAutoReconnect(bool autoReconnect) { + return false; +} + +bool WiFiClass::getAutoReconnect() { + return false; +} + +IPAddress WiFiClass::localIP() { + IPStatusTypedef config; + bk_wlan_get_ip_status(&config, BK_STATION); + IPAddress ip; + ip.fromString(config.ip); + return ip; +} + +IPAddress WiFiClass::subnetMask() { + IPStatusTypedef config; + bk_wlan_get_ip_status(&config, BK_STATION); + IPAddress ip; + ip.fromString(config.mask); + return ip; +} + +IPAddress WiFiClass::gatewayIP() { + IPStatusTypedef config; + bk_wlan_get_ip_status(&config, BK_STATION); + IPAddress ip; + ip.fromString(config.gate); + return ip; +} + +IPAddress WiFiClass::dnsIP(uint8_t dns_no) { + IPStatusTypedef config; + bk_wlan_get_ip_status(&config, BK_STATION); + IPAddress ip; + ip.fromString(config.dns); + return ip; +} + +IPAddress WiFiClass::broadcastIP() { + return calculateBroadcast(localIP(), subnetMask()); +} + +const char *WiFiClass::getHostname() { + struct netif *ifs = net_get_sta_handle(); + return netif_get_hostname(ifs); +} + +bool WiFiClass::setHostname(const char *hostname) { + struct netif *ifs = net_get_sta_handle(); + netif_set_hostname(ifs, (char *)hostname); + return true; +} + +uint8_t *WiFiClass::macAddress(uint8_t *mac) { + wifi_get_mac_address((char *)mac, CONFIG_ROLE_STA); + return mac; +} + +bool WiFiClass::setMacAddress(const uint8_t *mac) { + wifi_set_mac_address((char *)mac); + return true; +} + +const String WiFiClass::SSID() { + if (!isConnected() || !wpas_connect_ssid) + return ""; + return (char *)wpas_connect_ssid->ssid; +} + +const String WiFiClass::psk() { + if (!isConnected()) + return ""; + struct wpa_supplicant *wpas = wpa_suppliant_ctrl_get_wpas(); + if (!wpas || !wpas->conf || !wpas->conf->ssid) + return ""; + return (char *)wpas->conf->ssid->passphrase; +} + +uint8_t *WiFiClass::BSSID() { + if (!isConnected()) + return NULL; + bk_wlan_get_link_status(LINK_STATUS); + return LINK_STATUS->bssid; +} + +int32_t WiFiClass::channel() { + bk_wlan_get_link_status(LINK_STATUS); + return LINK_STATUS->channel; +} + +int8_t WiFiClass::RSSI() { + bk_wlan_get_link_status(LINK_STATUS); + return LINK_STATUS->wifi_strength; +} + +WiFiAuthMode WiFiClass::getEncryption() { + bk_wlan_get_link_status(LINK_STATUS); + return securityTypeToAuthMode(LINK_STATUS->security); +} diff --git a/arduino/beken-72xx/libraries/WiFi/WiFiServer.h b/arduino/beken-72xx/libraries/WiFi/WiFiServer.h new file mode 100644 index 0000000..db8df0b --- /dev/null +++ b/arduino/beken-72xx/libraries/WiFi/WiFiServer.h @@ -0,0 +1,8 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */ + +#pragma once + +#include +#include + +typedef LwIPServer WiFiServer; diff --git a/arduino/libretuya/api/WiFi/WiFi.h b/arduino/libretuya/api/WiFi/WiFi.h index a09b6b6..e26ddfb 100644 --- a/arduino/libretuya/api/WiFi/WiFi.h +++ b/arduino/libretuya/api/WiFi/WiFi.h @@ -48,7 +48,6 @@ class WiFiClass { void printDiag(Print &dest); public: /* WiFiGeneric.cpp */ - int32_t channel(void); bool mode(WiFiMode mode); bool modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap); WiFiMode getMode(); @@ -135,6 +134,7 @@ class WiFiClass { const String psk(); uint8_t *BSSID(); String BSSIDstr(); + int32_t channel(); int8_t RSSI(); WiFiAuthMode getEncryption(); diff --git a/builder/frameworks/beken-72xx-arduino.py b/builder/frameworks/beken-72xx-arduino.py index 2a88972..1084561 100644 --- a/builder/frameworks/beken-72xx-arduino.py +++ b/builder/frameworks/beken-72xx-arduino.py @@ -23,6 +23,10 @@ env.Append( "-Wno-missing-braces", "-Wno-attributes", ], + CPPDEFINES=[ + # LibreTuya configuration + ("LT_ARD_HAS_WIFI", "1"), + ], LINKFLAGS=[ # stdio wrappers (port/printf/printf.c) "-Wl,-wrap,bk_printf", diff --git a/builder/frameworks/beken-72xx-sdk.py b/builder/frameworks/beken-72xx-sdk.py index f48d505..1e943f0 100644 --- a/builder/frameworks/beken-72xx-sdk.py +++ b/builder/frameworks/beken-72xx-sdk.py @@ -66,7 +66,10 @@ env.Append( ], CPPDEFINES=[ # LibreTuya configuration - # (reserved) + ("LT_HAS_LWIP", "1"), + ("LT_HAS_LWIP2", "1"), + ("LT_HAS_FREERTOS", "1"), + ("LT_HAS_MBEDTLS", "1"), # SDK options ("CFG_OS_FREERTOS", "1"), ("MBEDTLS_CONFIG_FILE", ""), diff --git a/platform/beken-72xx/fixups/inc/lwipopts.h b/platform/beken-72xx/fixups/inc/lwipopts.h new file mode 100644 index 0000000..2d98583 --- /dev/null +++ b/platform/beken-72xx/fixups/inc/lwipopts.h @@ -0,0 +1,7 @@ +/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */ + +#pragma once + +#include_next "lwipopts.h" + +#define LWIP_MDNS_RESPONDER 1