1 /*
2  * Percepio DFM v2.1.0
3  * Copyright 2023 Percepio AB
4  * www.percepio.com
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * DFM Cloud
9  */
10 
11 #include <dfm.h>
12 #include <stdio.h> /*cstat !MISRAC2012-Rule-21.6 We require snprintf() in order for the helper function to construct an MQTT topic*/
13 
14 #if ((DFM_CFG_ENABLED) >= 1)
15 
16 static DfmCloudData_t* pxCloudData = (void*)0;
17 
xDfmCloudInitialize(DfmCloudData_t * pxBuffer)18 DfmResult_t xDfmCloudInitialize(DfmCloudData_t* pxBuffer)
19 {
20 	if (pxBuffer == (void*)0)
21 	{
22 		return DFM_FAIL;
23 	}
24 
25 	if (xDfmCloudPortInitialize(&pxBuffer->xCloudPortData) == DFM_FAIL)
26 	{
27 		return DFM_FAIL;
28 	}
29 
30 	pxCloudData = pxBuffer;
31 
32 	pxCloudData->ulInitialized = 1;
33 
34 	return DFM_SUCCESS;
35 }
36 
xDfmCloudSendAlert(DfmEntryHandle_t xEntryHandle)37 DfmResult_t xDfmCloudSendAlert(DfmEntryHandle_t xEntryHandle)
38 {
39 	DfmCloudStrategy_t xCloudStrategy = DFM_CLOUD_STRATEGY_OFFLINE;
40 
41 	if (pxCloudData == (void*)0)
42 	{
43 		return DFM_FAIL;
44 	}
45 
46 	if (pxCloudData->ulInitialized == (uint32_t)0)
47 	{
48 		return DFM_FAIL;
49 	}
50 
51 	if (ulDfmSessionIsEnabled() == (uint32_t)0)
52 	{
53 		return DFM_FAIL;
54 	}
55 
56 	if (xEntryHandle == 0)
57 	{
58 		return DFM_FAIL;
59 	}
60 
61 	if (xDfmSessionGetCloudStrategy(&xCloudStrategy) == DFM_FAIL)
62 	{
63 		return DFM_FAIL;
64 	}
65 
66 	if (xCloudStrategy == DFM_CLOUD_STRATEGY_OFFLINE)
67 	{
68 		return DFM_FAIL;
69 	}
70 
71 	return xDfmCloudPortSendAlert(xEntryHandle);
72 }
73 
xDfmCloudSendPayloadChunk(DfmEntryHandle_t xEntryHandle)74 DfmResult_t xDfmCloudSendPayloadChunk(DfmEntryHandle_t xEntryHandle)
75 {
76 	DfmCloudStrategy_t xCloudStrategy = DFM_CLOUD_STRATEGY_OFFLINE;
77 
78 	if (pxCloudData == (void*)0)
79 	{
80 		return DFM_FAIL;
81 	}
82 
83 	if (pxCloudData->ulInitialized == (uint32_t)0)
84 	{
85 		return DFM_FAIL;
86 	}
87 
88 	if (ulDfmSessionIsEnabled() == (uint32_t)0)
89 	{
90 		return DFM_FAIL;
91 	}
92 
93 	if (xEntryHandle == 0)
94 	{
95 		return DFM_FAIL;
96 	}
97 
98 	if (xDfmSessionGetCloudStrategy(&xCloudStrategy) == DFM_FAIL)
99 	{
100 		return DFM_FAIL;
101 	}
102 
103 	if (xCloudStrategy == DFM_CLOUD_STRATEGY_OFFLINE)
104 	{
105 		return DFM_FAIL;
106 	}
107 
108 	return xDfmCloudPortSendPayloadChunk(xEntryHandle);
109 }
110 
xDfmCloudGenerateMQTTTopic(char * cTopicBuffer,uint32_t ulBufferSize,const char * szMQTTPrefix,DfmEntryHandle_t xEntryHandle)111 DfmResult_t xDfmCloudGenerateMQTTTopic(char* cTopicBuffer, uint32_t ulBufferSize, const char* szMQTTPrefix, DfmEntryHandle_t xEntryHandle)
112 {
113 	const char* szSessionId = (void*)0;
114 	const char* szDeviceName = (void*)0;
115 	uint32_t ulAlertId = (uint32_t)0;
116 	uint16_t usEntryId = (uint16_t)0;
117 	uint16_t usType = (uint16_t)0;
118 	uint16_t usChunkIndex = (uint16_t)0;
119 	uint16_t usChunkCount = (uint16_t)0;
120 	int32_t lRetVal;
121 
122 	if (pxCloudData == (void*)0)
123 	{
124 		return DFM_FAIL;
125 	}
126 
127 	if (pxCloudData->ulInitialized == (uint32_t)0)
128 	{
129 		return DFM_FAIL;
130 	}
131 
132 	if (cTopicBuffer == (void*)0)
133 	{
134 		return DFM_FAIL;
135 	}
136 
137 	if (ulBufferSize == (uint32_t)0)
138 	{
139 		return DFM_FAIL;
140 	}
141 
142 	if (xEntryHandle == 0)
143 	{
144 		return DFM_FAIL;
145 	}
146 
147 	if (xDfmEntryGetSessionId(xEntryHandle, &szSessionId) == DFM_FAIL)
148 	{
149 		return DFM_FAIL;
150 	}
151 
152 	if (xDfmEntryGetDeviceName(xEntryHandle, &szDeviceName) == DFM_FAIL)
153 	{
154 		return DFM_FAIL;
155 	}
156 
157 	if (xDfmEntryGetAlertId(xEntryHandle, &ulAlertId) == DFM_FAIL)
158 	{
159 		return DFM_FAIL;
160 	}
161 
162 	if (xDfmEntryGetType(xEntryHandle, &usType) == DFM_FAIL)
163 	{
164 		return DFM_FAIL;
165 	}
166 
167 	if (xDfmEntryGetEntryId(xEntryHandle, &usEntryId) == DFM_FAIL)
168 	{
169 		return DFM_FAIL;
170 	}
171 
172 	if (xDfmEntryGetChunkIndex(xEntryHandle, &usChunkIndex) == DFM_FAIL)
173 	{
174 		return DFM_FAIL;
175 	}
176 
177 	if (xDfmEntryGetChunkCount(xEntryHandle, &usChunkCount) == DFM_FAIL)
178 	{
179 		return DFM_FAIL;
180 	}
181 
182 	if (szMQTTPrefix == (void*)0)
183 	{
184 		/* Set it to empty */
185 		szMQTTPrefix = "";
186 	}
187 
188 	/* "<PREFIX>DevAlert/<DEVICE_NAME>/<UNIQUE_SESSION_ID>/<TRACE_COUNTER>/<SLICE_ID>-<TOTAL_EXPECTED_SLICES>_<PAYLOAD_TYPE>" */
189 	switch (usType)
190 	{
191 	case DFM_ENTRY_TYPE_ALERT:
192 		lRetVal = snprintf(cTopicBuffer, ulBufferSize, "%sDevAlert/%s/%s/%u/%u-%u_da_header", szMQTTPrefix, szDeviceName, szSessionId, (unsigned int)ulAlertId, (unsigned int)usChunkIndex, (unsigned int)usChunkCount);
193 		break;
194 	case DFM_ENTRY_TYPE_PAYLOAD_HEADER:
195 		lRetVal = snprintf(cTopicBuffer, ulBufferSize, "%sDevAlert/%s/%s/%u/%u-%u_da_payload%u_header", szMQTTPrefix, szDeviceName, szSessionId, (unsigned int)ulAlertId, (unsigned int)usChunkIndex, (unsigned int)usChunkCount, (unsigned int)usEntryId);
196 		break;
197 	case DFM_ENTRY_TYPE_PAYLOAD:
198 		lRetVal = snprintf(cTopicBuffer, ulBufferSize, "%sDevAlert/%s/%s/%u/%u-%u_da_payload%u", szMQTTPrefix, szDeviceName, szSessionId, (unsigned int)ulAlertId, (unsigned int)usChunkIndex, (unsigned int)usChunkCount, (unsigned int)usEntryId);
199 		break;
200 	default:
201 		return DFM_FAIL;
202 		break;
203 	}
204 
205 	/* TODO: Instead of doing an strlen after calling this function, we should reuse this value (pass a pointer to a len var or similar */
206 	if ((lRetVal < (int32_t)0) || (lRetVal >= (int32_t)ulBufferSize))
207 	{
208 		return DFM_FAIL;
209 	}
210 
211 	return DFM_SUCCESS;
212 }
213 
214 #endif
215