Thread 中讨论的其他器件:CC3220SF、 SysConfig、 SYSBIOS
您好!
我必须发送多个数据包(例如、 每秒10000个样本)从基于 HTTP 的 CC3220SF 服务器获取来自客户端的 HTTP GET 请求的 uint16_t 数据(原始 ADC 数据)。
有人能告诉我如何执行相同的操作吗?
谢谢你。
此致、
Kuldeep
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
您好!
我必须发送多个数据包(例如、 每秒10000个样本)从基于 HTTP 的 CC3220SF 服务器获取来自客户端的 HTTP GET 请求的 uint16_t 数据(原始 ADC 数据)。
有人能告诉我如何执行相同的操作吗?
谢谢你。
此致、
Kuldeep
谢谢 Jesse、
它帮助我了解了很多功能。
现在我的要求是 在每200ms 内发送大小为64*10=640的 uint16数组数据。
我尝试将数据直接复制到数据缓冲区结构中、如下所示-
//Created Buffer #define DATA_BUFFER_SIZE (1280) struct DataBufferStruct { int len; char data[DATA_BUFFER_SIZE]; }; extern struct DataBufferStruct DataBuffer; int send_data(void* dat, int len);
//Function to update the DataBuffer int send_data(void* data, int len) { // Append data to global DataBuffer if (DataBuffer.len + len >= DATA_BUFFER_SIZE+1) // Buffer overflow { sprintf(DataBuffer.data, "BUFFER OVERFLOW"); DataBuffer.len = strlen(DataBuffer.data); return -1; } memcpy(DataBuffer.data + DataBuffer.len, data, len); DataBuffer.len += len; return 0; }
//Test Thread to put the data in the DataBuffer after each 1 sec (for test). This thread will be used to receive the data from the ADC output. uint16_t testData[640] = {645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546,645,745,842,931,1011,1080,1138,1185,1222,1250,1270,1283,1290,1290,1283,1269,1247,1220,1188,1152,1114,1077,1041,1006,973,941,908,874,835,793,747,697,645,594,544,498,456,417,382,350,318,285,250,214,176,139,103,71,43,22,8,1,1,8,21,41,69,106,153,211,280,360,449,546}; //uint16_t testData[2] = {0x56BA, 0x2349}; /**/ void *testThread(void* arg0) { while (1) { send_data(testData, 1280); sleep(1); } }
//When there is a http request for the test data then below is the response for the same - int payload_len = strlen((const char*) gPayloadBuffer); // while (*argcCallback > 0) // { // ... // } // Copy all data from Global buffer to payload memcpy((void *)pPayload, DataBuffer.data, DataBuffer.len); payload_len += DataBuffer.len; // Null terminate the payload pPayload[DataBuffer.len] = '\0'; // Reset global Data Buffer DataBuffer.len = 0; //metadataLen = prepareGetMetadata(0, strlen((const char *)gPayloadBuffer), HttpContentTypeList_UrlEncoded); metadataLen = prepareGetMetadata(0, payload_len, HttpContentTypeList_UrlEncoded); metadataLen = prepareGetMetadata(0, strlen((const char *)gPayloadBuffer), HttpContentTypeList_UrlEncoded); sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); Display_printf(display, 0, 0, "[Http server task] Metadata Sent, len = %d ", metadataLen); sl_NetAppSend (netAppRequest->Handle, strlen ((const char *)gPayloadBuffer), gPayloadBuffer, 0); /* mark as last segment */ Display_printf(display, 0, 0, "[Http server task] Data Sent, len = %d", strlen ((const char *)gPayloadBuffer));
当我从笔记本电脑访问此请求时、对请求的响应如下所示、该笔记本电脑包含发送的数据、但它具有 C2、C3等、如下所示-
C28502C3A9024A03C2A303C3B3033804
7204C2A104C38604C3A204C3B6040305
0D0A050D0A050305C3B504C39F04C384
04C2A404C280045A0435041104C3AE03
C38D03C2AD03C28C036A0343031903C3
AB02C2B902C2850252022002C3B201C3
8801C2A1017E015E013E011D01C3BA
这太不完整了。
在这里有什么问题?
这是以二进制格式发送数据的正确方法吗?
我应该先转换字符串中的数组,然后再发送吗?
此致、
Kuldeep
Kuldeep、您好!
是的、您可以尝试将阵列转换为字符串、然后发送以查看其在笔记本电脑上是否正确显示。
您还可以从 SimpleLink Academy 中的开箱即用演示或此 Wi-Fi HTTP 服务器实验等已知工作示例开始、并根据您的用例对其进行编辑: https://dev.ti.com/tirex/explore/node?node=AKNlsGY7AbtkzVvTPm66qw__fc2e6sr__LATEST
HTTP 服务器实验室使用以下 HTTP 服务器文件: https://dev.ti.com/tirex/explore/node?node=ADokazZfJ2yBW-QoOaEHCw__fc2e6sr__LATEST
此致、
Jesse
您好 Jesse、
感谢您的参考。
我尝试发送字符串、这种情况正常。
但我不想以字符串的形式发送数据、因为我需要将整数数组转换为字符串、而大小也更多地用于字符串格式。 因此、总体而言、它将增加计算和存储器要求。
因此、我想直接从存储器发送数据。
那么、是否可以将这些数据作为 png 或其他格式发送。 我的最终动机是将数据存储在一个文件中、这样我就可以避免所需的进一步操作。
请建议是否可以执行除字符串以外的任何其他操作。
谢谢、此致、
Kuldeep
Kuldeep、您好!
可以尝试通过更新 prepareGetMetadata()函数中的内容类型以二进制格式发送数据。 HTTP 内容类型列表位于 httpserver.h 中 尝试使用 HttpContentTypeList_ApplicationOctecStream 而不是 HttpContentTypeList_urlencoded。
typedef enum { /* Content types list */ HttpContentTypeList_TextHtml, HttpContentTypeList_TextCSS, HttpContentTypeList_TextXML, HttpContentTypeList_ApplicationJson, HttpContentTypeList_ImagePNG, HttpContentTypeList_ImageGIF, HttpContentTypeList_TextPlain, HttpContentTypeList_TextCSV, HttpContentTypeList_ApplicationJavascript, HttpContentTypeList_ImageJPEG, HttpContentTypeList_ApplicationPDF, HttpContentTypeList_ApplicationZIP, HttpContentTypeList_ShokewaveFlash, HttpContentTypeList_AudioXAAC, HttpContentTypeList_ImageXIcon, HttpContentTypeList_TextVcard, HttpContentTypeList_ApplicationOctecStream, HttpContentTypeList_VideoAVI, HttpContentTypeList_VideoMPEG, HttpContentTypeList_VideoMP4, HttpContentTypeList_UrlEncoded, }HttpContentTypeList;
此致、
Jesse
您好 Jesse、
感谢您的建议。
我已将数据转换为字符串、它正在工作。
之后、我能够使用 SPI 将一些数据从 C2000发送到 CC3220SF、然后将这些数据发送到 HTTP 客户端。 从 C2000到 CC3220sf 的数据大小为640Bytes。 在发送任何数据之前、我在 CC3220SF 和 C2000之间具有握手(类似于主从演示代码)。 数据在每100ms 后发送一次。 每隔100ms,HTTP 客户端就会发出一个数据获取请求。 SPI 数据使用定时 MSGQUEUE 发送到 HTTP GET 回调、然后转换为字符串并作为请求的响应发送(如果队列为空、则1ms 后队列返回-1、发送字符串为空字符串)。
最初、我创建了另一个 GET 请求(用户从客户端输入)、该请求为握手布置一个信标、从而启动 SPI 通信、然后使用 msg 队列发布数据。 当在每100ms 之后有一个 GET 请求并且数据出现在队列中时,回调函数将处理数据以将其转换为字符串,然后使用 sl_NetAppSend()发送到客户端。 每当我收到用户的请求时、此操作就会起作用。 但是、当我尝试在每隔100ms 后连续发送数据(使用 SPI 在间隔100ms 内从 C2000接收数据、然后在队列中从 cc3220中的 SPI 线程发布到 Get 回调) 时、它会卡住并停止发送数据。
我试图弄清楚这个问题,但仍然没有成功。 您能提供同样的帮助吗?
谢谢、此致、
Kuldeep
Kuldeep、您好!
您是否设置了断点来查看代码何时/在哪里卡住?
当您说:
[~用户在处理此请求时,可引用 userid="518327" URL"/support/wireless-connectivity/wi-fi-group/wi-fi-fi-fi-forum/1098718/cc3220sf-launchxl-how-forthe-se-send-uint16_t-data-t-desktop-client-fer-fer-http-server-on-32980" cc411020/i 随时可以通过此用户请求。 但是、当我尝试在每隔100ms 后连续发送数据时(使用 SPI 在间隔100ms 内从 C2000接收数据、然后在队列中从 cc3220中的 SPI 线程发布到 Get 回调) 、数据将被卡住并停止发送数据。您是否说它在您响应来自客户端的 GET 请求发送数据时起作用? 如果它被卡住并停止发送数据,是否在没有客户机的 GET 请求的情况下调用 sl_NetAppSend()?
此致、
Jesse
您好 Jesse、
我有两个 Get 请求、如下所示-
1。
var rawDataStart = true; function getRawData(){ if(rawDataStart) { ajaxCall('/raw', "GET", "raw", respRaw); } }
这在每100ms 后调用、如下所示-
function startRawData() { rawDataInterval = setInterval(getRawData, 100); }
服务器对此的响应如下所示-
int32_t rawGetCallback(uint8_t requestIdx, uint8_t *argcCallback, uint8_t **argvCallback, SlNetAppRequest_t *netAppRequest) { uint8_t *pPayload; uint16_t metadataLen; int16_t i, msgSize; int32_t retVal; char rawDataStr[1300]; uint16_t queueMsg[320]; struct timespec rawts; /* timeout is 0 to send the message immediatelly */ rawts.tv_sec = 1; rawts.tv_nsec = 0; pPayload = gPayloadBuffer; retVal =mq_timedreceive(i1DataMQueue, (char *)&queueMsg, 640, 0, &rawts); if(retVal < 0) { strcpy(rawDataStr, ""); } else { clock_gettime(CLOCK_REALTIME, &rawts); sprintf( &rawDataStr[0], "%d,",rawts.tv_sec); for(i = 0; i < 319;i++) { sprintf( &rawDataStr[ strlen(rawDataStr) ], "%d,", queueMsg[i] ); } sprintf( &rawDataStr[ strlen(rawDataStr) ], "%d", queueMsg[319] ); } // Prepares payload sl_Memcpy (pPayload,rawDataStr, strlen(rawDataStr)); msgSize = strlen(rawDataStr); pPayload += msgSize; /* NULL terminate the payload */ *(pPayload) = '\0'; metadataLen = prepareGetMetadata(0, msgSize, HttpContentTypeList_TextPlain); sl_NetAppSend (netAppRequest->Handle, metadataLen, gMetadataBuffer, (SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION | SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA)); Display_printf(display, 0, 0, "[Http server task] Metadata Sent, len = %d ", metadataLen); pPayload = gPayloadBuffer; if(msgSize > 1024) { sl_NetAppSend (netAppRequest->Handle, 1024, pPayload, SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION); /* middle segment */ pPayload +=1024; msgSize -=1024; } sl_NetAppSend (netAppRequest->Handle, msgSize, pPayload, 0); /* mark as last segment */ return 0; }
当 SPI 转换可用时、它从 SPI 转换中获取数据、否则在经过时间后、当计时队列中没有数据时、它只返回-1。将其转换为字符串并作为响应发送。
2.同时,在浏览器中按按钮会调用用户请求。
//I have linked the user request with LED ON OFF because with this I can know if the user request is properly placed or not function rawDataGet(val){ var vsend = "redled="+val; ajaxCall('/usrRqst', "post", vsend, rawDataGetResp); if($('#lightCircle').hasClass('lightOff')){ $('#lightCircle').removeClass('lightOff'); $('#lightCircle').addClass('lightOn'); } else { if($('#lightCircle').hasClass('lightOn')){ $('#lightCircle').removeClass('lightOn'); $('#lightCircle').addClass('lightOff'); } } }
POSTuserCallback 将会 post_SEM ()、而 userThread 中的 SEM 等待将被执行、这将启用与 C2000的握手、然后 SPI 转换开始。 完成后将执行 SEND_QUEU()。
因为 URL 和线程都是独立的、所以这不会有任何问题。
您在此过程中是否看到任何问题?
因为 同时 涉及到与 C2000和 HTTP 客户端的 SPI 和 HTTP 通信、所以由于 C2000和 cc3220SF 之间的握手、无法将断点置于所需位置。
我能够一次将320个数据从 C2000发送到 cc3220sf (SPI)、并将 cc3220sf 发送到 http 客户端(使用 http) 在 http 客户端发出用户请求时、但有时不会发生这种情况、因为握手会停止、但在 C2000和 c3220sf 之间的 SPI 数据传输之前没有 http 握手会在任何时间内正常工作。
请告诉我您的建议。
谢谢、此致、
Kuldeep
您好 Kuldeep、
您上面的第二点似乎是:
[~引语 userid="518327" URL"//support-wireless-connectivity/wi-fi-group/wi-fi-fi-fi-forum/1098718/cc3220sf-launchxl-how-forthe-se-send-uint16_t-data-t-to 桌面客户端-fer-http-server-on-3220_cc12414414/12412]12414/12412'。 同时、在浏览器中按下按钮会调用用户请求。您能不能澄清应用程序陷入困境意味着什么? 是否未从 C2000接收数据? 数据是否未从 CC3220SF 发送到 HTTP 客户端以响应 GET 请求?
您应该能够放置断点或向 Get 回调函数添加调试输出以进一步调试。
此致、
Jesse
您好 Jesse、
感谢您的建议。
Get Callback 处的断点正在工作。 我能够看到数据已从 C2000正确接收。 并能够将数据发送到 http 客户端。
您对其发布请求的第二点是正确的。 我没有用原始数据回复该请求。 原始数据是另一个 Get 调用的响应、即 ajaxCall ('/raw)、"get"、"raw (原始)"、"respRaw (重新生成))。 当我接收到 POST 请求时、我只是在 CC3220SF 上发布一个用于主机 GPIO 状态更改的信标、该信标将在 C2000上创建一个外部中断。 C2000将启动 SPI 通信。
接收到数据后、Get 请求的响应回调函数 将从队列中获取数据(SPI 线程上的 SPI RX 中的数据)。
问题并非始终存在、当我尝试获取多个用户请求、然后在一段时间后 SPI 传输停止时、就会发生这种情况。
此外、当我尝试发送 Application/OctecStream 数据时、它会将一些数据设置为"\xEF\xBF\xBD\x0f"、而数据是"\xe1\x0f"或0x0FE1。 您能帮助您获取正确的数据吗? 问题是 gzip 还是放气编码? 如果是、如何解决?
谢谢、此致、
Kuldeep
您好 Jesse、
我已经尝试调试了这个问题、 我觉得这个问题是由于通过 HTTP 同时使用 SPI 以及 C2000和 CC3220SF 之间的通信。
每当我执行替代数据传输(首先在 cc3220SF 和 C2000之间 传输数据、然后从 CC3220SF 向 HTTP 客户端发送数据)时、其工作效果都非常好。
下面是 SysConfig 快照。
您能不能建议我如何在 http 传输请求和 CC3220-C2000 SPI 通信之间放置互斥量? 或任何其他方法来解决此问题。
根据文档、网络 SPI 与通用 SPI 不同。 是我的理解不正确或我上面所做的配置不正确。
谢谢、此致、
Kuldeep
Kuldeep、您好!
您可以尝试重新发布 SysConfig 快照吗? 我无法在您之前的帖子中看到它。
正确、用于与 NWP 通信的 SPI 与通用 SPI 不同。
至于实现互斥量:
此致、
Jesse
您好 Jesse、
请找到以下 SPI 配置的 SysConfig 快照-
此外、您能否建议队列是否已满、是否会导致问题、或者数据将随 下一个数据改写。
我正在尝试使用队列将 SPI 数据发送到 http 获取响应。
关于互斥、我问在哪里将互斥锁放置在 http 请求中、以便它不会阻止 SPI。
当我在 getcallback 和 SPI 传输中使用 mutext lock 时、它会执行它的操作、但如果队列已满、它会卡住。
问题出在哪呢?
谢谢、
此致、
Kuldeep
您好 Jesse、
我再次尝试调试、发现如果我将 ADC 输入连接到使用 SPI 连接到 CC3220SF 的 C2000。 当我从客户端发出 HTTP 请求时、我看到我的 CC3220SF 正像下面那样卡住-
您能否检查此问题是否已知、或者我为何卡在那里。
当我从客户端向 CC3220SF HTTP 服务器发出请求而不将 Input 连接到 C2000时。 我能够将数据发送到客户端、并且它不会陷入这个无限循环。
它是否与某些硬件问题有关?
谢谢你。
此致、
Kuldeep
您好 Kuldeep、
你可能会因为几个不同的原因而陷入 一个 Hwi 中。 它可能是堆栈溢出、或者您可能在中断例程中做了一些不当操作。
您可以使用 CCS 中的调试功能和工具获取有关此功能的更多信息: https://dev.ti.com/tirex/content/simplelink_academy_cc32xxsdk_6_10_00_00/modules/rtos/tirtos_basics/tirtos_basics.html#debugging-features-and-tools
运行时对象视图和系统分析器应有助于继续调试。
此致、
Jesse
您好 Jesse、
感谢您的建议。
我会尝试相同的方法、然后再返回给您。
是否有机会使用相同的 SPI 资源与 C2000进行 http 通信和通信? 我之所以提出这个问题、是因为当我在 http 发送响应和 SPI 数据传输之间使用互斥量时、它开始处理某些用户请求。
您能否告诉我使用 SPI 进行 HTTP 通信以及将 SPI 数据传输到其他 MCU 或其他器件的任何示例?
谢谢你。
此致、
Kuldeep
您好 Jesse、
感谢您的回答。
我还有一个问题。
我们是否可以传输超过 1364的数据作为 GET 请求的响应?
我尝试在段之间保留 SL_NetApp_Request_Response_FLAGS_Continuation 标志、但会发生超时。
您能给出一个示例、其中在 HTTP 协议中传输了超过1364个数据作为 GET 请求的响应。
谢谢你。
此致、
Kuldeep
您好 Kuldeep、
见 《NWP 指南》第9.7.2.1节的分段。 "碎片必须用于传输大于1500字节的资源(单个碎片的最大大小)。 虽然需要发送更多片段,但 必须在 API 的 flags 参数中设置 sl_NetApp_Request_Response_FLAGS_Continuation 位。 在最后一个片段上、该位必须为零。 对 SL_NetAppSend API 的第一次调用必须承载响应的元数据(HTTP 标头)。 为此、 必须在 API 的 flags 参数中设置 sl_netapp_request_response _FLAGS_metadata 位。
图9-11的第2部分 显示了具有碎片的 GET 请求、第181页(恰好在第9.7.3节后处理之前)上的示例代码显示了使用碎片的示例。
此致、
Jesse