diff --git a/cmd/cmd.c b/cmd/cmd.c index 4a8dc64..0c90b4c 100644 --- a/cmd/cmd.c +++ b/cmd/cmd.c @@ -41,7 +41,7 @@ static uint16_t resp_crc; // Start a response, returns the partial CRC void ICACHE_FLASH_ATTR cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc) { - DBG("cmdResponse: cmd=%d val=%d argc=%d\n", cmd, value, argc); + // DBG("cmdResponse: cmd=%d val=%d argc=%d\n", cmd, value, argc); uart0_write_char(SLIP_END); cmdProtoWriteBuf((uint8_t*)&cmd, 2); diff --git a/cmd/cmd.h b/cmd/cmd.h index 85032df..05f9b7b 100644 --- a/cmd/cmd.h +++ b/cmd/cmd.h @@ -68,6 +68,10 @@ typedef enum { CMD_WIFI_GET_SSID, // Query SSID currently connected to CMD_WIFI_START_SCAN, // Trigger a scan (takes a long time) + CMD_UPNP_SCAN = 60, + CMD_UPNP_ADD_PORT, + CMD_UPNP_REMOVE_PORT, + } CmdName; typedef void (*cmdfunc_t)(CmdPacket *cmd); diff --git a/cmd/handlers.c b/cmd/handlers.c index 1be8b6e..74b2b44 100644 --- a/cmd/handlers.c +++ b/cmd/handlers.c @@ -40,6 +40,8 @@ static void cmdWifiSignalStrength(CmdPacket *cmd); void cmdMqttGetClientId(CmdPacket *cmd); +void cmdUPnPScan(CmdPacket *cmd); + // keep track of last status sent to uC so we can notify it when it changes static uint8_t lastWifiStatus = wifiIsDisconnected; // keep track of whether we have registered our cb handler with the wifi subsystem @@ -64,6 +66,8 @@ const CmdList commands[] = { {CMD_WIFI_GET_SSID, "WIFI_GET_SSID", cmdWifiQuerySSID}, {CMD_WIFI_START_SCAN, "WIFI_START_SCAN", cmdWifiStartScan}, + {CMD_UPNP_SCAN, "UPNP_SCAN", cmdUPnPScan}, + #ifdef MQTT {CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup}, {CMD_MQTT_PUBLISH, "MQTT_PUB", MQTTCMD_Publish}, diff --git a/esp-link/upnp.c b/esp-link/upnp.c new file mode 100644 index 0000000..faf5b88 --- /dev/null +++ b/esp-link/upnp.c @@ -0,0 +1,124 @@ +#include "esp8266.h" +#include "sntp.h" +#include "cmd.h" +#include +#include + +#if 1 +#define DBG_SOCK(format, ...) os_printf(format, ## __VA_ARGS__) +#else +#define DBG_SOCK(format, ...) do { } while(0) +#endif + +#define location_size 80 +static const int counter_max = 4; + +enum upnp_state_t { + upnp_none, + upnp_multicasted, + upnp_found_igd +}; +static enum upnp_state_t upnp_state; + + +static const char *upnp_ssdp_multicast = "239.255.255.250"; +static short upnp_server_port = 1900; +static short upnp_local_port = -1; +static const char *ssdp_message = "M-SEARCH * HTTP/1.1\r\n" + "HOST: 239.255.255.250:1900\r\n" + "ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n" + "MAN: \"ssdp:discover\"\r\n" + "MX: 2\r\n"; +static int ssdp_len; +static char location[location_size]; +static int counter; + +static void ICACHE_FLASH_ATTR +upnp_recv_cb(void *arg, char *pusrdata, unsigned short length) { + // struct espconn *pCon = (struct espconn *)arg; + + os_printf("upnp_recv_cb : %d bytes\n", length); + + switch (upnp_state) { + case upnp_multicasted: + // Find the LOCATION: field + for (int i=0; itype = ESPCONN_UDP; + con->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); + if (con->proto.udp == NULL) { + DBG_SOCK("SOCKET : Setup failed to alloc memory for client->pCon->proto.udp\n"); + return; + } + + con->state = ESPCONN_NONE; + + con->proto.udp->remote_port = upnp_server_port; + con->proto.udp->local_port = upnp_local_port; + + espconn_regist_sentcb(con, upnp_sent_cb); + espconn_regist_recvcb(con, upnp_recv_cb); + + DBG_SOCK("SOCKET : Create connection to ip %s:%d\n", upnp_ssdp_multicast, upnp_server_port); + + if (UTILS_StrToIP((char *)upnp_ssdp_multicast, &con->proto.udp->remote_ip)) { + espconn_create(con); + } else { + DBG_SOCK("SOCKET : failed to copy remote_ip to &con->proto.udp->remote_ip\n"); + return; + } + + ssdp_len = strlen(ssdp_message); + espconn_sent(con, (uint8_t*)ssdp_message, ssdp_len); + DBG_SOCK("SOCKET : sending %d bytes\n", ssdp_len); + upnp_state = upnp_multicasted; +} +