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);
89 }
else if (access ==
"wo"){
92 }
else if (access ==
"rw"){
95 }
else if (access ==
"rwr"){
98 }
else if (access ==
"rww"){
101 }
else if (access ==
"const"){
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);
205 set_access(entry,
object.get<std::string>(
"AccessType"));
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);
222 entry->obj_code =
ObjectDict::Code(int_from_string<uint16_t>(object->get<std::string>(
"ObjectType", boost::lexical_cast<std::string>((uint16_t)
ObjectDict::VAR))));
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,
242 ReadAnyValue::read_value(pt, entry->data_type, name.substr(2)+
"Value." + boost::lexical_cast<std::string>((int)i))));
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);
336 if(it == storage_.end()){
341 if(!e->def_val.type().valid()){
345 data = std::make_shared<Data>(key, e,e->def_val.type(),read_delegate_, write_delegate_);
347 std::pair<ObjectStorageMap::iterator, bool> ok = storage_.insert(std::make_pair(key, data));
353 if(read_delegate && write_delegate){
354 it->second->set_delegates(read_delegate_, write_delegate);
355 it->second->force_write();
356 it->second->set_delegates(read_delegate, write_delegate_);
357 }
else if(write_delegate) {
358 it->second->set_delegates(read_delegate_, write_delegate);
359 it->second->force_write();
360 }
else if(read_delegate){
361 it->second->set_delegates(read_delegate, write_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);
384 :read_delegate_(read_delegate), write_delegate_(write_delegate), dict_(dict), node_id_(node_id){
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);
T int_from_string(const std::string &s)
const ObjectDictConstSharedPtr dict_
void read_optional(T &var, boost::property_tree::iptree &pt, const std::string &key)
std::list< std::pair< std::string, std::string > > Overlay
std::unordered_set< uint32_t > baudrates
std::function< std::string()> ReadStringFuncType
std::shared_ptr< const ObjectDict > ObjectDictConstSharedPtr
void init(const ObjectDict::Key &key)
Entry< T > entry(const ObjectDict::Key &key)
std::shared_ptr< Data > DataSharedPtr
static std::function< std::string()> getReader(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
static std::string func(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
static void write(ObjectStorage::Entry< T > entry, bool cached, reader_type reader, const std::string &value)
static ObjectDictSharedPtr fromFile(const std::string &path, const Overlay &overlay=Overlay())
HoldAny parse_typed_value< String >(boost::property_tree::iptree &pt, const std::string &key)
static HoldAny func(boost::property_tree::iptree &pt, const std::string &key)
bool dynamic_channels_supported
std::string buffer2hex(const std::string &in, bool lc)
bool iterate(ObjectDictMap::const_iterator &it) const
bool simple_boot_up_slave
std::string formatValue(const T &value)
void set_access(ObjectDict::Entry &entry, std::string access)
std::shared_ptr< const Entry > EntryConstSharedPtr
std::unordered_set< uint16_t > dummy_usage
ObjectStorage(ObjectDictConstSharedPtr dict, uint8_t node_id, ReadFunc read_delegate, WriteFunc write_delegate)
HoldAny parse_int(boost::property_tree::iptree &pt, const std::string &key)
void read_integer(T &var, boost::property_tree::iptree &pt, const std::string &key)
ObjectDict::ObjectDictSharedPtr ObjectDictSharedPtr
WriteFunc write_delegate_
void init_nolock(const ObjectDict::Key &key, const ObjectDict::EntryConstSharedPtr &entry)
static std::function< void(const std::string &)> getWriter(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
static R * branch_type(const uint16_t data_type)
ObjectStorageMap storage_
bool simple_boot_up_master
void parse_objects(ObjectDictSharedPtr dict, boost::property_tree::iptree &pt, const std::string &key)
bool set_cached(const T &val)
std::size_t hash_value(ObjectDict::Key const &k)
static HoldAny read_value(boost::property_tree::iptree &pt, uint16_t data_type, const std::string &key)
size_t map(const ObjectDict::EntryConstSharedPtr &e, const ObjectDict::Key &key, const ReadFunc &read_delegate, const WriteFunc &write_delegate)
std::shared_ptr< ObjectDict > ObjectDictSharedPtr
static std::function< void(const std::string &)> func(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
HoldAny parse_octets(boost::property_tree::iptree &pt, const std::string &key)
bool hex2buffer(std::string &out, const std::string &in_raw, bool pad)
WriteStringFuncType getStringWriter(const ObjectDict::Key &key, bool cached=false)
ReadStringFuncType getStringReader(const ObjectDict::Key &key, bool cached=false)
#define THROW_WITH_KEY(e, k)
std::function< void(const ObjectDict::Entry &, const String &)> WriteFunc
std::ostream & operator<<(std::ostream &stream, const NodeIdOffset< T > &n)
static size_t fromString(const std::string &str)
void parse_object(ObjectDictSharedPtr dict, boost::property_tree::iptree &pt, const std::string &name, const uint8_t *sub_index=0)
std::function< void(const std::string &)> WriteStringFuncType
void read_var(ObjectDict::Entry &entry, boost::property_tree::iptree &object)
std::function< void(const ObjectDict::Entry &, String &)> ReadFunc
const String & data() const
HoldAny parse_typed_value(boost::property_tree::iptree &pt, const std::string &key)