I'll enclose my code below which is in parts a mixture of different concepts. I already tried different approaches but just can't get to see why it wouldn't work as I want.
- init
- config uart
- config wifi to STATIONAP_MODE + config wifi_set_broadcast_if
- config connections (one for AP, separate one for STATION) and config tasks / timers / handlers
- timers
- timer to check network state every second (predecessor / alternative to wifi_set_event_hander_cb)
- timer to sporadically do "work", i.e. post a message to IdleTask (main work routine)
- IdleTask
- send UDP message to a connection for AP and - if connected to a STATION - to another connection for STATION
- wifi_handle_event_cb (wifi_set_event_hander_cb)
- initialize a connection whenever an IP for STATION has been received
Thanks in advance for any hint,
M.
Code:
// Copyright by SomeDay54
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"
//default tasks (3 priority levels)
#define TopTaskPrio 2
#define TopTaskQueueLen 1
#define ActionTaskPrio 1
#define ActionTaskQueueLen 8
#define IdleTaskPrio 0
//#define IdleTaskQueueLen 1
#define IdleTaskQueueLen 10
#define MAX_BUF 1024
static void TopTask(os_event_t *events);
static void ActionTask(os_event_t *events);
static void IdleTask(os_event_t *events);
void ICACHE_FLASH_ATTR udp_Receive (void* arg);
void ICACHE_FLASH_ATTR udp_SendComplete (void* arg);
void ICACHE_FLASH_ATTR wifi_handle_event_cb(System_Event_t *evt);
os_event_t TopTaskQueue[TopTaskQueueLen];
os_event_t ActionTaskQueue[ActionTaskQueueLen];
os_event_t IdleTaskQueue[IdleTaskQueueLen];
static int network = -1;
static os_timer_t network_timer;
static os_timer_t next_work_timer;
struct espconn udpCon;
struct espconn udpConAP;
ip_addr_t multicast_ip;
uint8 hostAddr[4];
char udpBuf[MAX_BUF+1];
void ICACHE_FLASH_ATTR network_check_ip(void)
{
struct ip_info ipconfig;
os_timer_disarm(&network_timer); // Disarm timer
wifi_get_ip_info(STATION_IF, &ipconfig); // Get Wifi info
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0)
{
os_printf("connected (%d.%d.%d.%d) !!! \r\n", hostAddr[0]=ip4_addr1(&ipconfig.ip.addr), hostAddr[1]=ip4_addr2(&ipconfig.ip.addr), hostAddr[2]=ip4_addr3(&ipconfig.ip.addr), hostAddr[3]=ip4_addr4(&ipconfig.ip.addr));
}
else if ((wifi_station_get_connect_status() == STATION_WRONG_PASSWORD ||
wifi_station_get_connect_status() == STATION_NO_AP_FOUND ||
wifi_station_get_connect_status() == STATION_CONNECT_FAIL)) {
os_printf("connect fail (%d) !!! \r\n", wifi_station_get_connect_status());
} else
{
os_printf("Waiting for IP...\n\r");
if (network-- == -1000) {
os_printf("No connection / no ip\n");
// switch to ap
network = 2;
//wifi_set_opmode(STATION_MODE); // Force Station mode
//wifi_station_set_auto_connect(TRUE);
} else {
//wifi_station_connect(); //should work automagically
os_timer_setfn(&network_timer, (os_timer_func_t *)network_check_ip, NULL);
os_timer_arm(&network_timer, 1000, 0);
}
}
}
/******************************************************************************
* FunctionName : user_set_station_config
* Description : set the router info which ESP8266 station will connect to
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_set_station_config(void)
{
// Wifi configuration
char ssid[32] = "SSID";
char password[64] = "PWD";
struct station_config stationConf;
os_memset(stationConf.ssid, 0, 32);
os_memset(stationConf.password, 0, 64);
//need not mac address
stationConf.bssid_set = 0;
wifi_set_opmode(STATIONAP_MODE); // Force Station+AP mode
wifi_set_broadcast_if(STATIONAP_MODE);
wifi_set_event_handler_cb(wifi_handle_event_cb);
//Set ap settings
os_memcpy(&stationConf.ssid, ssid, 32);
os_memcpy(&stationConf.password, password, 64);
//wifi_station_set_config(&stationConf);
//set a timer to check whether got ip from router succeed or not.
os_timer_disarm(&network_timer);
os_timer_setfn(&network_timer, (os_timer_func_t *)network_check_ip, NULL);
os_timer_arm(&network_timer, 1000, 0);
}
static void ICACHE_FLASH_ATTR TopTask(os_event_t *events){
}
static void ICACHE_FLASH_ATTR ActionTask(os_event_t *events){
}
static void ICACHE_FLASH_ATTR IdleTask(os_event_t *events){
os_printf("GMA-Task\n");
os_sprintf(udpBuf, "Packet ok\n");
udpBuf[MAX_BUF]=0;
espconn_sendto(&udpCon, udpBuf, MAX_BUF);
if (network == 1) {
espconn_sendto(&udpConAP, udpBuf, MAX_BUF);
}
//system_os_post(IdleTaskPrio, 0, 0); //add IdleTask back into queue
}
void ICACHE_FLASH_ATTR IdleTask2(void) {
os_timer_disarm(&next_work_timer);
system_os_post(IdleTaskPrio, 0, 0); //add IdleTask back into queue
os_timer_setfn(&next_work_timer, (os_timer_func_t *)IdleTask2, NULL);
os_timer_arm(&next_work_timer, 10000, 0);
}
void ICACHE_FLASH_ATTR udp_Receive (void* arg) {
os_printf("UDP receive ..\n");
}
void ICACHE_FLASH_ATTR udp_SendComplete (void* arg) {
os_printf("UDP sent ..\n");
}
void ICACHE_FLASH_ATTR init_tasks(){
IP4_ADDR(&multicast_ip, 224, 0, 2, 9); // 224.0.2.9
memset(&udpCon, 0, sizeof(udpCon));
memset(&udpConAP, 0, sizeof(udpConAP));
udpCon.type = ESPCONN_UDP;
udpCon.state = ESPCONN_NONE;
udpCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
udpCon.proto.udp->local_port = 1025;
udpCon.proto.udp->remote_port = 6789;
udpCon.proto.udp->remote_ip[0] = ip4_addr1(&multicast_ip);
udpCon.proto.udp->remote_ip[1] = ip4_addr2(&multicast_ip);
udpCon.proto.udp->remote_ip[2] = ip4_addr3(&multicast_ip);
udpCon.proto.udp->remote_ip[3] = ip4_addr4(&multicast_ip);
udpConAP.type = ESPCONN_UDP;
udpConAP.state = ESPCONN_NONE;
udpConAP.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
udpConAP.proto.udp->local_port = 1024;
udpConAP.proto.udp->remote_port = 6789;
udpConAP.proto.udp->remote_ip[0] = ip4_addr1(&multicast_ip);
udpConAP.proto.udp->remote_ip[1] = ip4_addr2(&multicast_ip);
udpConAP.proto.udp->remote_ip[2] = ip4_addr3(&multicast_ip);
udpConAP.proto.udp->remote_ip[3] = ip4_addr4(&multicast_ip);
espconn_regist_recvcb(&udpConAP, (espconn_recv_callback) ((void *)udp_Receive));
espconn_regist_sentcb(&udpConAP, (espconn_sent_callback) ((void *)udp_SendComplete));
if (espconn_create(&udpConAP) == 0) {
os_printf("UDP-Port AP ok\n");
} else
os_printf("UDP-Port AP error\n");
os_printf("Initialisation Complete. Starting Tasks\n");
//add tasks
system_os_task(TopTask, TopTaskPrio, TopTaskQueue, TopTaskQueueLen);
system_os_task(ActionTask, ActionTaskPrio, ActionTaskQueue, ActionTaskQueueLen);
system_os_task(IdleTask, IdleTaskPrio, IdleTaskQueue, IdleTaskQueueLen);
//after init done, start idle task loop
system_os_post(IdleTaskPrio, 0, 0);
os_timer_disarm(&next_work_timer);
os_timer_setfn(&next_work_timer, (os_timer_func_t *)IdleTask2, NULL);
os_timer_arm(&next_work_timer, 10000, 0);
}
void user_rf_pre_init(void)
{
}
void ICACHE_FLASH_ATTR wifi_handle_event_cb(System_Event_t *evt)
{ int state;
os_printf("event %x\n", evt->event);
switch (evt->event) {
case EVENT_STAMODE_CONNECTED:
os_printf("connect to ssid %s, channel %d\n",
evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break;
case EVENT_STAMODE_DISCONNECTED:
network=-1;
os_printf("disconnect from ssid %s, reason %d\n",
evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
espconn_igmp_leave((ip_addr_t *)hostAddr, &multicast_ip);
state=espconn_delete(&udpCon);
os_printf("udpCon deleted ret=%d\n", state);
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
os_printf("mode: %d -> %d\n",
evt->event_info.auth_change.old_mode,
evt->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP:
os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR,
IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask),
IP2STR(&evt->event_info.got_ip.gw));
os_printf("\n");
hostAddr[0]=ip4_addr1(&evt->event_info.got_ip.ip.addr);
hostAddr[1]=ip4_addr2(&evt->event_info.got_ip.ip.addr);
hostAddr[2]=ip4_addr3(&evt->event_info.got_ip.ip.addr);
hostAddr[3]=ip4_addr4(&evt->event_info.got_ip.ip.addr);
udpCon.type = ESPCONN_UDP;
udpCon.state = ESPCONN_NONE;
//udpCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
udpCon.proto.udp->local_port = 1025;
udpCon.proto.udp->remote_port = 6789;
udpCon.proto.udp->remote_ip[0] = ip4_addr1(&multicast_ip);
udpCon.proto.udp->remote_ip[1] = ip4_addr2(&multicast_ip);
udpCon.proto.udp->remote_ip[2] = ip4_addr3(&multicast_ip);
udpCon.proto.udp->remote_ip[3] = ip4_addr4(&multicast_ip);
udpCon.proto.udp->local_ip[0] = hostAddr[0];
udpCon.proto.udp->local_ip[1] = hostAddr[1];
udpCon.proto.udp->local_ip[2] = hostAddr[2];
udpCon.proto.udp->local_ip[3] = hostAddr[3];
// if (wifi_set_broadcast_if(STATIONAP_MODE)) {
if (wifi_set_broadcast_if(STATION_MODE)) {
os_printf("broadcast to ap and station\n");
} else {
os_printf("broadcast to ap and station failed\n");
}
espconn_igmp_join((ip_addr_t *)hostAddr, &multicast_ip);
espconn_regist_recvcb(&udpCon, (espconn_recv_callback) ((void *)udp_Receive));
espconn_regist_sentcb(&udpCon, (espconn_sent_callback) ((void *)udp_SendComplete));
state=espconn_create(&udpCon);
os_printf("udpCon created ret=%d\n", state);
network=1;
break;
case EVENT_SOFTAPMODE_STACONNECTED:
os_printf("station: " MACSTR "join, AID = %d\n",
MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
os_printf("station: " MACSTR "leave, AID = %d\n",
MAC2STR(evt->event_info.sta_disconnected.mac),
evt->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
/******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
uart_div_modify(0, UART_CLK_FREQ / 115200);
os_printf("SDK version:%s\n", system_get_sdk_version());
user_set_station_config();
os_printf("Post-Station\n");
//system_init_done_cb(init_tasks);
init_tasks();
}