Pārlūkot izejas kodu

AirPlay fix & misc

- Spectrum scale fix
- Initialize more display parameters
- Reboot after 30s of no connection
- Reboot after IP address change
philippe44 5 gadi atpakaļ
vecāks
revīzija
8e95bd3dd2

+ 9 - 4
components/display/SSD1306.c

@@ -74,7 +74,7 @@ static void Update( struct GDS_Device* Device ) {
 			CurrentPage = p + 1;
 			
 			// actual write
-			Device->WriteData( Device, Private->Shadowbuffer + p*width + first, last - first + 1);
+			Device->WriteData( Device, Private->Shadowbuffer + p*width + first, last - first + 1 );
 		}
 	}	
 #else	
@@ -114,6 +114,10 @@ static bool Init( struct GDS_Device* Device ) {
 	// charge pump regulator, do direct init
 	Device->WriteCommand( Device, 0x8D );
 	Device->WriteCommand( Device, 0x14 ); 
+	
+	// set Clocks
+    Device->WriteCommand( Device, 0xD5 );
+    Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 );
 			
 	// COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something different
 	Device->WriteCommand( Device, 0xDA );
@@ -122,6 +126,10 @@ static bool Init( struct GDS_Device* Device ) {
 	// MUX Ratio
     Device->WriteCommand( Device, 0xA8 );
     Device->WriteCommand( Device, Device->Height - 1);
+	// Page & GDDRAM Start Column High/Low
+    Device->WriteCommand( Device, 0x00 );
+	Device->WriteCommand( Device, 0x10 );
+	Device->WriteCommand( Device, 0xB0 );
 	// Display Offset
     Device->WriteCommand( Device, 0xD3 );
     Device->WriteCommand( Device, 0 );
@@ -133,9 +141,6 @@ static bool Init( struct GDS_Device* Device ) {
 	Device->SetHFlip( Device, false );
 	// no Display Inversion
     Device->WriteCommand( Device, 0xA6 );
-	// set Clocks
-    Device->WriteCommand( Device, 0xD5 );
-    Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 );
 	// set Adressing Mode Horizontal
 	Device->WriteCommand( Device, 0x20 );
 	Device->WriteCommand( Device, 0 );

+ 17 - 3
components/display/SSD132x.c

@@ -126,6 +126,7 @@ static void Update1( struct GDS_Device* Device ) {
 	// not sure the compiler does not have to redo all calculation in for loops, so local it is
 	int width = Device->Width / 8, rows = Device->Height;
 	uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer;
+	int CurrentRow = -1, FirstCol = -1, LastCol = -1;
 	
 	// by row, find first and last columns that have been updated
 	for (int r = 0; r < rows; r++) {
@@ -140,9 +141,22 @@ static void Update1( struct GDS_Device* Device ) {
 		
 		// now update the display by "byte rows"
 		if (first--) {
-			SetColumnAddress( Device, first, last );
-			SetRowAddress( Device, r, r);
-			Device->WriteData( Device, Private->Shadowbuffer + r*width + first, last - first + 1);
+			// only set column when useful, saves a fair bit of CPU
+			if (first > FirstCol && first <= FirstCol + 4 && last < LastCol && last >= LastCol - 4) {
+				first = FirstCol;
+				last = LastCol;
+			} else {	
+				SetColumnAddress( Device, first, last );
+				FirstCol = first;
+				LastCol = last;
+			}
+			
+			// Set row only when needed, otherwise let auto-increment work
+			if (r != CurrentRow) SetRowAddress( Device, r, Device->Height - 1 );
+			CurrentRow = r + 1;
+			
+			// actual write
+			Device->WriteData( Device, Private->Shadowbuffer + r*width + first, last - first + 1 );
 		}
 	}	
 #else	

+ 2 - 2
components/display/display.c

@@ -201,8 +201,8 @@ static void displayer_task(void *args) {
 				displayer.tick = tick;
 				displayer.elapsed += elapsed / 1000;
 				xSemaphoreGive(displayer.mutex);				
-				if (displayer.elapsed < 3600) sprintf(counter, "%5u:%02u", displayer.elapsed / 60, displayer.elapsed % 60);
-				else sprintf(counter, "%2u:%02u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60);
+				if (displayer.elapsed < 3600) snprintf(counter, 16, "%5u:%02u", displayer.elapsed / 60, displayer.elapsed % 60);
+				else snprintf(counter, 16, "%2u:%02u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60);
 				GDS_TextLine(display, 1, GDS_TEXT_RIGHT, (GDS_TEXT_CLEAR | GDS_TEXT_CLEAR_EOL) | GDS_TEXT_UPDATE, counter);
 				timer_sleep = 1000;
 			} else timer_sleep = max(1000 - elapsed, 0);	

+ 5 - 2
components/raop/raop.c

@@ -508,7 +508,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
 		pthread_create(&ctx->active_remote.thread, NULL, &search_remote, ctx);
 #else
 		ctx->active_remote.running = true;
-		ctx->active_remote.destroy_mutex = xSemaphoreCreateMutex();		
+		ctx->active_remote.destroy_mutex = xSemaphoreCreateBinary();
 		ctx->active_remote.xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
 		ctx->active_remote.thread = xTaskCreateStatic( (TaskFunction_t) search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 1, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer);
 #endif		
@@ -570,7 +570,10 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
 		if ((p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime);
 
 		// only send FLUSH if useful (discards frames above buffer head and top)
-		if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime)) success = ctx->cmd_cb(RAOP_FLUSH);
+		if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime, true)) {
+			success = ctx->cmd_cb(RAOP_FLUSH);
+			rtp_flush_release(ctx->rtp);
+		}	
 
 	}  else if (!strcmp(method, "TEARDOWN")) {
 

+ 36 - 22
components/raop/rtp.c

@@ -267,25 +267,25 @@ rtp_resp_t rtp_init(struct in_addr host, int latency, char *aeskey, char *aesiv,
 	resp.cport = ctx->rtp_sockets[CONTROL].lport;
 	resp.tport = ctx->rtp_sockets[TIMING].lport;
 	resp.aport = ctx->rtp_sockets[DATA].lport;
-	
-	if (rc) {
-		ctx->running = true;
+		
+	ctx->running = true;
+
 #ifdef WIN32
-		pthread_create(&ctx->thread, NULL, rtp_thread_func, (void *) ctx);
+	pthread_create(&ctx->thread, NULL, rtp_thread_func, (void *) ctx);
 #else
-		// xTaskCreate((TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_TASK_SIZE, ctx,  CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1 , &ctx->thread);
-		ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
-		ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx, 
-										 CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer );
+	ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+	ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx,
+									 CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer );
 #endif
-	} else {
+	
+	// cleanup everything if we failed
+	if (!rc) {	
 		LOG_ERROR("[%p]: cannot start RTP", ctx);
 		rtp_end(ctx);
 		ctx = NULL;
-	}
-
-	resp.ctx = ctx;
-
+	}	
+	
+	resp.ctx = ctx;	
 	return resp;
 }
 
