ProviewR Programmer's Reference Manual  V6.1.4
rt_mh_appl.c
Go to the documentation of this file.
1 /*
2  * ProviewR Open Source Process Control.
3  * Copyright (C) 2005-2025 SSAB EMEA AB.
4  *
5  * This file is part of ProviewR.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation, either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with ProviewR. If not, see <http://www.gnu.org/licenses/>
19  *
20  * Linking ProviewR statically or dynamically with other modules is
21  * making a combined work based on ProviewR. Thus, the terms and
22  * conditions of the GNU General Public License cover the whole
23  * combination.
24  *
25  * In addition, as a special exception, the copyright holders of
26  * ProviewR give you permission to, from the build function in the
27  * ProviewR Configurator, combine ProviewR with modules generated by the
28  * ProviewR PLC Editor to a PLC program, regardless of the license
29  * terms of these modules. You may copy and distribute the resulting
30  * combined work under the terms of your choice, provided that every
31  * copy of the combined work is accompanied by a complete copy of
32  * the source code of ProviewR (the version used to produce the
33  * combined work), being distributed under the terms of the GNU
34  * General Public License plus this exception.
35  */
36 
37 /* rt_mh_appl.c -- Runtime environment - Message Handler */
38 
43 #include <stdio.h>
44 #include <string.h>
45 
46 #include "co_time.h"
47 #include "rt_mh_def.h"
48 #include "rt_qcom_msg.h"
49 #include "rt_mh_util.h"
50 
52 typedef struct {
53  mh_sHead head;
54  qcom_sQid handler;
55  mh_eApplState state;
56 } sApplContext;
57 
58 /* Local variables */
59 
60 static sApplContext lAppl;
61 
62 /* Local function prototypes */
63 
64 static pwr_tStatus sendAndReceive(mh_eMsg, pwr_tUInt32, void*, mh_uApplReply*);
65 
76  pwr_tUInt32 id,
77  pwr_tString80* cancelText
79  )
80 {
81  pwr_tStatus sts;
82  mh_sApplReturn cancel;
83 
84  /* Check parameters */
85 
86  if (cancelText == NULL)
87  memset(&cancel.ReturnText, 0, sizeof(cancel.ReturnText));
88  else
89  strncpy(cancel.ReturnText, (char*)cancelText, sizeof(*cancelText));
90 
91  cancel.TargetIdx = id;
92  cancel.ReturnType = mh_eEvent_Cancel;
93 
94  sts = sendAndReceive(mh_eMsg_ApplReturn, sizeof(cancel), &cancel, NULL);
95 
96  return sts;
97 }
98 
99 /*
100 *@example mh_examples.c
101 */
102 
113  pwr_tObjid applObject,
128  flags,
129  const pwr_tString80 abortEventName,
134  mh_eEvent abortEventType,
135  mh_eEventPrio abortEventPrio,
139  mh_mEventFlags abortEventFlags,
144  const pwr_tString80 abortEventText,
150  pwr_tUInt32* activeMessages
157  )
158 {
159  pwr_tStatus sts;
160  pwr_tClassId cid;
161  mh_sApplConnect connect;
162  mh_uApplReply reply;
163  qcom_sQid qid = qcom_cNQid;
164  char name[32];
165  qcom_sNode myNode;
166  qcom_sQattr qAttr;
167 
168  mh_UtilWaitForMh();
169 
170  sprintf(name, "MhAppl_%X", applObject.oix);
171 
172  if (!qcom_Init(&sts, NULL, name)) {
173  errh_Error("Failed connecting application to QCOM\n%m", sts);
174  return MH__QCOMCONAPPL;
175  }
176 
177  qAttr.type = qcom_eQtype_private;
178  qAttr.quota = 100;
179  if (!qcom_CreateQ(&sts, &qid, &qAttr, name)) {
180  errh_Error("Failed to create QCOM que\n%m", sts);
181  return MH__QCOMCREQ;
182  }
183 
184  qcom_MyNode(&sts, &myNode);
185  lAppl.head.platform.os = myNode.os;
186  lAppl.head.platform.hw = myNode.hw;
187 
188  /* Check Application object */
189 
190  if (applObject.vid
191  != pwr_cNVolumeId) { /* Application object should exist in Rtdb */
192  sts = gdh_GetObjectClass(applObject, &cid);
193  if (EVEN(sts))
194  return sts;
195  switch (cid) {
196  case pwr_eClass_Appl:
197  case pwr_cClass_OpAppl:
198  case pwr_cClass_Application:
199  break;
200  default:
201  return MH__NOAPPL;
202  }
203  }
204 
205  lAppl.head.xdr = FALSE; /* To local handler only */
206  lAppl.head.ver = mh_cVersion;
207  lAppl.head.source = mh_eSource_Application;
208  net_GetTime(&lAppl.head.birthTime);
209  lAppl.head.qid = qid;
210  lAppl.head.aid = applObject;
211  lAppl.handler.nid = qid.nid;
212  lAppl.handler.qix = mh_cProcHandler;
213 
214  connect.ApplObject = applObject;
215  connect.Qid = qid;
216  connect.Flags = flags;
217  strncpy(
218  connect.AbortEventName, abortEventName, sizeof(connect.AbortEventName));
219  connect.AbortEventType = abortEventType;
220  connect.AbortEventPrio = abortEventPrio;
221  connect.AbortEventFlags = abortEventFlags;
222  strncpy(
223  connect.AbortEventText, abortEventText, sizeof(connect.AbortEventText));
224 
225  sts = sendAndReceive(mh_eMsg_ApplConnect, sizeof(connect), &connect, &reply);
226  if (EVEN(sts))
227  return sts;
228 
229  if (activeMessages != NULL)
230  *activeMessages = reply.Connect.NoOfActMessages;
231 
232  lAppl.state = mh_eApplState_Connected;
233  return sts;
234 }
235 
245 {
246  pwr_tStatus sts;
247 
248  sts = sendAndReceive(mh_eMsg_ApplDisconnect, 0, NULL, NULL);
249 
250  lAppl.state = mh_eApplState_Disconnected;
251 
252  return MH__SUCCESS;
253 }
254 
264  pwr_tUInt32* id,
267  mh_sApplMessage* message
272  )
273 {
274  pwr_tStatus sts;
275  mh_uApplReply reply;
276 
277  /* Check parameters */
278 
279  if (message == NULL)
280  return MH__BADPARAM;
281 
282  sts = sendAndReceive(mh_eMsg_ApplMessage, sizeof(*message), message, &reply);
283  if (EVEN(sts))
284  return sts;
285 
286  message->Id = reply.Message.Idx;
287  if (id != NULL)
288  *id = reply.Message.Idx;
289  return sts;
290 }
291 
300  pwr_tUInt32 id,
302  pwr_tString80* returnText
304  )
305 {
306  pwr_tStatus sts;
307  mh_sApplReturn applReturn;
308 
309  /* Check parameters */
310 
311  if (returnText == NULL)
312  memset(&applReturn.ReturnText, 0, sizeof(applReturn.ReturnText));
313  else
314  strncpy(applReturn.ReturnText, (char*)returnText, sizeof(*returnText));
315 
316  applReturn.TargetIdx = id;
317  applReturn.ReturnType = mh_eEvent_Return;
318 
319  sts = sendAndReceive(
320  mh_eMsg_ApplReturn, sizeof(applReturn), &applReturn, NULL);
321 
322  return sts;
323 }
324 
333  id,
340  mh_sApplMessage* message
344  )
345 {
346  pwr_tStatus sts;
347  mh_uApplReply reply;
348 
349  /* Check parameters */
350 
351  if (message == NULL)
352  return MH__BADPARAM;
353 
354  sts = sendAndReceive(mh_eMsg_ApplGetMsgInfo, sizeof(id), &id, &reply);
355  if (EVEN(sts))
356  return sts;
357 
358  memcpy(message, &reply.Info.Message, sizeof(*message));
359 
360  return MH__SUCCESS;
361 }
362 
363 static pwr_tStatus sendAndReceive(
364  mh_eMsg type, pwr_tUInt32 inSize, void* ip, mh_uApplReply* reply)
365 {
366  pwr_tStatus sts;
367  qcom_sPut put;
368  qcom_sGet get;
369  mh_sHead* hp;
370  mh_uApplReply* rp;
371  void* rvoid;
372  pwr_tUInt32 size = sizeof(lAppl.head) + inSize;
373 
374  if ((put.data = qcom_Alloc(&sts, size)) == NULL) {
375  errh_Error("mh_Appl, sendAndReceive, qcom_AllocMsg failed\n%m", sts);
376  return MH__QCOMALLOCMSG;
377  }
378 
379  memcpy(put.data, &lAppl.head, sizeof(lAppl.head));
380  ((mh_sHead*)put.data)->type = type;
381  if (inSize > 0)
382  memcpy((char*)put.data + sizeof(lAppl.head), ip, inSize);
383 
384  put.type.b = mh_cMsgClass;
385  put.type.s = 0;
386  put.reply.qix = 0;
387  put.reply.nid = 0;
388  put.size = size;
389  put.allocate = 0;
390 
391  get.data = NULL;
392 
393  rvoid = qcom_Request(
394  &sts, &lAppl.handler, &put, &lAppl.head.qid, &get, 1000 * 3600, 0);
395  if (EVEN(sts)) {
396  errh_Error("mhAppl, sendAndReceive, qcom_Get failed\n%m", sts);
397  qcom_Free(NULL, put.data);
398  return MH__QCOMRCVMSG;
399  }
400 
401  hp = (mh_sHead*)get.data;
402  rp = (mh_uApplReply*)(hp + 1);
403  sts = rp->Sts;
404 
405  if (ODD(sts) && reply != NULL)
406  memcpy(reply, rp, sizeof(mh_uApplReply));
407 
408  qcom_Free(NULL, get.data);
409 
410  return sts;
411 }
Include file for Time management.
void errh_Error(const char *msg,...)
Log an error message. The function has a variable argument list similar to sprintf.
Definition: rt_errh.c:343
pwr_tStatus gdh_GetObjectClass(pwr_tObjid object, pwr_tClassId *classid)
Get the class identifier of an object.
Definition: rt_gdh.c:1107
mh_mApplFlags
Flags governing how mh interacts with the application.
Definition: rt_mh_appl.h:70
pwr_tStatus mh_ApplMessage(pwr_tUInt32 *id, mh_sApplMessage *message)
This routine is called by an application to create and send a message.
Definition: rt_mh_appl.c:263
pwr_tStatus mh_ApplCancel(pwr_tUInt32 id, pwr_tString80 *cancelText)
Cancel a message previously created by this application.
Definition: rt_mh_appl.c:75
pwr_tStatus mh_ApplConnect(pwr_tObjid applObject, mh_mApplFlags flags, const pwr_tString80 abortEventName, mh_eEvent abortEventType, mh_eEventPrio abortEventPrio, mh_mEventFlags abortEventFlags, const pwr_tString80 abortEventText, pwr_tUInt32 *activeMessages)
Connects this application to the local Handler.
Definition: rt_mh_appl.c:112
pwr_tStatus mh_ApplReturn(pwr_tUInt32 id, pwr_tString80 *returnText)
Set return status on a message previously created by this application.
Definition: rt_mh_appl.c:299
pwr_tStatus mh_ApplDisconnect()
Informs the local Handler to remove this Application from its list of known applications.
Definition: rt_mh_appl.c:244
pwr_tStatus mh_ApplGetMsgInfo(pwr_tUInt32 id, mh_sApplMessage *message)
Fetches the properties of an earlier sent message.
Definition: rt_mh_appl.c:331
pwr_tBoolean qcom_MyNode(pwr_tStatus *sts, qcom_sNode *node)
Get the local qcom node.
Definition: rt_qcom.c:496
pwr_tBoolean qcom_CreateQ(pwr_tStatus *sts, qcom_sQid *myQ, qcom_sQattr *attr, const char *qname)
Create a queue and make an implicit connect to it.
Definition: rt_qcom.c:213
pwr_tBoolean qcom_Free(pwr_tStatus *sts, void *buffer)
Free a previously allocated buffer.
Definition: rt_qcom.c:355
void * qcom_Request(pwr_tStatus *sts, const qcom_sQid *receiver, qcom_sPut *put, const qcom_sQid *myQ, qcom_sGet *get, int tmo_ms, pwr_tBitMask flags)
Put a request and return the reply.
Definition: rt_qcom.c:1022
pwr_tBoolean qcom_Init(pwr_tStatus *sts, qcom_sAid *aid, const char *aname)
Connect to QCom.
Definition: rt_qcom.c:643
void * qcom_Alloc(pwr_tStatus *sts, unsigned int size)
Allocate a buffer in the qcom pool.
Definition: rt_qcom.c:85
#define EVEN(a)
Check if value is even.
Definition: pwr.h:623
unsigned int pwr_tUInt32
32-bit unsigned integer type.
Definition: pwr.h:233
pwr_tCid pwr_tClassId
Class identity type.
Definition: pwr.h:274
char pwr_tString80[80]
80 byte string type.
Definition: pwr.h:412
int pwr_tStatus
Status type.
Definition: pwr.h:284
#define ODD(a)
Check if value is odd.
Definition: pwr.h:618
The structure describing an application message.
Definition: rt_mh_appl.h:87
pwr_tUInt32 Id
Definition: rt_mh_appl.h:88
Object identity type.
Definition: pwr.h:263
Get data structure.
Definition: rt_qcom.h:185
Data for a Qcom node.
Definition: rt_qcom.h:219
co_eHW hw
hardware
Definition: rt_qcom.h:224
co_eOS os
operating system
Definition: rt_qcom.h:223
Put data structure.
Definition: rt_qcom.h:174
Queue attributes.
Definition: rt_qcom.h:162
Queue identity.
Definition: rt_qcom.h:125
qcom_tQix qix
Definition: rt_qcom.h:126
pwr_tNodeId nid
Definition: rt_qcom.h:127
Application context.
Definition: rt_mh_appl.c:52