OpcUaCanOpen
CANopen OPC-UA server
UaCalcItem.h
Go to the documentation of this file.
1 #ifndef __UACALCITEM_H__
2 #define __UACALCITEM_H__
3 
4 #include "exprtk.hpp"
5 
6 #include <opcua_basedatavariabletype.h>
7 #include "NmBuildingAutomation.h"
8 #include "UaControlDeviceItem.h"
10 #include "uadatetime.h"
11 #include "uadatavalue.h"
12 #include <cmath>
13 #include <string>
14 #include "srvtrace.h"
15 #include "CANOpenServerConfig.h"
16 
17 #ifndef isnan
18 #define isnan(x) std::isnan(x)
19 #endif
20 
21 #ifndef isinf
22 #define isinf(x) std::isinf(x)
23 #endif
24 
25 namespace AddressSpace
26 {
27  typedef std::map<string,vector<UaControlVariable *> > mapDataVariable ;
28 
29  typedef ::ITEM ITEM_type;
30  typedef ::xsd::cxx::tree::sequence< ITEM_type > ITEM_sequence;
31  typedef ITEM_sequence::iterator ITEM_iterator;
32  typedef ITEM_sequence::const_iterator ITEM_const_iterator;
33 
34  typedef ::REGEXPR REGEXPR_type;
35  typedef ::xsd::cxx::tree::sequence< REGEXPR_type > REGEXPR_sequence;
36  typedef REGEXPR_sequence::iterator REGEXPR_iterator;
37  typedef REGEXPR_sequence::const_iterator REGEXPR_const_iterator;
38 
42 
43  struct fmod : public exprtk::ifunction<double>
44  {
45  // using exprtk::ifunction<double>::operator();
46 
47  fmod() : exprtk::ifunction<double>(2)
48  {
49  // static_cast<double>(0.0);
50  }
51 
52  inline double operator()(const double& a1, const double& a2)
53  {
54  return std::fmod(a1, a2);
55  }
56  };
57 
58  static fmod f1;
66  {
68  public:
69 
70  typedef map<std::string, UaControlVariable*> variableSet;
71 
76  virtual void calculateOnChange(Session *pSession, const UaDataValue& dataValue, OpcUa_Boolean checkAccessLevel);
77 
79  virtual void initCalculation();
91 // UaCalcItem( const UaString& name,UaNodeId& uaId,
92 // NmBuildingAutomation * pNodeConfig, UaVariant &dv,string &formul, string &whenCondition, string &statusCondition,UaMutexRefCounted* pSharedMutex );
93 
94  UaCalcItem(const UaString& name, UaNodeId& uaId, const UaNode *parent,
95  NmBuildingAutomation * pNodeConfig, UaVariant &dv, ITEM &citem, UaControlVariableMap &cvs, UaMutexRefCounted* pSharedMutex);
96 
97  bool compile();
98 
100  virtual ~UaCalcItem(void) {}
101 
107  bool pushDataVariable(const string& name,UaControlVariable *obd)
108  {
109  bool res;
110 
111  boost::arg<1> _1;
112  boost::arg<2> _2;
113  boost::arg<3> _3;
114  m_var.insert(pair<string, UaControlVariable *>(name, obd));
116 
117  if (!m_cExists)
118  obd->valueChange.connect(boost::bind(&UaCalcItem::calculateOnChange,this,_1,_2,_3));
119  return res;
120  }
121 
127  bool pushConditionVariable(const string& name, UaControlVariable *obd)
128  {
129  bool res = true;
130 
131  boost::arg<1> _1;
132  boost::arg<2> _2;
133  boost::arg<3> _3;
134  m_whenVar.insert(pair<string, UaControlVariable *>(name, obd));
135 // res = m_whenCondition_table.add_variable(name, obd->curValue);
137 
138  obd->valueChange.connect(boost::bind(&UaCalcItem::calculateOnChange,this,_1,_2,_3));
139  return res;
140  }
146  bool pushStatusVariable(const string& name, UaControlVariable *obd)
147  {
148  bool res;
149 
150  m_statusVar.insert(pair<string, UaControlVariable *>(name, obd));
151 // res = m_statusFormula_table.add_variable(name, obd->curValue);
153 
154  return res;
155  }
156 
157  bool fExists() { return m_fExists; }
158 
159  void replaceAll(std::string& str, const std::string& from, const std::string& to) {
160  if(from.empty())
161  return;
162  size_t start_pos = 0;
163  while((start_pos = str.find(from, start_pos)) != std::string::npos) {
164  str.replace(start_pos, from.length(), to);
165  start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
166  }
167 }
168  bool checkDouble(const string& str, double &res)
169  {
170  size_t indx = 0;
171  m_fExists = true;
172  try {
173  res = stod(str,&indx);
174  }
175  catch (...)
176  {
177  return false;
178  }
179  if (str.size() > indx)
180  return false;
181  else {
182  m_fExists = false;
183  return true;
184  }
185 
186  }
187 
188 /*
189  void readData(Session *pSession, variableSet &vs)
190  {
191  for (auto &it: vs )
192  {
193 
194  if (!(it.second->active)) {
195  UaDataValue udv = it.second->ucv->value(pSession);
196  it.second->value = convertToDouble(udv);
197  }
198  }
199  }
200 */
201 
202  OpcUa_StatusCode checkStatus(variableSet& vs)
203  {
204  OpcUa_StatusCode ret = OpcUa_Good;
205  for (auto const &vit : vs)
206  {
207  UaControlVariable *uac = vit.second;
208  ret = uac->value(0).statusCode();
209 // cout << "Status Code " << uac->browseName().toString().toUtf8() << " "<< hex << ret << " value "<< uac->curValue << endl << flush;
210  if (ret != OpcUa_Good)
211  break;
212  }
213  return ret;
214  }
215 
216 /* double convertToDouble(const UaDataValue &dataValue)
217  {
218  double res = 0.0;
219  const OpcUa_Variant *val = dataValue.value();
220  switch (val->Datatype) {
221  case OpcUaType_Boolean:
222  res = val->Value.Boolean;
223  break;
224  case OpcUaType_SByte:
225  res = val->Value.SByte;
226  break;
227  case OpcUaType_Byte:
228  res = val->Value.Byte;
229  break;
230  case OpcUaType_Int16:
231  res = val->Value.Int16;
232  break;
233  case OpcUaType_UInt16:
234  res = val->Value.UInt16;
235  break;
236  case OpcUaType_Int32:
237  res = val->Value.Int32;
238  break;
239  case OpcUaType_UInt32:
240  res = val->Value.UInt32;
241  break;
242  case OpcUaType_Int64:
243  res = (double)val->Value.Int64;
244  break;
245  case OpcUaType_UInt64:
246  res = (double)val->Value.UInt64;
247  break;
248  case OpcUaType_Float:
249  res = val->Value.Float;
250  break;
251  case OpcUaType_Double:
252  res = val->Value.Double;
253  break;
254  default:
255  throw 1;
256  // res = 0.0;
257  };
258  return res;
259  }
260  */
261  const OpcUa::BaseObjectType *m_pParent;
263 
271  private:
272 
276 
278 // symbol_table_t m_whenCondition_table;
279 // symbol_table_t m_statusFormula_table;
280 
284 
285  string m_sFormul;
288 
289  bool m_fExists;
290  bool m_cExists;
291  bool m_sExists;
292 
296 
297  };
298 
299 }
300 #endif
301