1 /*
2 * Percepio DFM v2.0.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/%ld/%d-%d_da_header", szMQTTPrefix, szDeviceName, szSessionId, ulAlertId, usChunkIndex, usChunkCount);
193 break;
194 case DFM_ENTRY_TYPE_PAYLOAD_HEADER:
195 lRetVal = snprintf(cTopicBuffer, ulBufferSize, "%sDevAlert/%s/%s/%ld/%d-%d_da_payload%d_header", szMQTTPrefix, szDeviceName, szSessionId, ulAlertId, usChunkIndex, usChunkCount, usEntryId);
196 break;
197 case DFM_ENTRY_TYPE_PAYLOAD:
198 lRetVal = snprintf(cTopicBuffer, ulBufferSize, "%sDevAlert/%s/%s/%ld/%d-%d_da_payload%d", szMQTTPrefix, szDeviceName, szSessionId, ulAlertId, usChunkIndex, usChunkCount, 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