3 #include <boost/property_tree/ptree.hpp>
4 #include <boost/property_tree/ini_parser.hpp>
5 #include <boost/lexical_cast.hpp>
6 #include <boost/algorithm/string.hpp>
33 uint8_t sub_index = 0;
34 int num = sscanf(str.c_str(),
"%hxsub%hhx", &index, &sub_index);
35 return (index << 16) | (num==2?sub_index:0xFFFF);
37 ObjectDict::Key::operator std::string()
const{
38 std::stringstream sstr;
39 sstr << std::hex << index();
40 if(hasSub()) sstr <<
"sub" << (int) sub_index();
44 boost::mutex::scoped_lock lock(mutex);
46 if(
entry->init_val.is_empty())
return;
48 if(valid && !
entry->def_val.is_empty() && buffer !=
entry->def_val.data())
return;
50 if(!valid || buffer !=
entry->init_val.data()){
51 buffer =
entry->init_val.data();
53 if(
entry->writable && (
entry->def_val.is_empty() ||
entry->init_val.data() !=
entry->def_val.data()))
54 write_delegate(*
entry, buffer);
58 boost::mutex::scoped_lock lock(mutex);
60 if(!valid &&
entry->readable){
61 read_delegate(*
entry, buffer);
64 if(valid) write_delegate(*
entry, buffer);
68 boost::mutex::scoped_lock lock(mutex);
69 if(!
entry->def_val.is_empty() &&
entry->def_val.type() == type_guard){
70 buffer =
entry->def_val.data();
78 if(it != ObjectDict::ObjectDictMap::const_iterator()){
80 }
else it =
dict_.begin();
81 return it !=
dict_.end();
84 boost::algorithm::to_lower(access);
85 entry.constant =
false;
87 entry.readable =
true;
88 entry.writable =
false;
89 }
else if (access ==
"wo"){
90 entry.readable =
false;
91 entry.writable =
true;
92 }
else if (access ==
"rw"){
93 entry.readable =
true;
94 entry.writable =
true;
95 }
else if (access ==
"rwr"){
96 entry.readable =
true;
97 entry.writable =
true;
98 }
else if (access ==
"rww"){
99 entry.readable =
true;
100 entry.writable =
true;
101 }
else if (access ==
"const"){
102 entry.readable =
true;
103 entry.writable =
false;
104 entry.constant =
true;
113 return strtol(s.c_str(), 0, 0);
116 return strtoul(s.c_str(), 0, 0);
119 return strtol(s.c_str(), 0, 0);
122 return strtoul(s.c_str(), 0, 0);
125 return strtol(s.c_str(), 0, 0);
128 return strtoul(s.c_str(), 0, 0);
132 return strtoll(s.c_str(), 0, 0);
135 return strtoull(s.c_str(), 0, 0);
138 template<
typename T>
HoldAny parse_int(boost::property_tree::iptree &pt,
const std::string &key){
139 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<T>());
141 std::string str = boost::trim_copy(pt.get<std::string>(key));
142 if(boost::istarts_with(str,
"$NODEID")){
144 }
else return HoldAny(int_from_string<T>(str));
149 if(pt.count(key) == 0 ||
can::hex2buffer(out,pt.get<std::string>(key),
true))
return HoldAny(TypeGuard::create<T>());
154 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<T>());
155 return HoldAny(pt.get<T>(key));
158 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<String>());
163 template<const ObjectDict::DataTypes dt>
static HoldAny func(boost::property_tree::iptree &pt,
const std::string &key);
164 static HoldAny read_value(boost::property_tree::iptree &pt, uint16_t data_type,
const std::string &key){
165 return branch_type<ReadAnyValue, HoldAny (boost::property_tree::iptree &, const std::string &)>(data_type)(pt, key);
168 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER8>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int8_t>(pt,key); }
169 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER16>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int16_t>(pt,key); }
170 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER32>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int32_t>(pt,key); }
171 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER64>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int64_t>(pt,key); }
173 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED8>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint8_t>(pt,key); }
174 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED16>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint16_t>(pt,key); }
175 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED32>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint32_t>(pt,key); }
176 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED64>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint64_t>(pt,key); }
178 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_DOMAIN>(boost::property_tree::iptree &pt,
const std::string &key)
179 {
return parse_octets<ObjectStorage::DataType<ObjectDict::DEFTYPE_DOMAIN>::type>(pt,key); }
181 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_OCTET_STRING>(boost::property_tree::iptree &pt,
const std::string &key)
182 {
return parse_octets<ObjectStorage::DataType<ObjectDict::DEFTYPE_OCTET_STRING>::type>(pt,key); }
185 return parse_typed_value<typename ObjectStorage::DataType<dt>::type>(pt, key);
188 template<
typename T>
void read_optional(T& var, boost::property_tree::iptree &pt,
const std::string &key){
189 var = pt.get(key, T());
192 template<
typename T>
void read_integer(T& var, boost::property_tree::iptree &pt,
const std::string &key){
193 var = int_from_string<T>(pt.get<std::string>(key));
196 template<
typename T> T
read_integer(boost::property_tree::iptree &pt,
const std::string &key){
197 return int_from_string<T>(pt.get<std::string>(key, std::string()));
202 read_integer<uint16_t>(
entry.data_type,
object,
"DataType");
203 entry.mappable =
object.get<
bool>(
"PDOMapping",
false);
216 boost::optional<boost::property_tree::iptree&>
object = pt.get_child_optional(name.substr(2));
219 std::shared_ptr<ObjectDict::Entry>
entry = std::make_shared<ObjectDict::Entry>();
221 entry->index = int_from_string<uint16_t>(name);
223 entry->desc =
object->get<std::string>(
"Denotation",
object->get<std::string>(
"ParameterName"));
227 entry->sub_index = sub_index? *sub_index: 0;
229 dict->insert(sub_index != 0,
entry);
231 uint8_t subs = read_integer<uint8_t>(*
object,
"CompactSubObj");
237 for(uint8_t i=1; i< subs; ++i){
238 std::string subname = pt.get<std::string>(name.substr(2)+
"Name." + boost::lexical_cast<std::string>((
int)i),
entry->desc + boost::lexical_cast<std::string>((
int)i));
239 subname = pt.get<std::string>(name.substr(2)+
"Denotation." + boost::lexical_cast<std::string>((
int)i), subname);
241 dict->insert(
true, std::make_shared<const canopen::ObjectDict::Entry>(
entry->index, i,
entry->data_type, name,
entry->readable,
entry->writable,
entry->mappable,
entry->def_val,
246 for(uint8_t i=0; i< subs; ++i){
247 std::stringstream buf;
248 buf << name <<
"sub" << std::hex << int(i);
257 catch(
const std::bad_cast &e){
258 throw ParseException(std::string(
"Type of ") + name +
" does not match or is not supported");
260 catch(
const std::exception&e){
261 throw ParseException(std::string(
"Cannot process ") + name +
": " + e.what());
265 if(!pt.count(key))
return;
267 boost::property_tree::iptree objects = pt.get_child(key);
268 uint16_t count = read_integer<uint16_t>(objects,
"SupportedObjects");
269 for(uint16_t i=0; i < count; ++i){
270 std::string name = objects.get<std::string>(boost::lexical_cast<std::string>(i+1));
276 boost::property_tree::iptree pt;
279 boost::property_tree::read_ini(path, pt);
281 boost::property_tree::iptree di = pt.get_child(
"DeviceInfo");
298 std::unordered_set<uint32_t> baudrates;
299 std::unordered_set<uint16_t> dummy_usage;
301 for(boost::property_tree::iptree::value_type &v: di){
302 if(v.first.find(
"BaudRate_") == 0){
303 uint16_t rate = int_from_string<uint16_t>(v.first.substr(9));
304 if(v.second.get_value<
bool>())
309 if(pt.count(
"DummyUsage")){
310 for(boost::property_tree::iptree::value_type &v: pt.get_child(
"DummyUsage")){
311 if(v.first.find(
"Dummy") == 0){
313 uint16_t dummy = int_from_string<uint16_t>(
"0x"+v.first.substr(5));
314 if(v.second.get_value<
bool>())
320 dict = std::make_shared<ObjectDict>(info);
322 for(Overlay::const_iterator it= overlay.begin(); it != overlay.end(); ++it){
323 pt.get_child(it->first).put(
"ParameterValue", it->second);
334 ObjectStorageMap::iterator it =
storage_.find(key);
341 if(!e->def_val.type().valid()){
347 std::pair<ObjectStorageMap::iterator, bool> ok =
storage_.insert(std::make_pair(key, data));
353 if(read_delegate && write_delegate){
355 it->second->force_write();
357 }
else if(write_delegate) {
359 it->second->force_write();
360 }
else if(read_delegate){
363 return it->second->size();
367 boost::mutex::scoped_lock lock(
mutex_);
372 return map(e, key,read_delegate, write_delegate);
374 catch(std::out_of_range) {
375 if(sub_index != 0)
throw;
379 return map(e, key, read_delegate, write_delegate);
392 if(!
entry->init_val.is_empty()){
393 ObjectStorageMap::iterator it =
storage_.find(key);
397 std::pair<ObjectStorageMap::iterator, bool> ok =
storage_.insert(std::make_pair(key, data));
407 boost::mutex::scoped_lock lock(
mutex_);
411 boost::mutex::scoped_lock lock(
mutex_);
413 ObjectDict::ObjectDictMap::const_iterator entry_it;
414 while(
dict_->iterate(entry_it)){
420 boost::mutex::scoped_lock lock(
mutex_);
421 for(ObjectStorageMap::iterator it =
storage_.begin(); it !=
storage_.end(); ++it){
426 template<const ObjectDict::DataTypes dt,
typename T> std::string
formatValue(
const T &value){
427 std::stringstream sstr;
431 template<> std::string formatValue<ObjectDict::DEFTYPE_DOMAIN>(
const std::string &value){
434 template<> std::string formatValue<ObjectDict::DEFTYPE_OCTET_STRING>(
const std::string &value){
441 return formatValue<dt>(cached? entry.
get_cached() : entry.
get() );
454 typedef HoldAny (*reader_type)(boost::property_tree::iptree &,
const std::string &);
456 boost::property_tree::iptree pt;
457 pt.put(
"value", value);
458 HoldAny any = reader(pt,
"value");
467 reader_type reader = branch_type<ReadAnyValue, HoldAny (boost::property_tree::iptree &, const std::string &)>(dt);
472 return branch_type<WriteStringValue, std::function<void (const std::string&)> (
ObjectStorage&,
const ObjectDict::Key &,
bool)>(data_type)(storage, key, cached);