<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Problem with HTTP and PSM on Thingy:91</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/78056/problem-with-http-and-psm-on-thingy-91</link><description>Hello, 
 I&amp;#39;m trying to develop an application sending GPS over HTTP requests. 
 I started from the &amp;quot;https client&amp;quot; and &amp;quot;agps&amp;quot; samples in the NRF Connect SDK: the single examples work fine. 
 I&amp;#39;m having trouble in merging the http example into the agps</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 06 Aug 2021 12:23:50 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/78056/problem-with-http-and-psm-on-thingy-91" /><item><title>RE: Problem with HTTP and PSM on Thingy:91</title><link>https://devzone.nordicsemi.com/thread/323734?ContentTypeID=1</link><pubDate>Fri, 06 Aug 2021 12:23:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fec7e427-1684-4547-a4d1-00c1c1a58dd2</guid><dc:creator>Carl Richard</dc:creator><description>&lt;p&gt;Hello again!&lt;br /&gt;&lt;br /&gt;That&amp;#39;s interesting! There may be an issue priorities or calling the http_send() from an interrupt handler. Could you try to implement the send function as a work item, and post it to the queue from the button handler instead?&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Carl Richard&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem with HTTP and PSM on Thingy:91</title><link>https://devzone.nordicsemi.com/thread/322809?ContentTypeID=1</link><pubDate>Mon, 02 Aug 2021 08:46:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:400acb26-1528-40f9-8c3a-03d3760f448e</guid><dc:creator>MarcoRivolta</dc:creator><description>&lt;p&gt;Hi Carl,&lt;/p&gt;
&lt;p&gt;thank you for your answer.&lt;/p&gt;
&lt;p&gt;This is the main.c file:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#define HTTP_TEST 1
#define AZURE_TEST 1

#include &amp;lt;zephyr.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;modem/lte_lc.h&amp;gt;
#include &amp;lt;net/cloud.h&amp;gt;
#include &amp;lt;net/socket.h&amp;gt;
#include &amp;lt;dk_buttons_and_leds.h&amp;gt;
#include &amp;lt;drivers/gps.h&amp;gt;
#include &amp;lt;sys/reboot.h&amp;gt;
#if defined(CONFIG_NRF_CLOUD_PGPS)
#include &amp;lt;net/nrf_cloud_agps.h&amp;gt;
#include &amp;lt;net/nrf_cloud_pgps.h&amp;gt;
#include &amp;lt;date_time.h&amp;gt;
#include &amp;lt;pm_config.h&amp;gt;
#endif




#if HTTP_TEST
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;modem/nrf_modem_lib.h&amp;gt;
#include &amp;lt;net/tls_credentials.h&amp;gt;
#include &amp;lt;modem/lte_lc.h&amp;gt;
#include &amp;lt;modem/at_cmd.h&amp;gt;
#include &amp;lt;modem/at_notif.h&amp;gt;
#include &amp;lt;modem/modem_key_mgmt.h&amp;gt;

#define HTTPS_PORT 443
#if AZURE_TEST
#define HTTP_HEAD                                   \
	&amp;quot;POST /api/dummy HTTP/1.1\r\n&amp;quot;              \
	&amp;quot;Host: XXX-dev-iot.azurewebsites.net\r\n&amp;quot;   \
        &amp;quot;Content-Type: application/json\r\n&amp;quot;        \
        &amp;quot;Content-Length: 0\r\n&amp;quot;                     \
        &amp;quot;Connection: close\r\n\r\n&amp;quot;
#else
#define HTTP_HEAD                                                              \
	&amp;quot;HEAD / HTTP/1.1\r\n&amp;quot;                                                  \
	&amp;quot;Host: example.com:443\r\n&amp;quot;                                            \
	&amp;quot;Connection: close\r\n\r\n&amp;quot;
#endif                 

#define HTTP_HEAD_LEN (sizeof(HTTP_HEAD) - 1)
#define HTTP_HDR_END &amp;quot;\r\n\r\n&amp;quot;
#define RECV_BUF_SIZE 2048
#define TLS_SEC_TAG 42
static const char send_buf[] = HTTP_HEAD;
static char recv_buf[RECV_BUF_SIZE];
/* Certificate for `example.com` */
static const char cert[] = {
#if AZURE_TEST
	#include &amp;quot;../cert/azurewebsites-net.pem&amp;quot;
#else
	#include &amp;quot;../cert/DigiCertGlobalRootCA.pem&amp;quot;
#endif
};
BUILD_ASSERT(sizeof(cert) &amp;lt; KB(4), &amp;quot;Certificate too large&amp;quot;);

