2525#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
2626#include <mdns.h>
2727#endif
28+ #ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
29+ #include <esp_openthread.h>
30+ #include <esp_openthread_lock.h>
31+ #include <openthread/srp_client.h>
32+ #include <openthread/srp_client_buffers.h>
33+ #endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD */
2834#include <esp_rmaker_utils.h>
2935
3036#include <esp_idf_version.h>
@@ -272,6 +278,112 @@ static esp_err_t esp_rmaker_local_ctrl_service_disable(void)
272278 return ESP_OK ;
273279}
274280
281+ #ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
282+ #define SRP_MAX_HOST_NAME_LEN 32
283+ static char srp_host_name [SRP_MAX_HOST_NAME_LEN + 1 ];
284+
285+ static esp_err_t srp_client_set_host (const char * host_name )
286+ {
287+ if (!host_name || strlen (host_name ) > 15 ) {
288+ return ESP_ERR_INVALID_ARG ;
289+ }
290+ // Avoid adding the same host name multiple times
291+ if (strcmp (srp_host_name , host_name ) != 0 ) {
292+ strncpy (srp_host_name , host_name , SRP_MAX_HOST_NAME_LEN );
293+ srp_host_name [strnlen (host_name , SRP_MAX_HOST_NAME_LEN )] = 0 ;
294+ esp_openthread_lock_acquire (portMAX_DELAY );
295+ otInstance * instance = esp_openthread_get_instance ();
296+ if (otSrpClientSetHostName (instance , srp_host_name ) != OT_ERROR_NONE ) {
297+ esp_openthread_lock_release ();
298+ return ESP_FAIL ;
299+ }
300+ if (otSrpClientEnableAutoHostAddress (instance ) != OT_ERROR_NONE ) {
301+ esp_openthread_lock_release ();
302+ return ESP_FAIL ;
303+ }
304+ esp_openthread_lock_release ();
305+ }
306+ return ESP_OK ;
307+ }
308+
309+ static esp_err_t srp_client_add_local_ctrl_service (const char * serv_name )
310+ {
311+ static uint8_t rainmaker_node_id_txt_value [30 ];
312+ char * rmaker_node_id = esp_rmaker_get_node_id ();
313+ if (rmaker_node_id == NULL || strlen (rmaker_node_id ) > sizeof (rainmaker_node_id_txt_value )) {
314+ return ESP_ERR_INVALID_ARG ;
315+ }
316+ memcpy (rainmaker_node_id_txt_value , rmaker_node_id , strlen (rmaker_node_id ));
317+ const static uint8_t text_values [3 ][23 ] = {
318+ {'/' , 'e' , 's' , 'p' , '_' , 'l' , 'o' , 'c' , 'a' , 'l' , '_' , 'c' , 't' , 'r' , 'l' , '/' , 'v' , 'e' , 'r' , 's' , 'i' , 'o' , 'n' },
319+ {'/' , 'e' , 's' , 'p' , '_' , 'l' , 'o' , 'c' , 'a' , 'l' , '_' , 'c' , 't' , 'r' , 'l' , '/' , 's' , 'e' , 's' , 's' , 'i' , 'o' , 'n' },
320+ {'/' , 'e' , 's' , 'p' , '_' , 'l' , 'o' , 'c' , 'a' , 'l' , '_' , 'c' , 't' , 'r' , 'l' , '/' , 'c' , 'o' , 'n' , 't' , 'r' , 'o' , 'l' }};
321+ static otDnsTxtEntry txt_entries [4 ] = {
322+ {
323+ .mKey = "version_endpoint" ,
324+ .mValue = text_values [0 ],
325+ .mValueLength = 23 ,
326+ },
327+ {
328+ .mKey = "session_endpoint" ,
329+ .mValue = text_values [1 ],
330+ .mValueLength = 23 ,
331+ },
332+ {
333+ .mKey = "control_endpoint" ,
334+ .mValue = text_values [2 ],
335+ .mValueLength = 23 ,
336+ },
337+ {
338+ .mKey = "node_id" ,
339+ .mValue = rainmaker_node_id_txt_value ,
340+ .mValueLength = sizeof (rainmaker_node_id_txt_value ),
341+ }
342+ };
343+ txt_entries [3 ].mValueLength = (uint16_t )strlen (rmaker_node_id );
344+ static char s_serv_name [30 ];
345+ strncpy (s_serv_name , serv_name , strnlen (serv_name , sizeof (s_serv_name ) - 1 ));
346+ s_serv_name [strnlen (serv_name , sizeof (s_serv_name ) - 1 )] = 0 ;
347+ static otSrpClientService srp_client_service = {
348+ .mName = "_esp_local_ctrl._tcp" ,
349+ .mInstanceName = (const char * )s_serv_name ,
350+ .mTxtEntries = txt_entries ,
351+ .mPort = CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT ,
352+ .mNumTxtEntries = 4 ,
353+ .mNext = NULL ,
354+ .mLease = 0 ,
355+ .mKeyLease = 0 ,
356+ };
357+ esp_openthread_lock_acquire (portMAX_DELAY );
358+ otInstance * instance = esp_openthread_get_instance ();
359+ // Try to remove the service registered before adding a new service. If the previous service is not removed,
360+ // Adding service will fail with a duplicated instance error. This could happen when the device reboots, which
361+ // might result in the wrong resolved IP addresss on the phone app side.
362+ (void )otSrpClientRemoveService (instance , & srp_client_service );
363+ if (otSrpClientAddService (instance , & srp_client_service ) != OT_ERROR_NONE ) {
364+ esp_openthread_lock_release ();
365+ return ESP_FAIL ;
366+ }
367+ otSrpClientEnableAutoStartMode (instance , NULL , NULL );
368+ esp_openthread_lock_release ();
369+ return ESP_OK ;
370+ }
371+
372+ static esp_err_t srp_client_clean_up ()
373+ {
374+ esp_err_t ret = ESP_OK ;
375+ esp_openthread_lock_acquire (portMAX_DELAY );
376+ otInstance * instance = esp_openthread_get_instance ();
377+ if (otSrpClientRemoveHostAndServices (instance , false, true) != OT_ERROR_NONE ) {
378+ ret = ESP_FAIL ;
379+ }
380+ memset (srp_host_name , 0 , sizeof (srp_host_name ));
381+ esp_openthread_lock_release ();
382+ return ret ;
383+ }
384+
385+ #endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD */
386+
275387static esp_err_t __esp_rmaker_start_local_ctrl_service (const char * serv_name )
276388{
277389 if (!serv_name ) {
@@ -292,6 +404,9 @@ static esp_err_t __esp_rmaker_start_local_ctrl_service(const char *serv_name)
292404 mdns_hostname_set (serv_name );
293405#endif
294406
407+ #ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
408+ srp_client_set_host (serv_name );
409+ #endif
295410
296411 esp_local_ctrl_config_t config = {
297412 .transport = ESP_LOCAL_CTRL_TRANSPORT_HTTPD ,
@@ -353,6 +468,9 @@ static esp_err_t __esp_rmaker_start_local_ctrl_service(const char *serv_name)
353468 /* Add node_id in mdns */
354469 mdns_service_txt_item_set ("_esp_local_ctrl" , "_tcp" , "node_id" , esp_rmaker_get_node_id ());
355470#endif
471+ #ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
472+ srp_client_add_local_ctrl_service (serv_name );
473+ #endif
356474
357475 if (pop ) {
358476 free (pop );
@@ -511,6 +629,9 @@ esp_err_t esp_rmaker_local_ctrl_disable(void)
511629 }
512630#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI
513631 mdns_free ();
632+ #endif
633+ #ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD
634+ srp_client_clean_up ();
514635#endif
515636 esp_err_t err = esp_local_ctrl_stop ();
516637 if (err != ESP_OK ) {
0 commit comments