@@ -98,6 +98,7 @@ typedef struct {
98
98
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE ;
99
99
100
100
static mdns_server_obj_t mdns ;
101
+ static uint32_t web_api_port = 80 ;
101
102
102
103
static socketpool_socketpool_obj_t pool ;
103
104
static socketpool_socket_obj_t listening ;
@@ -189,6 +190,9 @@ void supervisor_web_workflow_status(void) {
189
190
}
190
191
191
192
mp_printf (& mp_plat_print , "%s" , _our_ip_encoded );
193
+ if (web_api_port != 80 ) {
194
+ mp_printf (& mp_plat_print , ":%d" , web_api_port );
195
+ }
192
196
// TODO: Use these unicode to show signal strength: ▂▄▆█
193
197
}
194
198
} else {
@@ -199,11 +203,6 @@ void supervisor_web_workflow_status(void) {
199
203
void supervisor_start_web_workflow (void ) {
200
204
#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI
201
205
202
- if (common_hal_wifi_radio_get_enabled (& common_hal_wifi_radio_obj ) &&
203
- wifi_radio_get_ipv4_address (& common_hal_wifi_radio_obj ) != 0 ) {
204
- // Already started.
205
- return ;
206
- }
207
206
208
207
char ssid [33 ];
209
208
char password [64 ];
@@ -218,15 +217,20 @@ void supervisor_start_web_workflow(void) {
218
217
password_len <= 0 || (size_t )password_len >= sizeof (password )) {
219
218
return ;
220
219
}
221
- common_hal_wifi_init (false);
222
- common_hal_wifi_radio_set_enabled (& common_hal_wifi_radio_obj , true);
220
+ if (!common_hal_wifi_radio_get_enabled (& common_hal_wifi_radio_obj )) {
221
+ common_hal_wifi_init (false);
222
+ common_hal_wifi_radio_set_enabled (& common_hal_wifi_radio_obj , true);
223
+ }
223
224
224
225
// TODO: Do our own scan so that we can find the channel we want before calling connect.
225
226
// Otherwise, connect will do a full slow scan to pick the best AP.
226
227
227
228
// NUL terminate the strings because dotenv doesn't.
228
229
ssid [ssid_len ] = '\0' ;
229
230
password [password_len ] = '\0' ;
231
+ // We can all connect again because it will return early if we're already connected to the
232
+ // network. If we are connected to a different network, then it will disconnect before
233
+ // attempting to connect to the given network.
230
234
wifi_status = common_hal_wifi_radio_connect (
231
235
& common_hal_wifi_radio_obj , (uint8_t * )ssid , ssid_len , (uint8_t * )password , password_len ,
232
236
0 , 0.1 , NULL , 0 );
@@ -236,21 +240,46 @@ void supervisor_start_web_workflow(void) {
236
240
return ;
237
241
}
238
242
239
- mdns_server_construct (& mdns , true);
240
- common_hal_mdns_server_set_instance_name (& mdns , MICROPY_HW_BOARD_NAME );
241
- common_hal_mdns_server_advertise_service (& mdns , "_circuitpython" , "_tcp" , 80 );
243
+ char port_encoded [6 ];
244
+ size_t port_len = 0 ;
245
+ size_t new_port = web_api_port ;
246
+ #if CIRCUITPY_DOTENV
247
+ port_len = dotenv_get_key ("/.env" , "CIRCUITPY_WEB_API_PORT" , port_encoded , sizeof (port_encoded ) - 1 );
248
+ #endif
249
+ if (0 < port_len && port_len < sizeof (port_encoded )) {
250
+ new_port = strtoul (port_encoded , NULL , 10 );
251
+ }
252
+
253
+ bool first_start = mdns .base .type != & mdns_server_type ;
254
+ bool port_changed = new_port != web_api_port ;
242
255
243
- pool .base .type = & socketpool_socketpool_type ;
244
- common_hal_socketpool_socketpool_construct (& pool , & common_hal_wifi_radio_obj );
256
+ if (first_start ) {
257
+ ESP_LOGI (TAG , "Starting web workflow" );
258
+ mdns_server_construct (& mdns , true);
259
+ mdns .base .type = & mdns_server_type ;
260
+ common_hal_mdns_server_set_instance_name (& mdns , MICROPY_HW_BOARD_NAME );
261
+ pool .base .type = & socketpool_socketpool_type ;
262
+ common_hal_socketpool_socketpool_construct (& pool , & common_hal_wifi_radio_obj );
245
263
246
- ESP_LOGI (TAG , "Starting web workflow" );
247
- listening .base .type = & socketpool_socket_type ;
248
- socketpool_socket (& pool , SOCKETPOOL_AF_INET , SOCKETPOOL_SOCK_STREAM , & listening );
249
- common_hal_socketpool_socket_settimeout (& listening , 0 );
250
- // Bind to any ip.
251
- // TODO: Make this port .env configurable.
252
- common_hal_socketpool_socket_bind (& listening , "" , 0 , 80 );
253
- common_hal_socketpool_socket_listen (& listening , 1 );
264
+ listening .base .type = & socketpool_socket_type ;
265
+ active .base .type = & socketpool_socket_type ;
266
+ active .num = -1 ;
267
+ active .connected = false;
268
+
269
+ websocket_init ();
270
+ }
271
+ if (port_changed ) {
272
+ common_hal_socketpool_socket_close (& listening );
273
+ }
274
+ if (first_start || port_changed ) {
275
+ web_api_port = new_port ;
276
+ common_hal_mdns_server_advertise_service (& mdns , "_circuitpython" , "_tcp" , web_api_port );
277
+ socketpool_socket (& pool , SOCKETPOOL_AF_INET , SOCKETPOOL_SOCK_STREAM , & listening );
278
+ common_hal_socketpool_socket_settimeout (& listening , 0 );
279
+ // Bind to any ip.
280
+ common_hal_socketpool_socket_bind (& listening , "" , 0 , web_api_port );
281
+ common_hal_socketpool_socket_listen (& listening , 1 );
282
+ }
254
283
255
284
mp_int_t api_password_len = dotenv_get_key ("/.env" , "CIRCUITPY_WEB_API_PASSWORD" , _api_password + 1 , sizeof (_api_password ) - 2 );
256
285
if (api_password_len > 0 ) {
@@ -259,12 +288,6 @@ void supervisor_start_web_workflow(void) {
259
288
_base64_in_place (_api_password , api_password_len + 1 , sizeof (_api_password ));
260
289
}
261
290
262
- active .base .type = & socketpool_socket_type ;
263
- active .num = -1 ;
264
- active .connected = false;
265
-
266
- websocket_init ();
267
-
268
291
// TODO:
269
292
// GET /cp/serial.txt
270
293
// - Most recent 1k of serial output.
@@ -529,7 +552,13 @@ static void _reply_redirect(socketpool_socket_obj_t *socket, _request *request,
529
552
_send_str (socket , "http" );
530
553
}
531
554
532
- _send_strs (socket , "://" , hostname , ".local" , path , "\r\n" , NULL );
555
+ _send_strs (socket , "://" , hostname , ".local" , NULL );
556
+ if (web_api_port != 80 ) {
557
+ char encoded_port [6 ];
558
+ snprintf (encoded_port , sizeof (encoded_port ), "%d" , web_api_port );
559
+ _send_strs (socket , ":" , encoded_port , NULL );
560
+ }
561
+ _send_strs (socket , path , "\r\n" , NULL );
533
562
_cors_header (socket , request );
534
563
_send_str (socket , "\r\n" );
535
564
}
@@ -647,7 +676,7 @@ static void _reply_with_devices_json(socketpool_socket_obj_t *socket, _request *
647
676
}
648
677
const char * hostname = common_hal_mdns_remoteservice_get_hostname (& found_devices [i ]);
649
678
const char * instance_name = common_hal_mdns_remoteservice_get_instance_name (& found_devices [i ]);
650
- char port_encoded [4 ];
679
+ char port_encoded [6 ];
651
680
int port = common_hal_mdns_remoteservice_get_port (& found_devices [i ]);
652
681
snprintf (port_encoded , sizeof (port_encoded ), "%d" , port );
653
682
char ip_encoded [4 * 4 ];
@@ -675,6 +704,8 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request *
675
704
char encoded_creation_id [11 ]; // 2 ** 32 is 10 decimal digits plus one for \0
676
705
snprintf (encoded_creation_id , sizeof (encoded_creation_id ), "%u" , CIRCUITPY_CREATION_ID );
677
706
const char * hostname = common_hal_mdns_server_get_hostname (& mdns );
707
+ char encoded_port [6 ];
708
+ snprintf (encoded_port , sizeof (encoded_port ), "%d" , web_api_port );
678
709
_send_chunks (socket ,
679
710
"{\"web_api_version\": 1, " ,
680
711
"\"version\": \"" , MICROPY_GIT_TAG , "\", " ,
@@ -685,7 +716,7 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request *
685
716
"\"creator_id\": " , encoded_creator_id , ", " ,
686
717
"\"creation_id\": " , encoded_creation_id , ", " ,
687
718
"\"hostname\": \"" , hostname , "\", " ,
688
- "\"port\": 80 , " ,
719
+ "\"port\": " , encoded_port , " , " ,
689
720
"\"ip\": \"" , _our_ip_encoded ,
690
721
"\"}" , NULL );
691
722
// Empty chunk signals the end of the response.
@@ -1173,7 +1204,9 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
1173
1204
request -> authenticated = memcmp (request -> header_value , prefix , strlen (prefix )) == 0 &&
1174
1205
strcmp (_api_password , request -> header_value + strlen (prefix )) == 0 ;
1175
1206
} else if (strcmp (request -> header_key , "Host" ) == 0 ) {
1176
- request -> redirect = strcmp (request -> header_value , "circuitpython.local" ) == 0 ;
1207
+ // Do a prefix check so that port is ignored.
1208
+ const char * cp_local = "circuitpython.local" ;
1209
+ request -> redirect = memcmp (request -> header_value , cp_local , strlen (cp_local )) == 0 ;
1177
1210
} else if (strcmp (request -> header_key , "Content-Length" ) == 0 ) {
1178
1211
request -> content_length = strtoul (request -> header_value , NULL , 10 );
1179
1212
} else if (strcmp (request -> header_key , "Expect" ) == 0 ) {
0 commit comments