@@ -327,7 +327,7 @@ void rtp_end(rtp_t *ctx)
 }
 
 /*---------------------------------------------------------------------------*/
-bool rtp_flush(rtp_t *ctx, unsigned short seqno, unsigned int rtptime)
+bool rtp_flush(rtp_t *ctx, unsigned short seqno, unsigned int rtptime, bool exit_locked)
 {
 	bool rc = true;
 	u32_t now = gettime_ms();
@@ -340,7 +340,7 @@ bool rtp_flush(rtp_t *ctx, unsigned short seqno, unsigned int rtptime)
 		buffer_reset(ctx->audio_buffer);
 		ctx->playing = false;
 		ctx->flush_seqno = seqno;
-		pthread_mutex_unlock(&ctx->ab_mutex);
+		if (!exit_locked) pthread_mutex_unlock(&ctx->ab_mutex);
 	}
 
 	LOG_INFO("[%p]: flush %hu %u", ctx, seqno, rtptime);
@@ -349,8 +349,13 @@ bool rtp_flush(rtp_t *ctx, unsigned short seqno, unsigned int rtptime)
 }
 
 /*---------------------------------------------------------------------------*/
-void rtp_record(rtp_t *ctx, unsigned short seqno, unsigned rtptime)
-{
+void rtp_flush_release(rtp_t *ctx) {
+	pthread_mutex_unlock(&ctx->ab_mutex);
+}
+
+
+/*---------------------------------------------------------------------------*/
+void rtp_record(rtp_t *ctx, unsigned short seqno, unsigned rtptime) {
 	ctx->record.seqno = seqno;
 	ctx->record.rtptime = rtptime;
 	ctx->record.time = gettime_ms();
@@ -576,7 +581,7 @@ static void *rtp_thread_func(void *arg) {
 	while (ctx->running) {
 		ssize_t plen;
 		char type;
-		socklen_t rtp_client_len = sizeof(struct sockaddr_storage);
+		socklen_t rtp_client_len = sizeof(struct sockaddr_in);
 		int idx = 0;
 		char *pktp = packet;
 		struct timeval timeout = {0, 100*1000};
@@ -589,14 +594,18 @@ static void *rtp_thread_func(void *arg) {
 		for (i = 0; i < 3; i++)
 			if (FD_ISSET(ctx->rtp_sockets[i].sock, &fds)) idx = i;
 
-		plen = recvfrom(ctx->rtp_sockets[idx].sock, packet, MAX_PACKET, 0, (struct sockaddr*) &ctx->rtp_host, &rtp_client_len);
+		plen = recvfrom(ctx->rtp_sockets[idx].sock, packet, MAX_PACKET, MSG_DONTWAIT, (struct sockaddr*) &ctx->rtp_host, &rtp_client_len);
 
 		if (!ntp_sent) {
 			LOG_WARN("[%p]: NTP request not send yet", ctx);
 			ntp_sent = rtp_request_timing(ctx);
 		}
 
-		if (plen < 0) continue;
+		if (plen <= 0) {
+			LOG_WARN("Nothing received on a readable socket %d", plen);
+			continue;
+		}
+		
 		assert(plen <= MAX_PACKET);
 
 		type = packet[1] & ~0x80;
@@ -715,6 +724,11 @@ static void *rtp_thread_func(void *arg) {
 
 				break;
 			}
+			
+			default: {
+				LOG_WARN("Unknown packet received %x", (int) type);
+				break;
+			}
 		}
 	}
 
@@ -756,7 +770,7 @@ static bool rtp_request_timing(rtp_t *ctx) {
 
 	host.sin_port = htons(ctx->rtp_sockets[TIMING].rport);
 
-	if (sizeof(req) != sendto(ctx->rtp_sockets[TIMING].sock, req, sizeof(req), 0, (struct sockaddr*) &host, sizeof(host))) {
+	if (sizeof(req) != sendto(ctx->rtp_sockets[TIMING].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*) &host, sizeof(host))) {
 		LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno));
 	}
 
@@ -782,7 +796,7 @@ static bool rtp_request_resend(rtp_t *ctx, seq_t first, seq_t last) {
 
 	ctx->rtp_host.sin_port = htons(ctx->rtp_sockets[CONTROL].rport);
 
-	if (sizeof(req) != sendto(ctx->rtp_sockets[CONTROL].sock, req, sizeof(req), 0, (struct sockaddr*) &ctx->rtp_host, sizeof(ctx->rtp_host))) {
+	if (sizeof(req) != sendto(ctx->rtp_sockets[CONTROL].sock, req, sizeof(req), MSG_DONTWAIT, (struct sockaddr*) &ctx->rtp_host, sizeof(ctx->rtp_host))) {
 		LOG_WARN("[%p]: SENDTO failed (%s)", ctx, strerror(errno));
 	}
 

+ 2 - 1
components/raop/rtp.h

@@ -14,7 +14,8 @@ rtp_resp_t 			rtp_init(struct in_addr host, int latency,
 							short unsigned pCtrlPort, short unsigned pTimingPort,
 							raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb);
 void			 	rtp_end(struct rtp_s *ctx);
-bool 				rtp_flush(struct rtp_s *ctx, unsigned short seqno, unsigned rtptime);
+bool 				rtp_flush(struct rtp_s *ctx, unsigned short seqno, unsigned rtptime, bool exit_locked);
+void				rtp_flush_release(struct rtp_s *ctx);
 void 				rtp_record(struct rtp_s *ctx, unsigned short seqno, unsigned rtptime);
 void 				rtp_metadata(struct rtp_s *ctx, struct metadata_s *metadata);
 

+ 1 - 1
components/raop/util.c

@@ -401,7 +401,7 @@ bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
 	}
 
 	if (*len) {
-		int size = 0;
+		int size = 0;
 
 		*body = malloc(*len + 1);
 		while (*body && size < *len) {

+ 5 - 3
components/services/monitor.c

@@ -23,6 +23,7 @@
 #include "accessors.h"
 
 #define MONITOR_TIMER	(10*1000)
+#define SCRATCH_SIZE	256
 
 static const char *TAG = "monitor";
 
@@ -54,7 +55,7 @@ static void task_stats( void ) {
 	current.tasks = malloc( current.n * sizeof( TaskStatus_t ) );
 	current.n = uxTaskGetSystemState( current.tasks, current.n, &current.total );
 	
-	static EXT_RAM_ATTR char scratch[128+1];
+	static EXT_RAM_ATTR char scratch[SCRATCH_SIZE];
 	*scratch = '\0';
 
 #ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
@@ -63,7 +64,8 @@ static void task_stats( void ) {
 	for(int i = 0, n = 0; i < current.n; i++ ) {
 		for (int j = 0; j < previous.n; j++) {
 			if (current.tasks[i].xTaskNumber == previous.tasks[j].xTaskNumber) {
-				n += sprintf(scratch + n, "%16s %2u%% s:%5u", current.tasks[i].pcTaskName, 
+				n += snprintf(scratch + n, SCRATCH_SIZE - n, "%16s (%u) %2u%% s:%5u", current.tasks[i].pcTaskName, 
+																		   current.tasks[i].eCurrentState,
 																		   100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed, 
 																		   current.tasks[i].usStackHighWaterMark);
 				if (i % 3 == 2 || i == current.n - 1) {
@@ -72,7 +74,7 @@ static void task_stats( void ) {
 				}	
 				break;
 			}
-		}	
+		}
 	}	
 #else
 	for (int i = 0, n = 0; i < current.n; i ++) {

+ 3 - 3
components/squeezelite/display.c

@@ -100,7 +100,7 @@ static struct {
 #define SB_HEIGHT		32
 
 // lenght are number of frames, i.e. 2 channels of 16 bits
-#define	FFT_LEN_BIT	6		
+#define	FFT_LEN_BIT	7		
 #define	FFT_LEN		(1 << FFT_LEN_BIT)
 #define RMS_LEN_BIT	6
 #define RMS_LEN		(1 << RMS_LEN_BIT)
@@ -739,10 +739,10 @@ static void visu_update(void) {
  */
 void spectrum_limits(int min, int n, int pos) {
 	if (n / 2) {
-		int step = ((DISPLAY_BW - min) * visu.spectrum_scale * 2) / n;
+		int step = ((DISPLAY_BW - min) * visu.spectrum_scale)  / (n/2);
 		visu.bars[pos].limit = min + step;
 		for (int i = 1; i < n/2; i++) visu.bars[pos+i].limit = visu.bars[pos+i-1].limit + step;
-		spectrum_limits(visu.bars[pos + n/2 - 1].limit, n/2, pos + n/2);
+		spectrum_limits(visu.bars[pos + n/2 - 1].limit, n - n/2, pos + n/2);
 	} else {
 		visu.bars[pos].limit = DISPLAY_BW;
 	}	

+ 11 - 6
components/squeezelite/embedded.h

@@ -6,6 +6,7 @@
 /* 	must provide 
 		- mutex_create_p
 		- pthread_create_name
+		- register_xxx (see below)
 		- stack size
 		- s16_t, s32_t, s64_t and u64_t
 		- PLAYER_ID / custom_player_id
@@ -16,6 +17,11 @@
 		- EXT_BSS 		
 	recommended to add platform specific include(s) here
 */	
+
+typedef int16_t   s16_t;
+typedef int32_t   s32_t;
+typedef int64_t   s64_t;
+typedef unsigned long long u64_t;
 	
 #ifndef PTHREAD_STACK_MIN
 #define PTHREAD_STACK_MIN	256
@@ -26,18 +32,17 @@
 #define OUTPUT_THREAD_STACK_SIZE  6 * 1024
 #define IR_THREAD_STACK_SIZE      6 * 1024
 
+// number of 5s times search for a server will happen beforee slimproto exits (0 = no limit)
+#define MAX_SERVER_RETRIES	5
+
 // or can be as simple as #define PLAYER_ID 100
-#define PLAYER_ID custom_player_id;
+#define PLAYER_ID custom_player_id
 extern u8_t custom_player_id;
 
 #define BASE_CAP "Model=squeezeesp32,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION
+// to force some special buffer attribute
 #define EXT_BSS __attribute__((section(".ext_ram.bss"))) 
 
-typedef int16_t   s16_t;
-typedef int32_t   s32_t;
-typedef int64_t   s64_t;
-typedef unsigned long long u64_t;
-
 // all exit() calls are made from main thread (or a function called in main thread)
 #define exit(code) { int ret = code; pthread_exit(&ret); }
 #define gettime_ms _gettime_ms_

+ 14 - 6
components/squeezelite/slimproto.c

@@ -773,7 +773,7 @@ void wake_controller(void) {
 	wake_signal(wake_e);
 }
 
-in_addr_t discover_server(char *default_server) {
+in_addr_t discover_server(char *default_server, int max) {
 	struct sockaddr_in d;
 	struct sockaddr_in s;
 	char buf[32], port_d[] = "JSON", clip_d[] = "CLIP";
@@ -827,7 +827,7 @@ in_addr_t discover_server(char *default_server) {
 			server_addr(default_server, &s.sin_addr.s_addr, &port);
 		}
 
-	} while (s.sin_addr.s_addr == 0 && running);
+	} while (s.sin_addr.s_addr == 0 && running && (!max || --max));
 
 	closesocket(disc_sock);
 
@@ -858,7 +858,7 @@ void slimproto(log_level level, char *server, u8_t mac[6], const char *name, con
 	}
 
 	if (!slimproto_ip) {
-		slimproto_ip = discover_server(server);
+		slimproto_ip = discover_server(server, 0);
 	}
 
 	if (!slimproto_port) {
@@ -937,10 +937,18 @@ void slimproto(log_level level, char *server, u8_t mac[6], const char *name, con
 				sleep(5);
 			}
 
-			// rediscover server if it was not set at startup
+#if EMBEDDED
+			// in embedded we give up after a while no matter what
+			if (++failed_connect > 5 && !server) {
+				slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL, MAX_SERVER_RETRIES);
+				if (!slimproto_ip) return;
+			} else if (MAX_SERVER_RETRIES && failed_connect > 5 * MAX_SERVER_RETRIES) return;
+#else
+			// rediscover server if it was not set at startup or exit 
 			if (!server && ++failed_connect > 5) {
-				slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL);
-			}
+				slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL, 0);
+			} 
+#endif	
 
 		} else {
 

+ 10 - 9
main/cmd_squeezelite.c

@@ -13,9 +13,8 @@
 #include "freertos/event_groups.h"
 #include "pthread.h"
 #include "platform_esp32.h"
-#include "nvs.h"
-#include "nvs_flash.h"
-//extern char current_namespace[];
+#include "config.h"
+
 static const char * TAG = "squeezelite_cmd";
 #define SQUEEZELITE_THREAD_STACK_SIZE (6*1024)
 extern int main(int argc, char **argv);
@@ -36,7 +35,7 @@ static void * squeezelite_runner_thread(){
 	main(thread_parms.argc,thread_parms.argv);
 	return NULL;
 }
-#define ADDITIONAL_SQUEEZELILTE_ARGS 5
+#define ADDITIONAL_SQUEEZELITE_ARGS 5
 static void * squeezelite_thread(){
 	int * exit_code;
 	static bool isRunning=false;
@@ -45,9 +44,6 @@ static void * squeezelite_thread(){
 		return NULL;
 	}
 	isRunning=true;
-//  Let's not wait on WiFi to allow squeezelite to run in bluetooth mode
-//	ESP_LOGI(TAG,"Waiting for WiFi.");
-//	while(!wait_for_wifi()){usleep(100000);};
 	ESP_LOGV(TAG ,"Number of args received: %u",thread_parms.argc );
 	ESP_LOGV(TAG ,"Values:");
     for(int i = 0;i<thread_parms.argc; i++){
@@ -73,6 +69,11 @@ static void * squeezelite_thread(){
 	ESP_LOGV(TAG ,"Freeing argv pointer");
 	free(thread_parms.argv);
 	isRunning=false;
+	ESP_LOGE(TAG, "Exited from squeezelite thread, something's wrong ... rebooting");
+	if(!wait_for_commit()){
+		ESP_LOGW(TAG,"Unable to commit configuration. ");
+	}
+    esp_restart();
 	return NULL;
 }
 
@@ -87,8 +88,8 @@ static int launchsqueezelite(int argc, char **argv)
     ESP_LOGV(TAG,"Saving args in thread structure");
 
     thread_parms.argc=0;
-    thread_parms.argv = malloc(sizeof(char**)*(argc+ADDITIONAL_SQUEEZELILTE_ARGS));
-	memset(thread_parms.argv,'\0',sizeof(char**)*(argc+ADDITIONAL_SQUEEZELILTE_ARGS));
+    thread_parms.argv = malloc(sizeof(char**)*(argc+ADDITIONAL_SQUEEZELITE_ARGS));
+	memset(thread_parms.argv,'\0',sizeof(char**)*(argc+ADDITIONAL_SQUEEZELITE_ARGS));
 
 	for(int i=0;i<argc;i++){
 		ESP_LOGD(TAG ,"assigning parm %u : %s",i,argv[i]);

+ 12 - 0
main/esp_app_main.c

@@ -73,6 +73,18 @@ extern void	display_init(char *welcome);
 
 /* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
 void cb_connection_got_ip(void *pvParameter){
+	static ip4_addr_t ip;
+	tcpip_adapter_ip_info_t ipInfo; 
+
+	tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
+	if (ip.addr && ipInfo.ip.addr != ip.addr) {
+		ESP_LOGW(TAG, "IP change, need to reboot");
+		if(!wait_for_commit()){
+			ESP_LOGW(TAG,"Unable to commit configuration. ");
+		}
+		esp_restart();
+	}
+	ip.addr = ipInfo.ip.addr;
 	ESP_LOGI(TAG, "I have a connection!");
 	xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
 	bWifiConnected=true;