OpcUaCanOpen
CANopen OPC-UA server
CanSDOItem.cpp
Go to the documentation of this file.
1 //#include "BuildingAutomationTypeIds.h"
2 #include <opcua_basedatavariabletype.h>
3 #include "uabasenodes.h"
4 #include "CanSDOItem.h"
5 #include "CanSDOObject.h"
6 #include "CanNodeObject.h"
7 #include "CanOpenData.h"
8 #include "CanObject.h"
9 #include "CANopen.h"
10 #include <uadatetime.h>
11 #include "uasemaphore.h"
12 #include "UaCanTrace.h"
13 #include <iomanip>
14 
15 namespace CanOpen
16 {
17  /*
18  * Constructor of CanSDOObject
19  * @param par CanObject using to pass message to CanBus
20  * @param conf XML configuration parameter for this item
21  * @param blink pointer UaVariable
22  * @param code function code
23  */
25  SDOITEM_TYPE1 *conf,UaNode *blink,int code) : CanOpenItem( par, conf,blink,code)
26  {
27  char *p;
28  m_Timeout = 0;
29  m_subind = (OpcUa_Byte)strtol(conf->subindex().data(),&p,16);
30 
31  CanOpenDataAddress::getOpcUaType(conf->type().data(),itemType);
32  }
33 
34  /*
35  * Constructor of CanSDOObject
36  * @param par CanObject using to pass message to CanBus
37  * @param conf XML configuration parameter for this item
38  * @param blink pointer UaVariable
39  * @param code function code
40  */
42  SDOITEM_TYPE2 *conf,UaNode *blink,int code) : CanOpenItem( par, conf,blink,code)
43  {
44  char *p;
45  m_Timeout = 0;
46 
47  OpcUa_UInt16 ind = (OpcUa_UInt16)strtol(conf->index().data(), &p, 16);
48  static_cast<CanSDOObject *>(par->getDevice())->setIndex(ind);
49 
50  m_subind = (OpcUa_Byte)strtol(conf->subindex().data(),&p,16);
51  CanOpenDataAddress::getOpcUaType(conf->type().data(),itemType);
52  }
53  /*
54  * Constructor of CanSDOOItem
55  * @param par CanObject using to pass message to CanBus
56  * @param conf XML configuration parameter for this item
57  * @param blink pointer UaVariable
58  * @param code function code
59  */
61  SDOITEM_TYPE3 *conf,UaNode *blink,int code) : CanOpenItem( par, conf,blink,code)
62  {
63  CanOpenDataAddress::getOpcUaType(conf->type().data(),itemType);
64  m_Timeout = 0;
65  }
66 
67  UaStatus CanSDOItem::write(UaDataValue &udv)
68  {
70  par->setSDOItem(this);
71  par->setTimeout(m_Timeout);
72 
73  UaStatus ret = par->writeSdo(udv);
74 
75  par->freeSDOItem();
76 
77  return ret;
78  }
79 
80  UaStatus CanSDOItem::read()
81  {
82  UaDataValue udv;
83 
84  CanSDOObject *par = getCanSDOObject();;
85 
86  par->setSDOItem(this);
87  par->setTimeout(m_Timeout);
88 
89  UaStatus ret = par->readSdo(udv);
90  if ( ret.isGood() ) {
91  OpcUa::BaseDataVariableType *bdt = getUaEntry();
92  bdt->setValue(0,udv,OpcUa_False);
93 // cout << "Read " << bdt->browseName().toString().toUtf8() << endl;
94  }
95 
96  par->freeSDOItem();
97 
98  return ret;
99  }
100 
101  UaStatus CanSDOItem::pack(const OpcUa_Variant *sData)
102  {
103  UaStatus ret = OpcUa_Good;
104  CanSDOObject *pSDOObject = getCanSDOObject();
105  OpcUa_Variant convData;
106  UaStatus compatible = convertOpcUaType(sData, &convData, getItemType());
107 
108  if (compatible.isBad())
109  {
110  UaString sDiag = "Not compatible Data Types";
111  ret.setStatus(OpcUa_BadDataEncodingUnsupported, sDiag);
112  return ret;
113  }
114 
115 
116  switch (getItemType()) {
117  case OpcUaType_Boolean:
118  pSDOObject->m_iLength = 1;
119 
120  pSDOObject->m_buffer[4] = convData.Value.Boolean;
121  break;
122  case OpcUaType_Byte:
123  pSDOObject->m_iLength = 1;
124 
125  pSDOObject->m_buffer[4] = convData.Value.Byte;
126  break;
127  case OpcUaType_SByte:
128  pSDOObject->m_iLength = 1;
129 
130  pSDOObject->m_buffer[4] = convData.Value.SByte;
131  break;
132  case OpcUaType_Int16:
133  case OpcUaType_UInt16:
134  {
135  union {
136  unsigned char temp[2];
137  unsigned short dtemp;
138  } dt;
139 
140  dt.dtemp = convData.Value.UInt16;
141  pSDOObject->m_buffer[4] = dt.temp[0];
142  pSDOObject->m_buffer[5] = dt.temp[1];
143  pSDOObject->m_iLength = 2;
144  }
145  break;
146  case OpcUaType_Int32:
147  case OpcUaType_UInt32:
148  {
149  union {
150  unsigned char temp[4];
151  unsigned long dtemp;
152  } dt;
153 
154  dt.dtemp = convData.Value.UInt32;
155  pSDOObject->m_buffer[4] = dt.temp[0];
156  pSDOObject->m_buffer[5] = dt.temp[1];
157  pSDOObject->m_buffer[6] = dt.temp[2];
158  pSDOObject->m_buffer[7] = dt.temp[3];
159  pSDOObject->m_iLength = 4;
160  }
161  break;
162  case OpcUaType_Float:
163  {
164  union {
165  unsigned char temp[4];
166  float dtemp;
167  } dt;
168 
169  dt.dtemp = convData.Value.Float;
170  pSDOObject->m_buffer[4] = dt.temp[0];
171  pSDOObject->m_buffer[5] = dt.temp[1];
172  pSDOObject->m_buffer[6] = dt.temp[2];
173  pSDOObject->m_buffer[7] = dt.temp[3];
174  pSDOObject->m_iLength = 4;
175 
176  }
177  break;
178  case OpcUaType_ByteString:
179  {
180  union { unsigned char temp[4];
181  unsigned int dtemp;
182  } dt;
183  // initial download
184  if (getItemType() == sData->Datatype) { // Sdo Operation
185 
186  pSDOObject->m_iLength = sData->Value.ByteString.Length;
187  pSDOObject->m_segSdoBuffer.resize(pSDOObject->m_iLength);
188  pSDOObject->m_segSdoBuffer = sData->Value.ByteString;
189  dt.dtemp = pSDOObject->m_iLength;
191  pSDOObject->m_buffer[1] = 0xFF & pSDOObject->getIndex();
192  pSDOObject->m_buffer[2] = 0xFF & (pSDOObject->getIndex() >> 8);
193  pSDOObject->m_buffer[3] = m_subind;
194  pSDOObject->m_buffer[4] = dt.temp[0];
195  pSDOObject->m_buffer[5] = dt.temp[1];
196  pSDOObject->m_buffer[6] = dt.temp[2];
197  pSDOObject->m_buffer[7] = dt.temp[3];
198  }
199  else {
200  UaString sDiag = "Not compatible Data Types";
201  ret.setStatus(OpcUa_BadDataEncodingUnsupported,sDiag);
202  return ret;
203  }
204 
205  }
206  return OpcUa_Good;
207  default:
208  {
209  UaString sDiag = "Not compatible Data Types";
210  ret.setStatus(OpcUa_BadDataEncodingUnsupported, sDiag);
211  return ret;
212 
213  }
214  }
215 
216  OpcUa_Byte invalid_bytes = (OpcUa_Byte)(4 - pSDOObject->m_iLength);
218  pSDOObject->m_buffer[1] = 0xFF & pSDOObject->getIndex();
219  pSDOObject->m_buffer[2] = 0xFF & (pSDOObject->getIndex() >> 8);
220  pSDOObject->m_buffer[3] = m_subind;
221 
222  return ret;
223  }
224 
225  UaVariant CanSDOItem::UnPack()
226  {
227  UaVariant newValue;
228  CanSDOObject *pSDOObject = getCanSDOObject();
229 
230  newValue.clear();
231 
232 
233 
234  UaByteArray& m_buffer = pSDOObject->m_buffer;
235  OpcUa_Byte sByte = 4;
236  switch (getItemType()) {
237  case OpcUaType_Boolean:
238  {
239  newValue.setBool(m_buffer[sByte]);
240  break;
241  }
242  case OpcUaType_Byte:
243  case OpcUaType_SByte:
244  {
245  newValue.setByte(m_buffer[sByte]);
246  break;
247  }
248  case OpcUaType_UInt16:
249  {
250  unsigned short ushortTemp = (unsigned char)m_buffer[sByte+1];
251  ushortTemp = ( ushortTemp << 8 ) + (unsigned char)m_buffer[sByte];
252  newValue.setUInt16(ushortTemp);
253  break;
254  }
255  case OpcUaType_UInt32:
256  {
257  unsigned int uintTemp = (unsigned char)m_buffer[sByte + 3];
258  uintTemp = (((((uintTemp << 8) + (unsigned char)m_buffer[sByte + 2]) << 8) + (unsigned char)m_buffer[sByte + 1]) << 8) + (unsigned char)m_buffer[sByte];
259  newValue.setUInt32(uintTemp);
260  break;
261  }
262  case OpcUaType_Float:
263  {
264  union {
265  unsigned int temp;
266  float dtemp;
267  } dt;
268 
269  dt.temp = (unsigned char)m_buffer[sByte+3];
270  dt.temp = ((((( dt.temp << 8 ) + (unsigned char)m_buffer[sByte+2]) << 8) + (unsigned char)m_buffer[sByte+1]) << 8) + (unsigned char)m_buffer[sByte];
271  newValue.setFloat(dt.dtemp);
272  break;
273  }
274  case OpcUaType_Int16:
275  {
276  unsigned short shortTemp = (unsigned char)m_buffer[sByte+1];
277  shortTemp = ( shortTemp << 8 ) + (unsigned char)m_buffer[sByte];
278  newValue.setInt16((OpcUa_Int16)shortTemp);
279  break;
280  }
281  case OpcUaType_Int32:
282  {
283  unsigned int intTemp = (unsigned char)m_buffer[sByte+3];
284  intTemp = ((((( intTemp << 8 ) + (unsigned char)m_buffer[sByte+2]) << 8) + (unsigned char)m_buffer[sByte+1]) << 8) + (unsigned char)m_buffer[sByte];
285  newValue.setInt32((OpcUa_Int32)intTemp);
286  break;
287  }
288  case OpcUaType_ByteString:
289  {
290  UaByteString tmp;
291  m_buffer = pSDOObject->m_segSdoBuffer;
292  tmp.setByteString(pSDOObject->m_iLength,(OpcUa_Byte *)(m_buffer.data()));
293  newValue.setByteString(tmp,false);
294  break;
295  }
296  default:
297  break;
298  };
299 
300  return newValue;
301  }
302  UaVariant CanSDOItem::getPropertyValue(OpcUa_UInt32 code, ::xsd::cxx::tree::type *conf)
303  {
304  UaVariant val;
305  val.clear();
306  auto *sdoi = conf;
307  switch (code) {
309  {
310  char *p;
311  getCanSDOObject()->setIndex(strtol(((SDOITEM_TYPE2 *)sdoi)->index().c_str(), &p, 16));
312  val.setString(UaString(((SDOITEM_TYPE2 *)sdoi)->index().c_str()));
313  }
314  break;
316  val.setString(UaString(((SDOITEM_TYPE2 *)sdoi)->subindex().c_str()));
317  break;
319  {
320  string t = ((SDOITEM_TYPE1 *)sdoi)->subindex();
321  val.setString(UaString(t.c_str()));
322  }
323  break;
324  }
325  return val;
326  }
327 
328  UaStatus CanSDOItem::connectCode(OpcUa_UInt32 code, ::xsd::cxx::tree::type *conf, UaNode *blink)
329  {
330  UaStatus ret = OpcUa_Good;
331  UaDataValue udt;
332  UaVariant val;
333  UaDateTime sdt = UaDateTime::now();
334 
335  SDOITEM_TYPE *sdoi = (SDOITEM_TYPE *)conf;
336  switch (code) {
338  m_Timeout = sdoi->timeout();
339  val.setUInt32(m_Timeout);
340  udt.setDataValue(val, OpcUa_False, OpcUa_Good, sdt, sdt);
341  ret = ((OpcUa::BaseDataVariableType *)blink)->setValue(0, udt, OpcUa_False);
342  break;
343  default:
344  return OpcUa_Bad;
345  }
346  return ret;
347  }
348 
349 
350 }