All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
config.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "config.h"
37 #include "buffer.h"
38 
39 #include <stdexcept>
40 #include <iomanip>
41 #include <limits>
42 #include <fstream>
43 
44 #include "Base/GCException.h"
45 
46 #include <GenApi/ChunkAdapterGEV.h>
47 #include <GenApi/ChunkAdapterU3V.h>
49 #include <GenApi/Filestream.h>
50 
52 
53 #ifdef _WIN32
54 #undef min
55 #undef max
56 #endif
57 
58 namespace rcg
59 {
60 
61 bool callCommand(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
62  bool exception)
63 {
64  bool ret=false;
65 
66  try
67  {
68  GenApi::INode *node=nodemap->_GetNode(name);
69 
70  if (node != 0)
71  {
72  if (GenApi::IsWritable(node))
73  {
74  GenApi::ICommand *val=dynamic_cast<GenApi::ICommand *>(node);
75 
76  if (val != 0)
77  {
78  val->Execute();
79  ret=true;
80  }
81  else if (exception)
82  {
83  throw std::invalid_argument(std::string("Feature not a command: ")+name);
84  }
85  }
86  else if (exception)
87  {
88  throw std::invalid_argument(std::string("Feature not writable: ")+name);
89  }
90  }
91  else if (exception)
92  {
93  throw std::invalid_argument(std::string("Feature not found: ")+name);
94  }
95  }
96  catch (const GENICAM_NAMESPACE::GenericException &ex)
97  {
98  if (exception)
99  {
100  throw std::invalid_argument(ex.what());
101  }
102  }
103 
104  return ret;
105 }
106 
107 bool setBoolean(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
108  bool value, bool exception)
109 {
110  bool ret=false;
111 
112  try
113  {
114  GenApi::INode *node=nodemap->_GetNode(name);
115 
116  if (node != 0)
117  {
118  if (GenApi::IsWritable(node))
119  {
120  GenApi::IBoolean *val=dynamic_cast<GenApi::IBoolean *>(node);
121 
122  if (val != 0)
123  {
124  val->SetValue(value);
125  ret=true;
126  }
127  else if (exception)
128  {
129  throw std::invalid_argument(std::string("Feature not boolean: ")+name);
130  }
131  }
132  else if (exception)
133  {
134  throw std::invalid_argument(std::string("Feature not writable: ")+name);
135  }
136  }
137  else if (exception)
138  {
139  throw std::invalid_argument(std::string("Feature not found: ")+name);
140  }
141  }
142  catch (const GENICAM_NAMESPACE::GenericException &ex)
143  {
144  if (exception)
145  {
146  throw std::invalid_argument(ex.what());
147  }
148  }
149 
150  return ret;
151 }
152 
153 bool setInteger(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
154  int64_t value, bool exception)
155 {
156  bool ret=false;
157 
158  try
159  {
160  GenApi::INode *node=nodemap->_GetNode(name);
161 
162  if (node != 0)
163  {
164  if (GenApi::IsWritable(node))
165  {
166  GenApi::IInteger *val=dynamic_cast<GenApi::IInteger *>(node);
167 
168  if (val != 0)
169  {
170  val->SetValue(value);
171  ret=true;
172  }
173  else if (exception)
174  {
175  throw std::invalid_argument(std::string("Feature not integer: ")+name);
176  }
177  }
178  else if (exception)
179  {
180  throw std::invalid_argument(std::string("Feature not writable: ")+name);
181  }
182  }
183  else if (exception)
184  {
185  throw std::invalid_argument(std::string("Feature not found: ")+name);
186  }
187  }
188  catch (const GENICAM_NAMESPACE::GenericException &ex)
189  {
190  if (exception)
191  {
192  throw std::invalid_argument(ex.what());
193  }
194  }
195 
196  return ret;
197 }
198 
199 bool setIPV4Address(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
200  const char *value, bool exception)
201 {
202  bool ret=false;
203 
204  try
205  {
206  GenApi::INode *node=nodemap->_GetNode(name);
207 
208  if (node != 0)
209  {
210  if (GenApi::IsWritable(node))
211  {
212  GenApi::IInteger *val=dynamic_cast<GenApi::IInteger *>(node);
213 
214  if (val != 0)
215  {
216  int64_t ip=0;
217 
218  std::stringstream in(value);
219  std::string elem;
220 
221  for (int i=0; i<4; i++)
222  {
223  getline(in, elem, '.');
224  ip=(ip<<8)|(stoi(elem)&0xff);
225  }
226 
227  val->SetValue(ip);
228  ret=true;
229  }
230  else if (exception)
231  {
232  throw std::invalid_argument(std::string("Feature not integer: ")+name);
233  }
234  }
235  else if (exception)
236  {
237  throw std::invalid_argument(std::string("Feature not writable: ")+name);
238  }
239  }
240  else if (exception)
241  {
242  throw std::invalid_argument(std::string("Feature not found: ")+name);
243  }
244  }
245  catch (const GENICAM_NAMESPACE::GenericException &ex)
246  {
247  if (exception)
248  {
249  throw std::invalid_argument(ex.what());
250  }
251  }
252 
253  return ret;
254 }
255 
256 bool setFloat(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
257  double value, bool exception)
258 {
259  bool ret=false;
260 
261  try
262  {
263  GenApi::INode *node=nodemap->_GetNode(name);
264 
265  if (node != 0)
266  {
267  if (GenApi::IsWritable(node))
268  {
269  GenApi::IFloat *val=dynamic_cast<GenApi::IFloat *>(node);
270 
271  if (val != 0)
272  {
273  val->SetValue(value);
274  ret=true;
275  }
276  else if (exception)
277  {
278  throw std::invalid_argument(std::string("Feature not float: ")+name);
279  }
280  }
281  else if (exception)
282  {
283  throw std::invalid_argument(std::string("Feature not writable: ")+name);
284  }
285  }
286  else if (exception)
287  {
288  throw std::invalid_argument(std::string("Feature not found: ")+name);
289  }
290  }
291  catch (const GENICAM_NAMESPACE::GenericException &ex)
292  {
293  if (exception)
294  {
295  throw std::invalid_argument(ex.what());
296  }
297  }
298 
299  return ret;
300 }
301 
302 bool setEnum(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
303  const char *value, bool exception)
304 {
305  bool ret=false;
306 
307  try
308  {
309  GenApi::INode *node=nodemap->_GetNode(name);
310 
311  if (node != 0)
312  {
313  if (GenApi::IsWritable(node))
314  {
315  GenApi::IEnumeration *val=dynamic_cast<GenApi::IEnumeration *>(node);
316 
317  if (val != 0)
318  {
319  GenApi::IEnumEntry *entry=0;
320 
321  try
322  {
323  entry=val->GetEntryByName(value);
324  }
326  { }
327 
328  if (entry != 0)
329  {
330  val->SetIntValue(entry->GetValue());
331 
332  return true;
333  }
334  else if (exception)
335  {
336  throw std::invalid_argument(std::string("Enumeration '")+name+
337  "' does not contain: "+value);
338  }
339  }
340  else if (exception)
341  {
342  throw std::invalid_argument(std::string("Feature not enumeration: ")+name);
343  }
344  }
345  else if (exception)
346  {
347  throw std::invalid_argument(std::string("Feature not writable: ")+name);
348  }
349  }
350  else if (exception)
351  {
352  throw std::invalid_argument(std::string("Feature not found: ")+name);
353  }
354  }
355  catch (const GENICAM_NAMESPACE::GenericException &ex)
356  {
357  if (exception)
358  {
359  throw std::invalid_argument(ex.what());
360  }
361  }
362 
363  return ret;
364 }
365 
366 size_t setRegister(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
367  const uint8_t *buffer, size_t len, bool exception)
368 {
369  size_t ret=0;
370 
371  try
372  {
373  GenApi::INode *node=nodemap->_GetNode(name);
374 
375  if (node != 0)
376  {
377  if (GenApi::IsWritable(node))
378  {
379  GenApi::IRegister *val=dynamic_cast<GenApi::IRegister *>(node);
380 
381  if (val != 0)
382  {
383  len=std::min(len, static_cast<size_t>(val->GetLength()));
384  val->Set(buffer, len);
385  ret=len;
386  }
387  else if (exception)
388  {
389  throw std::invalid_argument(std::string("Feature not of type register: ")+name);
390  }
391  }
392  else if (exception)
393  {
394  throw std::invalid_argument(std::string("Feature not writable: ")+name);
395  }
396  }
397  else if (exception)
398  {
399  throw std::invalid_argument(std::string("Feature not found: ")+name);
400  }
401  }
402  catch (const GENICAM_NAMESPACE::GenericException &ex)
403  {
404  if (exception)
405  {
406  throw std::invalid_argument(ex.what());
407  }
408  }
409 
410  return ret;
411 }
412 
413 bool setString(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
414  const char *value, bool exception)
415 {
416  bool ret=false;
417 
418  try
419  {
420  GenApi::INode *node=nodemap->_GetNode(name);
421 
422  if (node != 0)
423  {
424  if (GenApi::IsWritable(node))
425  {
426  switch (node->GetPrincipalInterfaceType())
427  {
429  {
430  GenApi::IBoolean *p=dynamic_cast<GenApi::IBoolean *>(node);
431 
432  std::string v=std::string(value);
433  if (v == "true" || v == "True" || v == "TRUE")
434  {
435  p->SetValue(1);
436  }
437  else if (v == "false" || v == "False" || v == "FALSE")
438  {
439  p->SetValue(0);
440  }
441  else
442  {
443  p->SetValue(static_cast<bool>(std::stoi(v)));
444  }
445  }
446  break;
447 
449  {
450  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(node);
451 
452  switch (p->GetRepresentation())
453  {
454  case GenApi::HexNumber:
455  p->SetValue(std::stoll(std::string(value), 0, 16));
456  break;
457 
458  case GenApi::IPV4Address:
459  {
460  int64_t ip=0;
461 
462  std::stringstream in(value);
463  std::string elem;
464 
465  for (int i=0; i<4; i++)
466  {
467  getline(in, elem, '.');
468  ip=(ip<<8)|(stoi(elem)&0xff);
469  }
470 
471  p->SetValue(ip);
472  }
473  break;
474 
475  case GenApi::MACAddress:
476  {
477  int64_t mac=0;
478 
479  std::stringstream in(value);
480  std::string elem;
481 
482  for (int i=0; i<4; i++)
483  {
484  getline(in, elem, ':');
485  mac=(mac<<8)|(stoi(elem, 0, 16)&0xff);
486  }
487 
488  p->SetValue(mac);
489  }
490  break;
491 
492  default:
493  p->SetValue(std::stoll(std::string(value)));
494  break;
495  }
496  }
497  break;
498 
499  case GenApi::intfIFloat:
500  {
501  GenApi::IFloat *p=dynamic_cast<GenApi::IFloat *>(node);
502  p->SetValue(std::stof(std::string(value)));
503  }
504  break;
505 
507  {
508  GenApi::IEnumeration *p=dynamic_cast<GenApi::IEnumeration *>(node);
509  GenApi::IEnumEntry *entry=0;
510 
511  try
512  {
513  entry=p->GetEntryByName(value);
514  }
516  { }
517 
518  if (entry != 0)
519  {
520  p->SetIntValue(entry->GetValue());
521  }
522  else if (exception)
523  {
524  throw std::invalid_argument(std::string("Enumeration '")+name+
525  "' does not contain: "+value);
526  }
527  }
528  break;
529 
531  {
532  GenApi::IRegister *p=dynamic_cast<GenApi::IRegister *>(node);
533 
534  std::string s=value;
535 
536  size_t n=s.find_first_not_of("0123456789abcdefABCDEF");
537  if (n != std::string::npos)
538  {
539  throw std::invalid_argument(std::string("Register '")+name+
540  "only accepts hedadecimal values: "+s);
541  }
542 
543  std::vector<uint8_t> buffer;
544  for (size_t i=0; i<s.size()-1; i+=2)
545  {
546  buffer.push_back(stoi(s.substr(i, 2), 0, 16));
547  }
548 
549  p->Set(buffer.data(), std::min(buffer.size(), static_cast<size_t>(p->GetLength())));
550  }
551  break;
552 
553  case GenApi::intfIString:
554  {
555  GenApi::IString *p=dynamic_cast<GenApi::IString *>(node);
556  p->SetValue(value);
557  }
558  break;
559 
560  default:
561  if (exception)
562  {
563  throw std::invalid_argument(std::string("Feature of unknown datatype: ")+name);
564  }
565  break;
566  }
567  }
568  else if (exception)
569  {
570  throw std::invalid_argument(std::string("Feature not writable: ")+name);
571  }
572  }
573  else if (exception)
574  {
575  throw std::invalid_argument(std::string("Feature not found: ")+name);
576  }
577  }
578  catch (const GENICAM_NAMESPACE::GenericException &ex)
579  {
580  if (exception)
581  {
582  throw std::invalid_argument(ex.what());
583  }
584  }
585 
586  return ret;
587 }
588 
589 bool getBoolean(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
590  bool exception, bool igncache)
591 {
592  bool ret=false;
593 
594  try
595  {
596  GenApi::INode *node=nodemap->_GetNode(name);
597 
598  if (node != 0)
599  {
600  if (GenApi::IsReadable(node))
601  {
602  GenApi::IBoolean *val=dynamic_cast<GenApi::IBoolean *>(node);
603 
604  if (val != 0)
605  {
606  ret=val->GetValue(false, igncache);
607  }
608  else if (exception)
609  {
610  throw std::invalid_argument(std::string("Feature not boolean: ")+name);
611  }
612  }
613  else if (exception)
614  {
615  throw std::invalid_argument(std::string("Feature not readable: ")+name);
616  }
617  }
618  else if (exception)
619  {
620  throw std::invalid_argument(std::string("Feature not found: ")+name);
621  }
622  }
623  catch (const GENICAM_NAMESPACE::GenericException &ex)
624  {
625  if (exception)
626  {
627  throw std::invalid_argument(ex.what());
628  }
629  }
630 
631  return ret;
632 }
633 
634 int64_t getInteger(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
635  int64_t *vmin, int64_t *vmax, bool exception, bool igncache)
636 {
637  int64_t ret=0;
638 
639  if (vmin != 0) *vmin=0;
640  if (vmax != 0) *vmax=0;
641 
642  try
643  {
644  GenApi::INode *node=nodemap->_GetNode(name);
645 
646  if (node != 0)
647  {
648  if (GenApi::IsReadable(node))
649  {
650  if (node->GetPrincipalInterfaceType() == GenApi::intfIEnumeration)
651  {
652  GenApi::IEnumeration *p=dynamic_cast<GenApi::IEnumeration *>(node);
653  ret=p->GetCurrentEntry(false, igncache)->GetValue();
654 
655  if (vmin != 0) *vmin=ret;
656  if (vmax != 0) *vmax=ret;
657  }
658  else
659  {
660  GenApi::IInteger *val=dynamic_cast<GenApi::IInteger *>(node);
661 
662  if (val != 0)
663  {
664  ret=val->GetValue(false, igncache);
665 
666  if (vmin != 0) *vmin=val->GetMin();
667  if (vmax != 0) *vmax=val->GetMax();
668  }
669  else if (exception)
670  {
671  throw std::invalid_argument(std::string("Feature not integer: ")+name);
672  }
673  }
674  }
675  else if (exception)
676  {
677  throw std::invalid_argument(std::string("Feature not readable: ")+name);
678  }
679  }
680  else if (exception)
681  {
682  throw std::invalid_argument(std::string("Feature not found: ")+name);
683  }
684  }
685  catch (const GENICAM_NAMESPACE::GenericException &ex)
686  {
687  if (exception)
688  {
689  throw std::invalid_argument(ex.what());
690  }
691  }
692 
693  return ret;
694 }
695 
696 double getFloat(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
697  double *vmin, double *vmax, bool exception, bool igncache)
698 {
699  double ret=0;
700 
701  if (vmin != 0) *vmin=0;
702  if (vmax != 0) *vmax=0;
703 
704  try
705  {
706  GenApi::INode *node=nodemap->_GetNode(name);
707 
708  if (node != 0)
709  {
710  if (GenApi::IsReadable(node))
711  {
712  GenApi::IFloat *val=dynamic_cast<GenApi::IFloat *>(node);
713 
714  if (val != 0)
715  {
716  ret=val->GetValue(false, igncache);
717 
718  if (vmin != 0) *vmin=val->GetMin();
719  if (vmax != 0) *vmax=val->GetMax();
720  }
721  else if (exception)
722  {
723  throw std::invalid_argument(std::string("Feature not float: ")+name);
724  }
725  }
726  else if (exception)
727  {
728  throw std::invalid_argument(std::string("Feature not readable: ")+name);
729  }
730  }
731  else if (exception)
732  {
733  throw std::invalid_argument(std::string("Feature not found: ")+name);
734  }
735  }
736  catch (const GENICAM_NAMESPACE::GenericException &ex)
737  {
738  if (exception)
739  {
740  throw std::invalid_argument(ex.what());
741  }
742  }
743 
744  return ret;
745 }
746 
747 std::string getEnum(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
748  bool exception)
749 {
750  std::string ret;
751 
752  try
753  {
754  GenApi::INode *node=nodemap->_GetNode(name);
755 
756  if (node != 0)
757  {
758  if (GenApi::IsReadable(node))
759  {
760  GenApi::IEnumeration *val=dynamic_cast<GenApi::IEnumeration *>(node);
761 
762  if (val != 0)
763  {
764  GenApi::IEnumEntry *entry=val->GetCurrentEntry();
765 
766  if (entry != 0)
767  {
768  ret=entry->GetSymbolic();
769  }
770  else if (exception)
771  {
772  throw std::invalid_argument(std::string("Current value is not defined: ")+name);
773  }
774  }
775  else if (exception)
776  {
777  throw std::invalid_argument(std::string("Feature not enumeration: ")+name);
778  }
779  }
780  else if (exception)
781  {
782  throw std::invalid_argument(std::string("Feature not readable: ")+name);
783  }
784  }
785  else if (exception)
786  {
787  throw std::invalid_argument(std::string("Feature not found: ")+name);
788  }
789  }
790  catch (const GENICAM_NAMESPACE::GenericException &ex)
791  {
792  if (exception)
793  {
794  throw std::invalid_argument(ex.what());
795  }
796  }
797 
798  return ret;
799 }
800 
801 std::string getEnum(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
802  std::vector<std::string> &list, bool exception)
803 {
804  std::string ret;
805 
806  list.clear();
807 
808  try
809  {
810  GenApi::INode *node=nodemap->_GetNode(name);
811 
812  if (node != 0)
813  {
814  if (GenApi::IsReadable(node))
815  {
816  GenApi::IEnumeration *val=dynamic_cast<GenApi::IEnumeration *>(node);
817 
818  if (val != 0)
819  {
820  GenApi::StringList_t entries;
821  val->GetSymbolics(entries);
822 
823  for (size_t i=0; i<entries.size(); i++)
824  {
825  list.push_back(std::string(entries[i]));
826  }
827 
828  GenApi::IEnumEntry *entry=val->GetCurrentEntry();
829 
830  if (entry != 0)
831  {
832  ret=entry->GetSymbolic();
833  }
834  else if (exception)
835  {
836  throw std::invalid_argument(std::string("Current value is not defined: ")+name);
837  }
838  }
839  else if (exception)
840  {
841  throw std::invalid_argument(std::string("Feature not enumeration: ")+name);
842  }
843  }
844  else if (exception)
845  {
846  throw std::invalid_argument(std::string("Feature not readable: ")+name);
847  }
848  }
849  else if (exception)
850  {
851  throw std::invalid_argument(std::string("Feature not found: ")+name);
852  }
853  }
854  catch (const GENICAM_NAMESPACE::GenericException &ex)
855  {
856  if (exception)
857  {
858  throw std::invalid_argument(ex.what());
859  }
860  }
861 
862  return ret;
863 }
864 
865 size_t getRegister(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
866  uint8_t *buffer, size_t len, size_t *total, bool exception, bool igncache)
867 {
868  size_t ret=0;
869 
870  if (total != 0) *total=0;
871 
872  try
873  {
874  GenApi::INode *node=nodemap->_GetNode(name);
875 
876  if (node != 0)
877  {
878  if (GenApi::IsReadable(node))
879  {
880  GenApi::IRegister *p=dynamic_cast<GenApi::IRegister *>(node);
881 
882  if (p != 0)
883  {
884  size_t n=static_cast<size_t>(p->GetLength());
885 
886  if (total) *total=n;
887 
888  len=std::min(len, n);
889  p->Get(buffer, static_cast<int64_t>(len));
890  ret=len;
891  }
892  else if (exception)
893  {
894  throw std::invalid_argument(std::string("Feature not of type register: ")+name);
895  }
896  }
897  else if (exception)
898  {
899  throw std::invalid_argument(std::string("Feature not readable: ")+name);
900  }
901  }
902  else if (exception)
903  {
904  throw std::invalid_argument(std::string("Feature not found: ")+name);
905  }
906  }
907  catch (const GENICAM_NAMESPACE::GenericException &ex)
908  {
909  if (exception)
910  {
911  throw std::invalid_argument(ex.what());
912  }
913  }
914 
915  return ret;
916 }
917 
918 std::string getString(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
919  bool exception, bool igncache)
920 {
921  std::ostringstream out;
922 
923  try
924  {
925  GenApi::INode *node=nodemap->_GetNode(name);
926 
927  if (node != 0)
928  {
929  if (GenApi::IsReadable(node))
930  {
931  switch (node->GetPrincipalInterfaceType())
932  {
934  {
935  GenApi::IBoolean *p=dynamic_cast<GenApi::IBoolean *>(node);
936  out << p->GetValue(false, igncache);
937  }
938  break;
939 
941  {
942  GenApi::IInteger *p=dynamic_cast<GenApi::IInteger *>(node);
943  int64_t value=p->GetValue(false, igncache);
944 
945  switch (p->GetRepresentation())
946  {
947  case GenApi::HexNumber:
948  out << std::hex << value;
949  break;
950 
951  case GenApi::IPV4Address:
952  out << ((value>>24)&0xff) << '.' << ((value>>16)&0xff) << '.'
953  << ((value>>8)&0xff) << '.' << (value&0xff);
954  break;
955 
956  case GenApi::MACAddress:
957  out << std::hex << std::setfill('0');
958  out << std::setw(2) << ((value>>40)&0xff) << ':'
959  << std::setw(2) << ((value>>32)&0xff) << ':'
960  << std::setw(2) << ((value>>24)&0xff) << ':'
961  << std::setw(2) << ((value>>16)&0xff) << ':'
962  << std::setw(2) << ((value>>8)&0xff) << ':'
963  << std::setw(2) << (value&0xff);
964  break;
965 
966  default:
967  out << value;
968  break;
969  }
970  }
971  break;
972 
973  case GenApi::intfIFloat:
974  {
975  GenApi::IFloat *p=dynamic_cast<GenApi::IFloat *>(node);
976  out << p->GetValue(false, igncache);
977  }
978  break;
979 
981  {
982  GenApi::IEnumeration *p=dynamic_cast<GenApi::IEnumeration *>(node);
983  out << p->GetCurrentEntry()->GetSymbolic();
984  }
985  break;
986 
988  {
989  GenApi::IRegister *p=dynamic_cast<GenApi::IRegister *>(node);
990 
991  int len=std::min(static_cast<int>(p->GetLength()), 32);
992 
993  uint8_t buffer[32];
994  p->Get(buffer, len);
995 
996  out << std::hex;
997  for (int i=0; i<len; i++)
998  {
999  out << std::setfill('0') << std::setw(2) << static_cast<int>(buffer[i]);
1000  }
1001  }
1002  break;
1003 
1004  case GenApi::intfIString:
1005  {
1006  GenApi::IString *p=dynamic_cast<GenApi::IString *>(node);
1007  out << p->GetValue(false, igncache);
1008  }
1009  break;
1010 
1011  default:
1012  if (exception)
1013  {
1014  throw std::invalid_argument(std::string("Feature of unknown datatype: ")+name);
1015  }
1016  break;
1017  }
1018  }
1019  else if (exception)
1020  {
1021  throw std::invalid_argument(std::string("Feature not readable: ")+name);
1022  }
1023  }
1024  else if (exception)
1025  {
1026  throw std::invalid_argument(std::string("Feature not found: ")+name);
1027  }
1028  }
1029  catch (const GENICAM_NAMESPACE::GenericException &ex)
1030  {
1031  if (exception)
1032  {
1033  throw std::invalid_argument(ex.what());
1034  }
1035  }
1036 
1037  return out.str();
1038 }
1039 
1040 void checkFeature(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
1041  const char *value, bool igncache)
1042 {
1043  std::string cvalue=getString(nodemap, name, true, igncache);
1044 
1045  if (cvalue != "" && cvalue != value)
1046  {
1047  std::ostringstream out;
1048  out << name << " == " << value << " expected: " << cvalue;
1049  throw std::invalid_argument(out.str());
1050  }
1051 }
1052 
1053 std::shared_ptr<GenApi::CChunkAdapter> getChunkAdapter(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
1054  const std::string &tltype)
1055 {
1056  std::shared_ptr<GenApi::CChunkAdapter> chunkadapter;
1057 
1058  if (setBoolean(nodemap, "ChunkModeActive", true))
1059  {
1060  if (tltype == "GEV")
1061  {
1062  chunkadapter=std::shared_ptr<GenApi::CChunkAdapter>(new GenApi::CChunkAdapterGEV(nodemap->_Ptr));
1063  }
1064  else if (tltype == "U3V")
1065  {
1066  chunkadapter=std::shared_ptr<GenApi::CChunkAdapter>(new GenApi::CChunkAdapterU3V(nodemap->_Ptr));
1067  }
1068  else
1069  {
1070  chunkadapter=std::shared_ptr<GenApi::CChunkAdapter>(new GenApi::CChunkAdapterGeneric(nodemap->_Ptr));
1071  }
1072  }
1073 
1074  return chunkadapter;
1075 }
1076 
1077 std::string getComponetOfPart(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
1078  const Buffer *buffer, uint32_t ipart)
1079 {
1080  std::string component;
1081 
1082  try
1083  {
1084  // get chunk component selector and proprietary chunk part index parmeters
1085 
1086  GenApi::IEnumeration *sel=dynamic_cast<GenApi::IEnumeration *>(nodemap->_GetNode("ChunkComponentSelector"));
1087  GenApi::IInteger *part=dynamic_cast<GenApi::IInteger *>(nodemap->_GetNode("ChunkPartIndex"));
1088 
1089  if (sel != 0 && part != 0)
1090  {
1091  if (GenApi::IsReadable(sel) && GenApi::IsWritable(sel) && GenApi::IsReadable(part))
1092  {
1093  // go through all available enumerations
1094 
1095  GenApi::NodeList_t list;
1096  sel->GetEntries(list);
1097 
1098  for (size_t i=0; i<list.size() && component.size() == 0; i++)
1099  {
1100  GenApi::IEnumEntry *entry=dynamic_cast<GenApi::IEnumEntry *>(list[i]);
1101 
1102  if (entry != 0 && GenApi::IsReadable(entry))
1103  {
1104  sel->SetIntValue(entry->GetValue());
1105 
1106  int64_t val=part->GetValue();
1107  if (val == ipart)
1108  {
1109  component=dynamic_cast<GenApi::IEnumEntry *>(list[i])->GetSymbolic();
1110  }
1111  }
1112  }
1113  }
1114  }
1115  }
1116  catch (const std::exception &)
1117  { /* ignore errors */ }
1118  catch (const GENICAM_NAMESPACE::GenericException &)
1119  { /* ignore errors */ }
1120 
1121  // try guessing component name from pixel format
1122 
1123  if (component.size() == 0 && buffer->getImagePresent(ipart))
1124  {
1125  switch (buffer->getPixelFormat(ipart))
1126  {
1127  case Mono8:
1128  case YCbCr411_8:
1129  if (buffer->getWidth(ipart) >= buffer->getHeight(ipart))
1130  {
1131  component="Intensity";
1132  }
1133  else
1134  {
1135  component="IntensityCombined";
1136  }
1137  break;
1138 
1139  case Coord3D_C16:
1140  component="Disparity";
1141  break;
1142 
1143  case Confidence8:
1144  component="Confidence";
1145  break;
1146 
1147  case Error8:
1148  component="Error";
1149  break;
1150 
1151  default:
1152  break;
1153  }
1154  }
1155 
1156  return component;
1157 }
1158 
1159 std::string loadFile(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
1160  bool exception)
1161 {
1162  std::string ret;
1163 
1164  // load file in pieces of 512 bytes
1165 
1167  rf.attach(nodemap->_Ptr);
1168 
1169  if (rf.openFile(name, std::ios::in))
1170  {
1171  int length=std::numeric_limits<int>::max();
1172  try
1173  {
1174  // limit read operation to file size, if available
1175  length=rcg::getInteger(nodemap, "FileSize", 0, 0, true);
1176  }
1177  catch (const std::exception &)
1178  { }
1179 
1180  size_t off=0, n=512;
1181  std::vector<char> buffer(512);
1182 
1183  while (n > 0 && length > 0)
1184  {
1185  n=rf.read(buffer.data(), off, std::min(length, static_cast<int>(buffer.size())), name);
1186 
1187  if (n == 0)
1188  {
1189  // workaround for reading last partial block if camera reports failure
1190 
1191  n=rcg::getInteger(nodemap, "FileOperationResult");
1192 
1193  if (n > 0)
1194  {
1195  n=rf.read(buffer.data(), off, n, name);
1196  }
1197  }
1198 
1199  if (n > 0)
1200  {
1201  ret.append(buffer.data(), n);
1202  }
1203 
1204  off+=n;
1205  length-=n;
1206  }
1207 
1208  rf.closeFile(name);
1209  }
1210  else
1211  {
1212  if (exception)
1213  {
1214  throw std::invalid_argument(std::string("Cannot open file for reading: ")+name);
1215  }
1216  }
1217 
1218  return ret;
1219 }
1220 
1221 bool saveFile(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
1222  const std::string &data, bool exception)
1223 {
1224  bool ret=true;
1225 
1226  // store in pieces of 512 bytes
1227 
1229  rf.attach(nodemap->_Ptr);
1230 
1231  if (rf.openFile(name, std::ios::out))
1232  {
1233  size_t off=0, n=512;
1234  while (n > 0)
1235  {
1236  n=rf.write(data.c_str()+off, off, std::min(static_cast<size_t>(512), data.size()-off), name);
1237  off+=n;
1238  }
1239 
1240  rf.closeFile(name);
1241 
1242  if (off != data.size())
1243  {
1244  if (exception)
1245  {
1246  std::ostringstream out;
1247  out << "Error: Can only write " << off << " of " << data.size() << " bytes";
1248  throw std::invalid_argument(out.str());
1249  }
1250 
1251  ret=false;
1252  }
1253  }
1254  else
1255  {
1256  if (exception)
1257  {
1258  throw std::invalid_argument(std::string("Cannot open file for writing: ")+name);
1259  }
1260 
1261  ret=false;
1262  }
1263 
1264  return ret;
1265 }
1266 
1267 bool loadStreamableParameters(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
1268  bool exception)
1269 {
1270  bool ret=false;
1271 
1272  try
1273  {
1274  GenApi::CFeatureBag bag;
1275 
1276  std::ifstream in;
1277  in.exceptions(std::ios_base::failbit | std::ios_base::badbit);
1278 
1279  in.open(name);
1280  in >> bag;
1281  in.close();
1282 
1283  bag.LoadFromBag(nodemap->_Ptr, true);
1284 
1285  ret=true;
1286  }
1287  catch (const std::exception &ex)
1288  {
1289  if (exception)
1290  {
1291  throw std::invalid_argument(ex.what());
1292  }
1293  }
1294  catch (const GENICAM_NAMESPACE::GenericException &ex)
1295  {
1296  if (exception)
1297  {
1298  throw std::invalid_argument(ex.what());
1299  }
1300  }
1301 
1302  return ret;
1303 }
1304 
1305 bool saveStreamableParameters(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap, const char *name,
1306  bool exception)
1307 {
1308  bool ret=false;
1309 
1310  try
1311  {
1312  GenApi::CFeatureBag bag;
1313 
1314  bag.StoreToBag(nodemap->_Ptr);
1315 
1316  std::ofstream out;
1317  out.exceptions(std::ios_base::failbit | std::ios_base::badbit);
1318 
1319  out.open(name);
1320  out << bag;
1321  out.close();
1322 
1323  ret=true;
1324  }
1325  catch (const std::exception &ex)
1326  {
1327  if (exception)
1328  {
1329  throw std::invalid_argument(ex.what());
1330  }
1331  }
1332  catch (const GENICAM_NAMESPACE::GenericException &ex)
1333  {
1334  if (exception)
1335  {
1336  throw std::invalid_argument(ex.what());
1337  }
1338  }
1339 
1340  return ret;
1341 }
1342 
1343 }
GENAPI_NAMESPACE::IInteger
GENICAM_INTERFACE IInteger
Interface for integer properties.
Definition: IFloat.h:114
GENAPI_NAMESPACE::intfIString
@ intfIString
IString interface.
Definition: Types.h:196
GENAPI_NAMESPACE::intfIBoolean
@ intfIBoolean
IBoolean interface.
Definition: Types.h:193
GENAPI_NAMESPACE::intfIRegister
@ intfIRegister
IRegister interface.
Definition: Types.h:197
GENAPI_NAMESPACE::intfIInteger
@ intfIInteger
IInteger interface.
Definition: Types.h:192
GENAPI_NAMESPACE::IsWritable
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition: INode.h:196
rcg::setIPV4Address
bool setIPV4Address(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of an integer feature of the given nodemap from an IP address.
Definition: config.cc:199
GENAPI_NAMESPACE::FileProtocolAdapter::closeFile
virtual bool closeFile(const char *pFileName)
close a file on the device
ChunkAdapterU3V.h
Declaration of the CChunkAdapterU3V class.
rcg::setFloat
bool setFloat(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, double value, bool exception)
Set the value of a float feature of the given nodemap.
Definition: config.cc:256
rcg::getFloat
double getFloat(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, double *vmin, double *vmax, bool exception, bool igncache)
Get the value of a double feature of the given nodemap.
Definition: config.cc:696
Confidence8
@ Confidence8
Definition: PFNC.h:442
rcg::Buffer::getImagePresent
bool getImagePresent(uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
Definition: buffer.cc:472
rcg::Buffer
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:118
rcg::getRegister
size_t getRegister(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, uint8_t *buffer, size_t len, size_t *total, bool exception, bool igncache)
Read value of type register.
Definition: config.cc:865
ChunkAdapterGEV.h
Declaration of the CChunkAdapterGEV class.
GENAPI_NAMESPACE::IBoolean
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IBoolean
Interface for Boolean properties.
Definition: IBoolean.h:61
rcg::getBoolean
bool getBoolean(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a boolean feature of the given nodemap.
Definition: config.cc:589
YCbCr411_8
@ YCbCr411_8
Definition: PFNC.h:499
rcg::setRegister
size_t setRegister(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const uint8_t *buffer, size_t len, bool exception)
Set value of type register.
Definition: config.cc:366
rcg::setBoolean
bool setBoolean(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool value, bool exception)
Set the value of a boolean feature of the given nodemap.
Definition: config.cc:107
rcg::loadFile
std::string loadFile(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Loads the contents of a file via the GenICam FileAccessControl interface.
Definition: config.cc:1159
GENAPI_NAMESPACE::CFeatureBag::LoadFromBag
bool LoadFromBag(INodeMap *pNodeMap, bool Verify=true, GENICAM_NAMESPACE::gcstring_vector *pErrorList=NULL)
Loads the features from the bag to the node tree.
GENAPI_NAMESPACE::GetSymbolic
virtual GENICAM_NAMESPACE::gcstring GetSymbolic() const =0
Get symbolic enum value.
rcg
Definition: buffer.cc:47
GENAPI_NAMESPACE::HexNumber
@ HexNumber
Hex number in an edit control.
Definition: Types.h:94
GENAPI_NAMESPACE::IPV4Address
@ IPV4Address
IP-Address.
Definition: Types.h:95
pixel_formats.h
GENAPI_NAMESPACE::IRegister
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IRegister
Interface for registers.
Definition: IRegister.h:61
rcg::callCommand
bool callCommand(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Calls the given command.
Definition: config.cc:61
rcg::Buffer::getHeight
size_t getHeight(uint32_t part) const
Returns the height of the image in pixel.
Definition: buffer.cc:369
rcg::getChunkAdapter
std::shared_ptr< GenApi::CChunkAdapter > getChunkAdapter(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const std::string &tltype)
NOTE: This function is deprecated.
Definition: config.cc:1053
GENAPI_NAMESPACE::intfIFloat
@ intfIFloat
IFloat interface.
Definition: Types.h:195
GENAPI_NAMESPACE::FileProtocolAdapter::write
virtual GenICam_streamsize write(const char *buf, int64_t offs, int64_t len, const char *pFileName)
writes data into a file
rcg::saveStreamableParameters
bool saveStreamableParameters(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Store all streamable parameters from the nodemap into the file.
Definition: config.cc:1305
GENAPI_NAMESPACE::ICommand
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT ICommand
Interface for command like properties.
Definition: ICommand.h:59
rcg::getEnum
std::string getEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Get the value of an enumeration of the given nodemap.
Definition: config.cc:747
Coord3D_C16
@ Coord3D_C16
Definition: PFNC.h:438
rcg::loadStreamableParameters
bool loadStreamableParameters(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Load all streamable parameters from file into the nodemap.
Definition: config.cc:1267
GENAPI_NAMESPACE::intfIEnumeration
@ intfIEnumeration
IEnumeration interface.
Definition: Types.h:199
rcg::saveFile
bool saveFile(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const std::string &data, bool exception)
Loads the contents of the given string as a file via the GenICam FileAccessControl interface.
Definition: config.cc:1221
GENICAM_NAMESPACE::getline
std::istream & getline(std::istream &is, GENICAM_NAMESPACE::gcstring &str)
STL getline.
Definition: GCString.h:194
GENAPI_NAMESPACE::CChunkAdapterGEV
Connects a chunked DCAM buffer to a node map.
Definition: ChunkAdapterGEV.h:57
ChunkAdapterGeneric.h
Declaration of the CChunkAdapterGeneric class.
GENICAM_NAMESPACE::GenericException::what
virtual const char * what() const
Get error description (overwrite from std:exception)
GENAPI_NAMESPACE::CFeatureBag
Bag holding streamable features of a nodetree.
Definition: Persistence.h:56
rcg::setInteger
bool setInteger(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, int64_t value, bool exception)
Set the value of an integer feature of the given nodemap.
Definition: config.cc:153
GENAPI_NAMESPACE::IEnumeration
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IEnumeration
Interface for enumeration properties.
Definition: IEnumeration.h:60
GENAPI_NAMESPACE::CFeatureBag::StoreToBag
int64_t StoreToBag(INodeMap *pNodeMap, const int MaxNumPersistSkriptEntries=-1, GENICAM_NAMESPACE::gcstring_vector *pFeatureFilter=NULL)
Stores the streamable nodes to this feature bag.
GENAPI_NAMESPACE::FileProtocolAdapter::attach
virtual bool attach(GENAPI_NAMESPACE::INodeMap *pInterface)
attach file protocol adapter to nodemap
GENAPI_NAMESPACE::CChunkAdapterU3V
Connects a chunked U3V buffer to a node map.
Definition: ChunkAdapterU3V.h:56
GENAPI_NAMESPACE::IsReadable
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition: INode.h:178
Filestream.h
Definition of ODevFileStream and IDevFileStream.
GENAPI_NAMESPACE::FileProtocolAdapter::openFile
virtual bool openFile(const char *pFileName, std::ios_base::openmode mode)
open a file on the device
buffer.h
GENAPI_NAMESPACE::IFloat
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IFloat
Interface for float properties.
Definition: IFloat.h:60
GENAPI_NAMESPACE::INode
GENICAM_INTERFACE INode
Interface common to all nodes.
Definition: ICategory.h:51
GENICAM_NAMESPACE::GenericException
GenICam's exception class.
Definition: GCException.h:63
config.h
rcg::checkFeature
void checkFeature(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool igncache)
Checks the value of given feature and throws an exception in case of a mismatch.
Definition: config.cc:1040
rcg::setString
bool setString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of a feature of the given nodemap.
Definition: config.cc:413
std::ostringstream::str
std::string str()
GENAPI_NAMESPACE::CChunkAdapterGeneric
Connects a generic chunked buffer to a node map.
Definition: ChunkAdapterGeneric.h:64
GENAPI_NAMESPACE::IString
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IString
Interface for string properties.
Definition: IString.h:61
int64_t
__int64 int64_t
Definition: config-win32.h:21
rcg::setEnum
bool setEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of an enumeration of the given nodemap.
Definition: config.cc:302
std::ostringstream
Definition: Portability.hh:42
Error8
#define Error8
Definition: pixel_formats.h:46
GENAPI_NAMESPACE::FileProtocolAdapter::read
virtual GenICam_streamsize read(char *buf, int64_t offs, GenICam_streamsize len, const char *pFileName)
read data from the device into a buffer
rcg::getComponetOfPart
std::string getComponetOfPart(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const Buffer *buffer, uint32_t ipart)
Definition: config.cc:1077
rcg::Buffer::getWidth
size_t getWidth(uint32_t part) const
Returns the width of the image in pixel.
Definition: buffer.cc:344
rcg::getInteger
int64_t getInteger(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, int64_t *vmin, int64_t *vmax, bool exception, bool igncache)
Get the value of an integer feature of the given nodemap.
Definition: config.cc:634
GENAPI_NAMESPACE::FileProtocolAdapter
Adapter between the std::iostreambuf and the SFNC Features representing the device filesystem.
Definition: Filestream.h:106
rcg::getString
std::string getString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a feature of the given nodemap.
Definition: config.cc:918
GCException.h
GENAPI_NAMESPACE::MACAddress
@ MACAddress
MAC-Address.
Definition: Types.h:96
GENAPI_NAMESPACE::StringList_t
GENICAM_NAMESPACE::gcstring_vector StringList_t
A list of strings.
Definition: Types.h:149
GENAPI_NAMESPACE::IEnumEntry
GENICAM_INTERFACE GENAPI_DECL_ABSTRACT IEnumEntry
Interface of single enum value.
Definition: IEnumEntry.h:60
rcg::Buffer::getPixelFormat
uint64_t getPixelFormat(uint32_t part) const
Returns the pixel format of the specified part as defined in the PFNC.
Definition: buffer.cc:519
Mono8
@ Mono8
Definition: PFNC.h:306
GENAPI_NAMESPACE::NodeList_t
node_vector NodeList_t
a list of node references
Definition: INode.h:55


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Dec 4 2024 03:10:11