Add UDP Broadcast for OpenMV Cam discovery.

* Now OpenMV Cam's can be discovered in the wild by OpenMV IDE without
hardcoding the OpenMV Cam WiFi IP address and port.
* The firmware reads settings from OpenMV IDE for STA and AP mode.
* Boradcast in both modes works and OpenMV IDE can find the cam.
* AP mode works (albeit the driver needs help).
* Station mode sometimes connects every now and then. There's a bug in
the WiFi module that prevents this from working right. The same code
executes on the cam and in the IDE for both modes but station mode has
issues...
This commit is contained in:
Kwabena W. Agyeman 2018-08-07 01:23:28 -04:00 committed by iabdalkader
parent abe97a73ba
commit 60f6d1ddc7
4 changed files with 137 additions and 45 deletions

View File

@ -300,14 +300,24 @@ int ini_handler_callback(void *user, const char *section, const char *name, cons
openmv_config->wifidbg = ini_is_true(value);
} else if (MATCH("WiFiConfig", "Mode")) {
openmv_config->wifidbg_config.mode = ini_atoi(value);
} else if (MATCH("WiFiConfig", "SSID")) {
strncpy(openmv_config->wifidbg_config.ssid, value, WINC_MAX_SSID_LEN);
} else if (MATCH("WiFiConfig", "Key")) {
strncpy(openmv_config->wifidbg_config.key, value, WINC_MAX_PSK_LEN);
} else if (MATCH("WiFiConfig", "Security")) {
openmv_config->wifidbg_config.security = ini_atoi(value);
} else if (MATCH("WiFiConfig", "Channel")) {
openmv_config->wifidbg_config.channel = ini_atoi(value);
} else if (MATCH("WiFiConfig", "ClientSSID")) {
strncpy(openmv_config->wifidbg_config.client_ssid, value, WINC_MAX_SSID_LEN);
} else if (MATCH("WiFiConfig", "ClientKey")) {
strncpy(openmv_config->wifidbg_config.client_key, value, WINC_MAX_PSK_LEN);
} else if (MATCH("WiFiConfig", "ClientSecurity")) {
openmv_config->wifidbg_config.client_security = ini_atoi(value);
} else if (MATCH("WiFiConfig", "ClientChannel")) {
openmv_config->wifidbg_config.client_channel = ini_atoi(value);
} else if (MATCH("WiFiConfig", "AccessPointSSID")) {
strncpy(openmv_config->wifidbg_config.access_point_ssid, value, WINC_MAX_SSID_LEN);
} else if (MATCH("WiFiConfig", "AccessPointKey")) {
strncpy(openmv_config->wifidbg_config.access_point_key, value, WINC_MAX_PSK_LEN);
} else if (MATCH("WiFiConfig", "AccessPointSecurity")) {
openmv_config->wifidbg_config.access_point_security = ini_atoi(value);
} else if (MATCH("WiFiConfig", "AccessPointChannel")) {
openmv_config->wifidbg_config.access_point_channel = ini_atoi(value);
} else if (MATCH("WiFiConfig", "BoardName")) {
strncpy(openmv_config->wifidbg_config.board_name, value, WINC_MAX_BOARD_NAME_LEN);
} else {
return 0;
}

View File