int http_send(void);
#endif

#include &amp;lt;logging/log.h&amp;gt;

#define SERVICE_INFO_GPS &amp;quot;{\&amp;quot;state\&amp;quot;:{\&amp;quot;reported\&amp;quot;:{\&amp;quot;device\&amp;quot;: \
			  {\&amp;quot;serviceInfo\&amp;quot;:{\&amp;quot;ui\&amp;quot;:[\&amp;quot;GPS\&amp;quot;]}}}}}&amp;quot;

LOG_MODULE_REGISTER(agps_sample, CONFIG_AGPS_SAMPLE_LOG_LEVEL);

static struct cloud_backend *cloud_backend;
static const struct device *gps_dev;
static uint64_t start_search_timestamp;
static uint64_t fix_timestamp;
static struct k_work gps_start_work;
static struct k_work_delayable reboot_work;

#if defined(CONFIG_NRF_CLOUD_PGPS)
static struct k_work manage_pgps_work;
static struct k_work notify_pgps_work;
static struct gps_agps_request agps_request;
#endif

static void gps_start_work_fn(struct k_work *work);

#if defined(CONFIG_NRF_CLOUD_PGPS)
static struct nrf_cloud_pgps_prediction *prediction;

void pgps_handler(enum nrf_cloud_pgps_event event,
		  struct nrf_cloud_pgps_prediction *p)
{
	/* GPS unit asked for it, but we didn&amp;#39;t have it; check now */
	LOG_INF(&amp;quot;event: %d&amp;quot;, event);
	if (event == PGPS_EVT_AVAILABLE) {
		prediction = p;
		k_work_submit(&amp;amp;manage_pgps_work);
	}
}

static void manage_pgps(struct k_work *work)
{
	ARG_UNUSED(work);
	int err;

	LOG_INF(&amp;quot;Sending prediction to modem...&amp;quot;);
	err = nrf_cloud_pgps_inject(prediction, &amp;amp;agps_request, NULL);
	if (err) {
		LOG_ERR(&amp;quot;Unable to send prediction to modem: %d&amp;quot;, err);
	}

	err = nrf_cloud_pgps_preemptive_updates();
	if (err) {
		LOG_ERR(&amp;quot;Error requesting updates: %d&amp;quot;, err);
	}
}

static void notify_pgps(struct k_work *work)
{
	ARG_UNUSED(work);
	int err;

	err = nrf_cloud_pgps_notify_prediction();
	if (err) {
		LOG_ERR(&amp;quot;error requesting notification of prediction availability: %d&amp;quot;, err);
	}
}
#endif

static void cloud_send_msg(void)
{
	int err;

	LOG_DBG(&amp;quot;Publishing message: %s&amp;quot;, log_strdup(CONFIG_CLOUD_MESSAGE));

	struct cloud_msg msg = {
		.qos = CLOUD_QOS_AT_MOST_ONCE,
		.endpoint.type = CLOUD_EP_MSG,
		.buf = CONFIG_CLOUD_MESSAGE,
		.len = sizeof(CONFIG_CLOUD_MESSAGE)
	};

	err = cloud_send(cloud_backend, &amp;amp;msg);
	if (err) {
		LOG_ERR(&amp;quot;cloud_send failed, error: %d&amp;quot;, err);
	}
}

static void gps_start_work_fn(struct k_work *work)
{
	int err;
	struct gps_config gps_cfg = {
		.nav_mode = GPS_NAV_MODE_PERIODIC,
		.power_mode = GPS_POWER_MODE_DISABLED,
		.timeout = 120,
		.interval = 240,
		.priority = true,
	};

	ARG_UNUSED(work);

#if defined(CONFIG_NRF_CLOUD_PGPS)
	static bool initialized;

	if (!initialized) {
		struct nrf_cloud_pgps_init_param param = {
			.event_handler = pgps_handler,
			.storage_base = PM_MCUBOOT_SECONDARY_ADDRESS,
			.storage_size = PM_MCUBOOT_SECONDARY_SIZE};

		err = nrf_cloud_pgps_init(&amp;amp;param);
		if (err) {
			LOG_ERR(&amp;quot;Error from PGPS init: %d&amp;quot;, err);
		} else {
			initialized = true;
		}
	}
#endif

	err = gps_start(gps_dev, &amp;amp;gps_cfg);
	if (err) {
		LOG_ERR(&amp;quot;Failed to start GPS, error: %d&amp;quot;, err);
		return;
	}

	LOG_INF(&amp;quot;Periodic GPS search started with interval %d s, timeout %d s&amp;quot;,
		gps_cfg.interval, gps_cfg.timeout);
}

static void on_agps_needed(struct gps_agps_request request)
{
#if defined(CONFIG_AGPS)
	int err = gps_agps_request_send(request, GPS_SOCKET_NOT_PROVIDED);

	if (err) {
		LOG_ERR(&amp;quot;Failed to request A-GPS data, error: %d&amp;quot;, err);
		return;
	}
#endif
#if defined(CONFIG_NRF_CLOUD_PGPS)
	/* AGPS data not expected, so move on to PGPS */
	if (!nrf_cloud_agps_request_in_progress()) {
		k_work_submit(&amp;amp;notify_pgps_work);
	}
#endif
}

static void send_service_info(void)
{
	int err;
	struct cloud_msg msg = {
		.qos = CLOUD_QOS_AT_MOST_ONCE,
		.endpoint.type = CLOUD_EP_STATE,
		.buf = SERVICE_INFO_GPS,
		.len = strlen(SERVICE_INFO_GPS)
	};

	err = cloud_send(cloud_backend, &amp;amp;msg);
	if (err) {
		LOG_ERR(&amp;quot;Failed to send message to cloud, error: %d&amp;quot;, err);
		return;
	}

	LOG_INF(&amp;quot;Service info sent to cloud&amp;quot;);
}

static void cloud_event_handler(const struct cloud_backend *const backend,
				const struct cloud_event *const evt,
				void *user_data)
{
	int err = 0;

	ARG_UNUSED(backend);
	ARG_UNUSED(user_data);

	switch (evt-&amp;gt;type) {
	case CLOUD_EVT_CONNECTING:
		LOG_INF(&amp;quot;CLOUD_EVT_CONNECTING&amp;quot;);
		break;
	case CLOUD_EVT_CONNECTED:
		LOG_INF(&amp;quot;CLOUD_EVT_CONNECTED&amp;quot;);
		break;
	case CLOUD_EVT_READY:
		LOG_INF(&amp;quot;CLOUD_EVT_READY&amp;quot;);
		/* Update nRF Cloud with GPS service info signifying that it
		 * has GPS capabilities. */
		send_service_info();
		k_work_submit(&amp;amp;gps_start_work);
		break;
	case CLOUD_EVT_DISCONNECTED:
		LOG_INF(&amp;quot;CLOUD_EVT_DISCONNECTED&amp;quot;);
		break;
	case CLOUD_EVT_ERROR:
		LOG_INF(&amp;quot;CLOUD_EVT_ERROR&amp;quot;);
		break;
	case CLOUD_EVT_DATA_SENT:
		LOG_INF(&amp;quot;CLOUD_EVT_DATA_SENT&amp;quot;);
		break;
	case CLOUD_EVT_DATA_RECEIVED:
		LOG_INF(&amp;quot;CLOUD_EVT_DATA_RECEIVED&amp;quot;);

		/* Convenience functionality for remote testing.
		 * The device is reset if it receives &amp;quot;{&amp;quot;reboot&amp;quot;:true}&amp;quot;
		 * from the cloud. The command can be sent using the terminal
		 * card on the device page on nrfcloud.com.
		 */
		if (evt-&amp;gt;data.msg.buf[0] == &amp;#39;{&amp;#39;) {
			int ret = strncmp(evt-&amp;gt;data.msg.buf,
				      &amp;quot;{\&amp;quot;reboot\&amp;quot;:true}&amp;quot;,
				      strlen(&amp;quot;{\&amp;quot;reboot\&amp;quot;:true}&amp;quot;));

			if (ret == 0) {
				/* The work item may already be scheduled
				 * because of the button being pressed,
				 * so use rescheduling here to get the work
				 * submitted with no delay.
				 */
				k_work_reschedule(&amp;amp;reboot_work, K_NO_WAIT);
			}
			break;
		}

#if defined(CONFIG_AGPS)
		err = gps_process_agps_data(evt-&amp;gt;data.msg.buf, evt-&amp;gt;data.msg.len);
		if (!err) {
			LOG_INF(&amp;quot;A-GPS data processed&amp;quot;);
#if defined(CONFIG_NRF_CLOUD_PGPS)
			/* call us back when prediction is ready */
			k_work_submit(&amp;amp;notify_pgps_work);
#endif
			/* data was valid; no need to pass to other handlers */
			break;
		}
#endif
#if defined(CONFIG_NRF_CLOUD_PGPS)
		err = nrf_cloud_pgps_process(evt-&amp;gt;data.msg.buf, evt-&amp;gt;data.msg.len);
		if (err) {
			LOG_ERR(&amp;quot;Error processing PGPS packet: %d&amp;quot;, err);
		}
#else
		if (err) {
			LOG_INF(&amp;quot;Unable to process agps data, error: %d&amp;quot;, err);
		}
#endif
		break;
	case CLOUD_EVT_PAIR_REQUEST:
		LOG_INF(&amp;quot;CLOUD_EVT_PAIR_REQUEST&amp;quot;);
		break;
	case CLOUD_EVT_PAIR_DONE:
		LOG_INF(&amp;quot;CLOUD_EVT_PAIR_DONE&amp;quot;);
		break;
	case CLOUD_EVT_FOTA_DONE:
		LOG_INF(&amp;quot;CLOUD_EVT_FOTA_DONE&amp;quot;);
		break;
	case CLOUD_EVT_FOTA_ERROR:
		LOG_INF(&amp;quot;CLOUD_EVT_FOTA_ERROR&amp;quot;);
		break;
	default:
		LOG_INF(&amp;quot;Unknown cloud event type: %d&amp;quot;, evt-&amp;gt;type);
		break;
	}
}