@ -30,16 +30,23 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#define SERVER_ADDR ((uint8_t [5]){192, 168, 1, 1})
#define SERVER_PORT (9000)
#define BUFFER_SIZE (512)
#define OPENMVCAM_BROADCAST_ADDR ((uint8_t [5]){255, 255, 255, 255})
#define OPENMVCAM_BROADCAST_PORT (0xABD1)
#define SERVER_ADDR ((uint8_t [5]){192, 168, 1, 1})
#define SERVER_PORT (9000)
#define BUFFER_SIZE (512)
#define UDPCAST_STRING "%d.%d.%d.%d:%d:%s"
#define UDPCAST_STRING_SIZE 4+4+4+4+6+WINC_MAX_BOARD_NAME_LEN+1
#define close_all_sockets() \
do { \
winc_socket_close(client_fd); \
winc_socket_close(server_fd); \
winc_socket_close(udpbcast_fd); \
client_fd = -1; \
server_fd = -1; \
udpbcast_fd = -1; \
} while (0)
#define close_server_socket() \
@ -48,25 +55,71 @@
server_fd = -1; \
} while (0)
#define close_udpbcast_socket() \
do { \
winc_socket_close(udpbcast_fd); \
udpbcast_fd = -1; \
} while (0)
#define TIMEDOUT(x) (x == -ETIMEDOUT || x == SOCK_ERR_TIMEOUT)
static int client_fd = -1;
static int server_fd = -1;
static int udpbcast_fd = -1;
static int udpbcast_time = 0;
static uint8_t ip_addr[WINC_IP_ADDR_LEN] = {};
static char udpbcast_string[UDPCAST_STRING_SIZE] = {};
int wifidbg_init(wifidbg_config_t *config)
{
client_fd = -1;
server_fd = -1;
udpbcast_fd = -1;
// Initialize WiFi in AP mode.
if (winc_init(WINC_MODE_AP) != 0) {
return -1;
if(!config->mode) { // STA Mode
// Initialize WiFi in STA mode.
if (winc_init(WINC_MODE_STA) != 0) {
return -1;
}
// Connect to network.
if (winc_connect(config->client_ssid,
config->client_security,
config->client_key,
config->client_channel) != 0) {
return -2;
}
winc_ifconfig_t ifconfig;
if (winc_ifconfig(&ifconfig) < 0) {
return -3;
}
memcpy(ip_addr, ifconfig.ip_addr, WINC_IP_ADDR_LEN);
} else { // AP Mode
// Initialize WiFi in AP mode.
if (winc_init(WINC_MODE_AP) != 0) {
return -1;
}
// Start WiFi in AP mode.
if (winc_start_ap(config->access_point_ssid,
config->access_point_security,
config->access_point_key,
config->access_point_channel) != 0) {
return -2;
}
memcpy(ip_addr, SERVER_ADDR, WINC_IP_ADDR_LEN);
}
// Start WiFi in AP mode.
if (winc_start_ap(config->ssid, config->security, config->key, config->channel) != 0) {
return -2;
}
snprintf(udpbcast_string, UDPCAST_STRING_SIZE, UDPCAST_STRING,
ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3],
SERVER_PORT, config->board_name);
return 0;
}
@ -77,9 +130,35 @@ void wifidbg_dispatch()
uint8_t buf[BUFFER_SIZE];
sockaddr client_sockaddr;
if (udpbcast_fd < 0) {
// Create broadcast socket
MAKE_SOCKADDR(udpbcast_sockaddr, OPENMVCAM_BROADCAST_ADDR, OPENMVCAM_BROADCAST_PORT)
if ((udpbcast_fd = winc_socket_socket(SOCK_DGRAM)) < 0) {
return;
}
if ((ret = winc_socket_bind(udpbcast_fd, &udpbcast_sockaddr)) < 0) {
close_udpbcast_socket();
return;
}
}
if ((udpbcast_fd >= 0) && (!(udpbcast_time++ % 100))) {
// Create broadcast socket
MAKE_SOCKADDR(udpbcast_sockaddr, OPENMVCAM_BROADCAST_ADDR, OPENMVCAM_BROADCAST_PORT)
if ((ret = winc_socket_sendto(udpbcast_fd,
(uint8_t *) udpbcast_string, strlen(udpbcast_string) + 1,
&udpbcast_sockaddr, 500)) < 0) {
close_udpbcast_socket();
return;
}
}
if (server_fd < 0) {
// Create server socket
MAKE_SOCKADDR(server_sockaddr, SERVER_ADDR, SERVER_PORT)
MAKE_SOCKADDR(server_sockaddr, ip_addr, SERVER_PORT)
if ((server_fd = winc_socket_socket(SOCK_STREAM)) < 0) {
return;
@ -107,7 +186,6 @@ void wifidbg_dispatch()
}
return;
}
}
if ((ret = winc_socket_recv(client_fd, buf, 8, 10)) < 0) {

View File

@ -8,12 +8,14 @@
typedef struct wifidbg_config {
winc_mode_t mode;
winc_security_t security;
char key[WINC_MAX_PSK_LEN + 1];
char ssid[WINC_MAX_SSID_LEN + 1];
uint8_t channel;
winc_security_t client_security, access_point_security;
char client_key[WINC_MAX_PSK_LEN + 1], access_point_key[WINC_MAX_PSK_LEN + 1];
char client_ssid[WINC_MAX_SSID_LEN + 1], access_point_ssid[WINC_MAX_SSID_LEN + 1];
uint8_t client_channel, access_point_channel;
char board_name[WINC_MAX_BOARD_NAME_LEN + 1];
} wifidbg_config_t;
void wifidbg_dispatch();
int wifidbg_init(wifidbg_config_t *config);
void wifidbg_dispatch();
#endif /* __WIFIDBG_H__ */

View File

@ -9,10 +9,11 @@
#ifndef __WINC_H__
#define __WINC_H__
#include <stdint.h>
#define WINC_IP_ADDR_LEN (4)
#define WINC_MAC_ADDR_LEN (6)
#define WINC_MAX_SSID_LEN (33)
#define WINC_MAX_PSK_LEN (65)
#define WINC_IP_ADDR_LEN (4)
#define WINC_MAC_ADDR_LEN (6)
#define WINC_MAX_SSID_LEN (33)
#define WINC_MAX_PSK_LEN (65)
#define WINC_MAX_BOARD_NAME_LEN (33)
#define MAKE_SOCKADDR(addr, ip, port) \
struct sockaddr addr; \
@ -40,11 +41,11 @@ typedef enum {
} winc_mode_t;
typedef enum {
WINC_SEC_INVALID = 0,
WINC_SEC_OPEN,
WINC_SEC_WPA_PSK,
WINC_SEC_WEP,
WINC_SEC_802_1X
WINC_SEC_INVALID = 0,
WINC_SEC_OPEN,
WINC_SEC_WPA_PSK,
WINC_SEC_WEP,
WINC_SEC_802_1X
} winc_security_t;
typedef struct {
@ -56,23 +57,23 @@ typedef struct {
} winc_ifconfig_t;
typedef struct {
int8_t rssi;
uint8_t security;
int8_t rssi;
uint8_t security;
uint8_t channel;
uint8_t bssid[6];
char ssid[WINC_MAX_SSID_LEN];
uint8_t bssid[6];
char ssid[WINC_MAX_SSID_LEN];
} winc_scan_result_t;
typedef int (*winc_scan_callback_t) (winc_scan_result_t *, void *);
typedef struct {
uint8_t fw_major; // Firmware version major number.
uint8_t fw_minor; // Firmware version minor number.
uint8_t fw_patch; // Firmware version patch number.
uint8_t drv_major; // Driver version major number.
uint8_t drv_minor; // Driver version minor number.
uint8_t drv_patch; // Driver version patch number.
uint32_t chip_id; // HW revision number (chip ID).
uint8_t fw_major; // Firmware version major number.
uint8_t fw_minor; // Firmware version minor number.
uint8_t fw_patch; // Firmware version patch number.
uint8_t drv_major; // Driver version major number.
uint8_t drv_minor; // Driver version minor number.
uint8_t drv_patch; // Driver version patch number.
uint32_t chip_id; // HW revision number (chip ID).
} winc_fwver_t;
typedef struct {
@ -110,4 +111,5 @@ int winc_socket_recv(int fd, uint8_t *buf, uint32_t len, uint32_t timeout);
int winc_socket_sendto(int fd, const uint8_t *buf, uint32_t len, sockaddr *addr, uint32_t timeout);
int winc_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, sockaddr *addr, uint32_t timeout);
int winc_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen);
#endif //__WINC_H__