static void print_pvt_data(struct gps_pvt *pvt_data)
{
	char buf[300];
	size_t len;

	len = snprintf(buf, sizeof(buf),
		      &amp;quot;\r\n\tLongitude:  %f\r\n\t&amp;quot;
		      &amp;quot;Latitude:   %f\r\n\t&amp;quot;
		      &amp;quot;Altitude:   %f\r\n\t&amp;quot;
		      &amp;quot;Speed:      %f\r\n\t&amp;quot;
		      &amp;quot;Heading:    %f\r\n\t&amp;quot;
		      &amp;quot;Date:       %02u-%02u-%02u\r\n\t&amp;quot;
		      &amp;quot;Time (UTC): %02u:%02u:%02u\r\n&amp;quot;,
		      pvt_data-&amp;gt;longitude, pvt_data-&amp;gt;latitude,
		      pvt_data-&amp;gt;altitude, pvt_data-&amp;gt;speed, pvt_data-&amp;gt;heading,
		      pvt_data-&amp;gt;datetime.year, pvt_data-&amp;gt;datetime.month,
		      pvt_data-&amp;gt;datetime.day, pvt_data-&amp;gt;datetime.hour,
		      pvt_data-&amp;gt;datetime.minute, pvt_data-&amp;gt;datetime.seconds);
	if (len &amp;lt; 0) {
		LOG_ERR(&amp;quot;Could not construct PVT print&amp;quot;);
	} else {
		LOG_INF(&amp;quot;%s&amp;quot;, log_strdup(buf));
	}
}

static void print_satellite_stats(struct gps_pvt *pvt_data)
{
	uint8_t tracked = 0;
	uint32_t tracked_sats = 0;
	static uint32_t prev_tracked_sats;
	char print_buf[100];
	size_t print_buf_len;

	for (int i = 0; i &amp;lt; GPS_PVT_MAX_SV_COUNT; ++i) {
		if ((pvt_data-&amp;gt;sv[i].sv &amp;gt; 0) &amp;amp;&amp;amp;
		    (pvt_data-&amp;gt;sv[i].sv &amp;lt; 33)) {
			tracked++;
			tracked_sats |= BIT(pvt_data-&amp;gt;sv[i].sv - 1);
		}
	}

	if ((tracked_sats == 0) || (tracked_sats == prev_tracked_sats)) {
		if (tracked_sats != prev_tracked_sats) {
			prev_tracked_sats = tracked_sats;
			LOG_DBG(&amp;quot;Tracking no satellites&amp;quot;);
		}

		return;
	}

	prev_tracked_sats = tracked_sats;
	print_buf_len = snprintk(print_buf, sizeof(print_buf), &amp;quot;Tracking:  &amp;quot;);

	for (size_t i = 0; i &amp;lt; 32; i++) {
		if (tracked_sats &amp;amp; BIT(i)) {
			print_buf_len +=
				snprintk(&amp;amp;print_buf[print_buf_len - 1],
					 sizeof(print_buf) - print_buf_len,
					 &amp;quot;%d  &amp;quot;, i + 1);
			if (print_buf_len &amp;lt; 0) {
				LOG_ERR(&amp;quot;Failed to print satellite stats&amp;quot;);
				break;
			}
		}
	}

	LOG_INF(&amp;quot;%s&amp;quot;, log_strdup(print_buf));
	LOG_DBG(&amp;quot;Searching for %lld seconds&amp;quot;,
		(k_uptime_get() - start_search_timestamp) / 1000);
}

static void send_nmea(char *nmea)
{
	int err;
	char buf[150];
	struct cloud_msg msg = {
		.qos = CLOUD_QOS_AT_MOST_ONCE,
		.endpoint.type = CLOUD_EP_MSG,
		.buf = buf,
	};

	msg.len = snprintf(buf, sizeof(buf),
		&amp;quot;{&amp;quot;
			&amp;quot;\&amp;quot;appId\&amp;quot;:\&amp;quot;GPS\&amp;quot;,&amp;quot;
			&amp;quot;\&amp;quot;data\&amp;quot;:\&amp;quot;%s\&amp;quot;,&amp;quot;
			&amp;quot;\&amp;quot;messageType\&amp;quot;:\&amp;quot;DATA\&amp;quot;&amp;quot;
		&amp;quot;}&amp;quot;, nmea);
	if (msg.len &amp;lt; 0) {
		LOG_ERR(&amp;quot;Failed to create GPS cloud message&amp;quot;);
		return;
	}

	err = cloud_send(cloud_backend, &amp;amp;msg);
	if (err) {
		LOG_ERR(&amp;quot;Failed to send message to cloud, error: %d&amp;quot;, err);
		return;
	}
#if HTTP_TEST
        http_send();
#endif
	LOG_INF(&amp;quot;GPS position sent to cloud&amp;quot;);
        k_work_submit(&amp;amp;gps_start_work);
}

static void gps_handler(const struct device *dev, struct gps_event *evt)
{
	ARG_UNUSED(dev);

	switch (evt-&amp;gt;type) {
	case GPS_EVT_SEARCH_STARTED:
		LOG_INF(&amp;quot;GPS_EVT_SEARCH_STARTED&amp;quot;);
		start_search_timestamp = k_uptime_get();
		break;
	case GPS_EVT_SEARCH_STOPPED:
		LOG_INF(&amp;quot;GPS_EVT_SEARCH_STOPPED&amp;quot;);
		break;
	case GPS_EVT_SEARCH_TIMEOUT:
		LOG_INF(&amp;quot;GPS_EVT_SEARCH_TIMEOUT&amp;quot;);
		break;
	case GPS_EVT_OPERATION_BLOCKED:
		LOG_INF(&amp;quot;GPS_EVT_OPERATION_BLOCKED&amp;quot;);
		break;
	case GPS_EVT_OPERATION_UNBLOCKED:
		LOG_INF(&amp;quot;GPS_EVT_OPERATION_UNBLOCKED&amp;quot;);
		break;
	case GPS_EVT_AGPS_DATA_NEEDED:
		LOG_INF(&amp;quot;GPS_EVT_AGPS_DATA_NEEDED&amp;quot;);
#if defined(CONFIG_NRF_CLOUD_PGPS)
		LOG_INF(&amp;quot;A-GPS request from modem; emask:0x%08X amask:0x%08X utc:%u &amp;quot;
			&amp;quot;klo:%u neq:%u tow:%u pos:%u int:%u&amp;quot;,
			evt-&amp;gt;agps_request.sv_mask_ephe, evt-&amp;gt;agps_request.sv_mask_alm,
			evt-&amp;gt;agps_request.utc, evt-&amp;gt;agps_request.klobuchar,
			evt-&amp;gt;agps_request.nequick, evt-&amp;gt;agps_request.system_time_tow,
			evt-&amp;gt;agps_request.position, evt-&amp;gt;agps_request.integrity);
		memcpy(&amp;amp;agps_request, &amp;amp;evt-&amp;gt;agps_request, sizeof(agps_request));
#endif
		on_agps_needed(evt-&amp;gt;agps_request);
		break;
	case GPS_EVT_PVT:
		print_satellite_stats(&amp;amp;evt-&amp;gt;pvt);
		break;
	case GPS_EVT_PVT_FIX:
		fix_timestamp = k_uptime_get();

		LOG_INF(&amp;quot;---------       FIX       ---------&amp;quot;);
		LOG_INF(&amp;quot;Time to fix: %d seconds&amp;quot;,
			(uint32_t)(fix_timestamp - start_search_timestamp) / 1000);
		print_pvt_data(&amp;amp;evt-&amp;gt;pvt);
		LOG_INF(&amp;quot;-----------------------------------&amp;quot;);
#if defined(CONFIG_NRF_CLOUD_PGPS) &amp;amp;&amp;amp; defined(CONFIG_PGPS_STORE_LOCATION)
		nrf_cloud_pgps_set_location(evt-&amp;gt;pvt.latitude, evt-&amp;gt;pvt.longitude);
#endif
		break;
	case GPS_EVT_NMEA_FIX:
		send_nmea(evt-&amp;gt;nmea.buf);
		break;
	default:
		break;
	}
}

static void reboot_work_fn(struct k_work *work)
{
	LOG_WRN(&amp;quot;Rebooting in 2 seconds...&amp;quot;);
	k_sleep(K_SECONDS(2));
	sys_reboot(0);
}

static void work_init(void)
{
	k_work_init(&amp;amp;gps_start_work, gps_start_work_fn);
	k_work_init_delayable(&amp;amp;reboot_work, reboot_work_fn);

#if defined(CONFIG_NRF_CLOUD_PGPS)
	k_work_init(&amp;amp;manage_pgps_work, manage_pgps);
	k_work_init(&amp;amp;notify_pgps_work, notify_pgps);
#endif
}

static int modem_configure(void)
{
	int err = 0;

	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
		/* Do nothing, modem is already turned on
		 * and connected.
		 */
	} else {
		LOG_INF(&amp;quot;Connecting to LTE network. This may take minutes.&amp;quot;);

#if defined(CONFIG_LTE_POWER_SAVING_MODE)
		err = lte_lc_psm_req(true);
		if (err) {
			LOG_ERR(&amp;quot;PSM request failed, error: %d&amp;quot;, err);
			return err;
		}
                
		LOG_INF(&amp;quot;PSM mode requested&amp;quot;);
#endif

		err = lte_lc_init_and_connect();
		if (err) {
			LOG_ERR(&amp;quot;LTE link could not be established, error: %d&amp;quot;,
				err);
			return err;
		}

		LOG_INF(&amp;quot;Connected to LTE network&amp;quot;);
	}

	return err;
}

static void button_handler(uint32_t button_states, uint32_t has_changed)
{
	if (has_changed &amp;amp; button_states &amp;amp; DK_BTN1_MSK) {

		//cloud_send_msg();
                http_send();

		k_work_schedule(&amp;amp;reboot_work, K_SECONDS(3));
	} else if (has_changed &amp;amp; ~button_states &amp;amp; DK_BTN1_MSK) {
		k_work_cancel_delayable(&amp;amp;reboot_work);
	}
}

#if defined(CONFIG_DATE_TIME)
static void date_time_event_handler(const struct date_time_evt *evt)
{
	case DATE_TIME_OBTAINED_MODEM:
	switch (evt-&amp;gt;type) {
		LOG_INF(&amp;quot;DATE_TIME_OBTAINED_MODEM&amp;quot;);
		break;
	case DATE_TIME_OBTAINED_NTP:
		LOG_INF(&amp;quot;DATE_TIME_OBTAINED_NTP&amp;quot;);
		break;
	case DATE_TIME_OBTAINED_EXT:
		LOG_INF(&amp;quot;DATE_TIME_OBTAINED_EXT&amp;quot;);
		break;
	case DATE_TIME_NOT_OBTAINED:
		LOG_INF(&amp;quot;DATE_TIME_NOT_OBTAINED&amp;quot;);
		break;
	default:
		break;
	}
}
#endif


#if HTTP_TEST
/* Provision certificate to modem */
int cert_provision(void)
{
	int err;
	bool exists;
	uint8_t unused;

	err = modem_key_mgmt_exists(TLS_SEC_TAG,
				    MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN,
				    &amp;amp;exists, &amp;amp;unused);
	if (err) {
		printk(&amp;quot;Failed to check for certificates err %d\n&amp;quot;, err);
		return err;
	}

	if (exists) {
		/* For the sake of simplicity we delete what is provisioned
		 * with our security tag and reprovision our certificate.
		 */
		err = modem_key_mgmt_delete(TLS_SEC_TAG,
					    MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN);
		if (err) {
			printk(&amp;quot;Failed to delete existing certificate, err %d\n&amp;quot;,
			       err);
		}
	}

	printk(&amp;quot;Provisioning certificate\n&amp;quot;);

	/*  Provision certificate to the modem */
	err = modem_key_mgmt_write(TLS_SEC_TAG,
				   MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN,
				   cert, sizeof(cert) - 1);
	if (err) {
		printk(&amp;quot;Failed to provision certificate, err %d\n&amp;quot;, err);
		return err;
	}

	return 0;
}

/* Setup TLS options on a given socket */
int tls_setup(int fd)
{
	int err;
	int verify;

	/* Security tag that we have provisioned the certificate with */
	const sec_tag_t tls_sec_tag[] = {
		TLS_SEC_TAG,
	};

	/* Set up TLS peer verification */
	enum {
		NONE = 0,
		OPTIONAL = 1,
		REQUIRED = 2,
	};

	verify = REQUIRED;

	err = setsockopt(fd, SOL_TLS, TLS_PEER_VERIFY, &amp;amp;verify, sizeof(verify));
	if (err) {
		printk(&amp;quot;Failed to setup peer verification, err %d\n&amp;quot;, errno);
		return err;
	}

	/* Associate the socket with the security tag
	 * we have provisioned the certificate with.
	 */
	err = setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST, tls_sec_tag,
			 sizeof(tls_sec_tag));
	if (err) {
		printk(&amp;quot;Failed to setup TLS sec tag, err %d\n&amp;quot;, errno);
		return err;
	}

	return 0;
}

int http_send()
{
        int err;
	int fd;
	char *p;
	int bytes;
	size_t off;
	struct addrinfo *res;
	struct addrinfo hints = {
		.ai_family = AF_INET,
		.ai_socktype = SOCK_STREAM,
	};

#if AZURE_TEST  
	err = getaddrinfo(&amp;quot;XXX-dev-iot.azurewebsites.net&amp;quot;, NULL, &amp;amp;hints, &amp;amp;res);
#else
	err = getaddrinfo(&amp;quot;example.com&amp;quot;, NULL, &amp;amp;hints, &amp;amp;res);
#endif
        if (err) {
		printk(&amp;quot;getaddrinfo() failed, err %d\n&amp;quot;, errno);
		return;
	}

	((struct sockaddr_in *)res-&amp;gt;ai_addr)-&amp;gt;sin_port = htons(HTTPS_PORT);

	fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
	if (fd == -1) {
		printk(&amp;quot;Failed to open socket!\n&amp;quot;);
		goto clean_up;
	}

	/* Setup TLS socket options */
	err = tls_setup(fd);
	if (err) {
		goto clean_up;
	}

#if AZURE_TEST       
	printk(&amp;quot;Connecting to %s\n&amp;quot;, &amp;quot;XXX-dev-iot.azurewebsites.net&amp;quot;);
#else
	printk(&amp;quot;Connecting to %s\n&amp;quot;, &amp;quot;example.com&amp;quot;);
#endif
        err = connect(fd, res-&amp;gt;ai_addr, sizeof(struct sockaddr_in));
	if (err) {
		printk(&amp;quot;connect() failed, err: %d\n&amp;quot;, errno);
		goto clean_up;
	}

	off = 0;
	do {
		bytes = send(fd, &amp;amp;send_buf[off], HTTP_HEAD_LEN - off, 0);
		if (bytes &amp;lt; 0) {
			printk(&amp;quot;send() failed, err %d\n&amp;quot;, errno);
			goto clean_up;
		}
		off += bytes;
	} while (off &amp;lt; HTTP_HEAD_LEN);
        
	printk(&amp;quot;Sent %d bytes\n&amp;quot;, off);
        
	off = 0;
	do {
		bytes = recv(fd, &amp;amp;recv_buf[off], RECV_BUF_SIZE - off, 0);
		if (bytes &amp;lt; 0) {
			printk(&amp;quot;recv() failed, err %d\n&amp;quot;, errno);
			goto clean_up;
		}
		off += bytes;
	} while (bytes != 0 /* peer closed connection */);
        
	printk(&amp;quot;Received %d bytes\n&amp;quot;, off);
        
	/* Print HTTP response */
	p = strstr(recv_buf, &amp;quot;\r\n&amp;quot;);
	if (p) {
		off = p - recv_buf;
		recv_buf[off + 1] = &amp;#39;\0&amp;#39;;
		printk(&amp;quot;\n&amp;gt;\t %s\n\n&amp;quot;, recv_buf);
	}

       	printk(&amp;quot;Finished, closing socket.\n&amp;quot;);


clean_up:
	freeaddrinfo(res);
	(void)close(fd);
        return 0;
}
#endif


void main(void)
{
	int err;

	LOG_INF(&amp;quot;A-GPS sample has started&amp;quot;);

	cloud_backend = cloud_get_binding(&amp;quot;NRF_CLOUD&amp;quot;);
	__ASSERT(cloud_backend, &amp;quot;Could not get binding to cloud backend&amp;quot;);

	err = cloud_init(cloud_backend, cloud_event_handler);
	if (err) {
		LOG_ERR(&amp;quot;Cloud backend could not be initialized, error: %d&amp;quot;,
			err);
		return;
	}

#if HTTP_TEST
	/* Provision certificates before connecting to the LTE network */
	err = cert_provision();
	if (err) {
		return;
	}
#endif

	work_init();

	err = modem_configure();
	if (err) {
		LOG_ERR(&amp;quot;Modem configuration failed with error %d&amp;quot;,
			err);
		return;
	}

#if HTTP_TEST
        http_send();
#endif

	gps_dev = device_get_binding(&amp;quot;NRF9160_GPS&amp;quot;);
	if (gps_dev == NULL) {
		LOG_ERR(&amp;quot;Could not get binding to nRF9160 GPS&amp;quot;);
		return;
	}

	err = gps_init(gps_dev, gps_handler);
	if (err) {
		LOG_ERR(&amp;quot;Could not initialize GPS, error: %d&amp;quot;, err);
		return;
	}

	err = dk_buttons_init(button_handler);
	if (err) {
		LOG_ERR(&amp;quot;Buttons could not be initialized, error: %d&amp;quot;, err);
		LOG_WRN(&amp;quot;Continuing without button funcitonality&amp;quot;);
	}

#if defined(CONFIG_DATE_TIME)
	date_time_update_async(date_time_event_handler);
#endif

	err = cloud_connect(cloud_backend);
	if (err) {
		LOG_ERR(&amp;quot;Cloud connection failed, error: %d&amp;quot;, err);
		return;
	}

	/* The cloud connection is polled in a thread in the backend.
	 * Events will be received to cloud_event_handler() when data is
	 * received from the cloud.
	 */
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You can see that the http request is sent by&amp;nbsp;&lt;strong&gt;http_send&lt;/strong&gt;() function.&lt;/p&gt;
&lt;p&gt;MaybeI I was wrong about the PSM... I tried to add &amp;quot;Connection: close&amp;quot; to the http message and now&amp;nbsp;&lt;strong&gt;http_send&lt;/strong&gt;&lt;span&gt;() works when called inside the main function.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;However, when I call&amp;nbsp;&lt;strong&gt;http_send&lt;/strong&gt;() from the&amp;nbsp;&lt;strong&gt;button_handler&lt;/strong&gt;() function, the problem persists.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Here is the log:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;D: Tracking: 0 Using: 0 Unhealthy: 0&lt;br /&gt;D: Seconds since last fix 58&lt;br /&gt;D: Waiting for time window to operate&lt;br /&gt;I: GPS_EVT_OPERATION_BLOCKED&lt;br /&gt;D: GPS has time window to operate&lt;br /&gt;I: GPS_EVT_OPERATION_UNBLOCKED&lt;br /&gt;D: Tracking: 0 Using: 0 Unhealthy: 0&lt;br /&gt;D: Seconds since last fix 67&lt;br /&gt;D: Tracking: 0 Using: 0 Unhealthy: 0&lt;br /&gt;D: Seconds since last fix 68&lt;br /&gt;%CESQ: 58,2,30,4&lt;br /&gt;&lt;span style="background-color:#ffff00;"&gt;+CSCON: 1&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color:#ffff00;"&gt;Connecting to XXX-dev-iot.azurewebsites.net&lt;/span&gt;&lt;br /&gt;D: Waiting for time window to operate&lt;br /&gt;I: GPS_EVT_OPERATION_BLOCKED&lt;br /&gt;%CESQ: 56,2,25,3&lt;br /&gt;&lt;span style="background-color:#ffff00;"&gt;Sent 135 bytes&lt;/span&gt;&lt;br /&gt;%CESQ: 57,2,31,4&lt;br /&gt;&lt;span style="background-color:#ffff00;"&gt;+CSCON: 0&lt;/span&gt;&lt;br /&gt;D: GPS has time window to operate&lt;br /&gt;I: GPS_EVT_OPERATION_UNBLOCKED&lt;br /&gt;I: Tracking: 7&lt;br /&gt;D: Tracking SV 7: not used, healthy&lt;br /&gt;D: Tracking: 1 Using: 0 Unhealthy: 0&lt;br /&gt;D: Seconds since last fix 89&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Problem with HTTP and PSM on Thingy:91</title><link>https://devzone.nordicsemi.com/thread/322668?ContentTypeID=1</link><pubDate>Fri, 30 Jul 2021 12:36:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d2ee107d-10b5-40f2-ab9e-ff165ba44be6</guid><dc:creator>Carl Richard</dc:creator><description>&lt;p&gt;Hello!&lt;br /&gt;&lt;br /&gt;Could I have a look at how you have merged the samples? From what I can see you are correct that the device enters a not connected state after transmission. Could you try to&amp;nbsp;experiment with other&amp;nbsp;&lt;span&gt;CONFIG_LTE_PSM_REQ_RAT values? Some values could be rejected by the network provider.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Carl Richard&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>