3 #include <boost/property_tree/ptree.hpp> 4 #include <boost/property_tree/ini_parser.hpp> 5 #include <boost/foreach.hpp> 6 #include <boost/lexical_cast.hpp> 7 #include <boost/algorithm/string.hpp> 34 uint8_t sub_index = 0;
35 int num = sscanf(str.c_str(),
"%hxsub%hhx", &index, &sub_index);
36 return (index << 16) | (num==2?sub_index:0xFFFF);
38 ObjectDict::Key::operator std::string()
const{
39 std::stringstream sstr;
40 sstr << std::hex << index();
41 if(hasSub()) sstr <<
"sub" << (int) sub_index();
45 boost::mutex::scoped_lock lock(mutex);
47 if(entry->init_val.is_empty())
return;
49 if(valid && !entry->def_val.is_empty() &&
buffer != entry->def_val.data())
return;
51 if(!valid ||
buffer != entry->init_val.data()){
52 buffer = entry->init_val.data();
54 if(entry->writable && (entry->def_val.is_empty() || entry->init_val.data() != entry->def_val.data()))
55 write_delegate(*entry,
buffer);
59 boost::mutex::scoped_lock lock(mutex);
61 if(!valid && entry->readable){
62 read_delegate(*entry,
buffer);
65 if(valid) write_delegate(*entry,
buffer);
69 boost::mutex::scoped_lock lock(mutex);
70 if(!entry->def_val.is_empty() && entry->def_val.type() ==
type_guard){
71 buffer = entry->def_val.data();
79 if(it != boost::unordered_map<Key, EntryConstSharedPtr >::const_iterator()){
81 }
else it = dict_.begin();
82 return it != dict_.end();
85 boost::algorithm::to_lower(access);
90 }
else if (access ==
"wo"){
93 }
else if (access ==
"rw"){
96 }
else if (access ==
"rwr"){
99 }
else if (access ==
"rww"){
102 }
else if (access ==
"const"){
114 return strtol(s.c_str(), 0, 0);
117 return strtoul(s.c_str(), 0, 0);
120 return strtol(s.c_str(), 0, 0);
123 return strtoul(s.c_str(), 0, 0);
126 return strtol(s.c_str(), 0, 0);
129 return strtoul(s.c_str(), 0, 0);
133 return strtoll(s.c_str(), 0, 0);
136 return strtoull(s.c_str(), 0, 0);
139 template<
typename T>
HoldAny parse_int(boost::property_tree::iptree &pt,
const std::string &key){
140 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<T>());
142 std::string str = boost::trim_copy(pt.get<std::string>(key));
143 if(boost::istarts_with(str,
"$NODEID")){
145 }
else return HoldAny(int_from_string<T>(str));
150 if(pt.count(key) == 0 ||
can::hex2buffer(out,pt.get<std::string>(key),
true))
return HoldAny(TypeGuard::create<T>());
155 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<T>());
156 return HoldAny(pt.get<T>(key));
159 if(pt.count(key) == 0)
return HoldAny(TypeGuard::create<String>());
164 template<const ObjectDict::DataTypes dt>
static HoldAny func(boost::property_tree::iptree &pt,
const std::string &key);
165 static HoldAny read_value(boost::property_tree::iptree &pt, uint16_t data_type,
const std::string &key){
166 return branch_type<ReadAnyValue, HoldAny (boost::property_tree::iptree &, const std::string &)>(data_type)(pt, key);
169 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER8>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int8_t>(pt,key); }
170 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER16>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int16_t>(pt,key); }
171 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER32>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int32_t>(pt,key); }
172 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_INTEGER64>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<int64_t>(pt,key); }
174 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED8>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint8_t>(pt,key); }
175 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED16>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint16_t>(pt,key); }
176 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED32>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint32_t>(pt,key); }
177 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_UNSIGNED64>(boost::property_tree::iptree &pt,
const std::string &key){
return parse_int<uint64_t>(pt,key); }
179 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_DOMAIN>(boost::property_tree::iptree &pt,
const std::string &key)
180 {
return parse_octets<ObjectStorage::DataType<ObjectDict::DEFTYPE_DOMAIN>::type>(pt,key); }
182 template<>
HoldAny ReadAnyValue::func<ObjectDict::DEFTYPE_OCTET_STRING>(boost::property_tree::iptree &pt,
const std::string &key)
183 {
return parse_octets<ObjectStorage::DataType<ObjectDict::DEFTYPE_OCTET_STRING>::type>(pt,key); }
186 return parse_typed_value<typename ObjectStorage::DataType<dt>::type>(pt, key);
189 template<
typename T>
void read_optional(T& var, boost::property_tree::iptree &pt,
const std::string &key){
190 var = pt.get(key, T());
193 template<
typename T>
void read_integer(T& var, boost::property_tree::iptree &pt,
const std::string &key){
194 var = int_from_string<T>(pt.get<std::string>(key));
197 template<
typename T> T
read_integer(boost::property_tree::iptree &pt,
const std::string &key){
198 return int_from_string<T>(pt.get<std::string>(key, std::string()));
203 read_integer<uint16_t>(entry.
data_type, object,
"DataType");
204 entry.
mappable =
object.get<
bool>(
"PDOMapping",
false);
206 set_access(entry,
object.get<std::string>(
"AccessType"));
217 boost::optional<boost::property_tree::iptree&>
object = pt.get_child_optional(name.substr(2));
220 boost::shared_ptr<ObjectDict::Entry> entry = boost::make_shared<ObjectDict::Entry>();
222 entry->index = int_from_string<uint16_t>(name);
223 entry->obj_code =
ObjectDict::Code(int_from_string<uint16_t>(object->get<std::string>(
"ObjectType", boost::lexical_cast<std::string>((uint16_t)
ObjectDict::VAR))));
224 entry->desc =
object->get<std::string>(
"Denotation",
object->get<std::string>(
"ParameterName"));
228 entry->sub_index = sub_index? *sub_index: 0;
230 dict->insert(sub_index != 0, entry);
232 uint8_t subs = read_integer<uint8_t>(*object,
"CompactSubObj");
238 for(uint8_t i=1; i< subs; ++i){
239 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));
240 subname = pt.get<std::string>(name.substr(2)+
"Denotation." + boost::lexical_cast<std::string>((int)i), subname);
242 dict->insert(
true, boost::make_shared<const canopen::ObjectDict::Entry>(entry->index, i, entry->data_type, name, entry->readable, entry->writable, entry->mappable, entry->def_val,
243 ReadAnyValue::read_value(pt, entry->data_type, name.substr(2)+
"Value." + boost::lexical_cast<std::string>((int)i))));
247 for(uint8_t i=0; i< subs; ++i){
248 std::stringstream buf;
249 buf << name <<
"sub" << std::hex << int(i);
258 catch(
const std::bad_cast &e){
259 throw ParseException(std::string(
"Type of ") + name +
" does not match or is not supported");
261 catch(
const std::exception&e){
262 throw ParseException(std::string(
"Cannot process ") + name +
": " + e.what());
266 if(!pt.count(key))
return;
268 boost::property_tree::iptree objects = pt.get_child(key);
269 uint16_t count = read_integer<uint16_t>(objects,
"SupportedObjects");
270 for(uint16_t i=0; i < count; ++i){
271 std::string name = objects.get<std::string>(boost::lexical_cast<std::string>(i+1));
277 boost::property_tree::iptree pt;
280 boost::property_tree::read_ini(path, pt);
282 boost::property_tree::iptree di = pt.get_child(
"DeviceInfo");
299 boost::unordered_set<uint32_t> baudrates;
300 boost::unordered_set<uint16_t> dummy_usage;
302 BOOST_FOREACH(boost::property_tree::iptree::value_type &v, di){
303 if(v.first.find(
"BaudRate_") == 0){
304 uint16_t rate = int_from_string<uint16_t>(v.first.substr(9));
305 if(v.second.get_value<
bool>())
310 if(pt.count(
"DummyUsage")){
311 BOOST_FOREACH(boost::property_tree::iptree::value_type &v, pt.get_child(
"DummyUsage")){
312 if(v.first.find(
"Dummy") == 0){
314 uint16_t dummy = int_from_string<uint16_t>(
"0x"+v.first.substr(5));
315 if(v.second.get_value<
bool>())
321 dict = boost::make_shared<ObjectDict>(info);
323 for(Overlay::const_iterator it= overlay.begin(); it != overlay.end(); ++it){
324 pt.get_child(it->first).put(
"ParameterValue", it->second);
335 boost::unordered_map<ObjectDict::Key, DataSharedPtr >::iterator it = storage_.find(key);
337 if(it == storage_.end()){
342 if(!e->def_val.type().valid()){
346 data = boost::make_shared<Data>(key, e,e->def_val.type(),read_delegate_, write_delegate_);
348 std::pair<boost::unordered_map<ObjectDict::Key, DataSharedPtr >::iterator,
bool> ok = storage_.insert(std::make_pair(key, data));
354 if(read_delegate && write_delegate){
355 it->second->set_delegates(read_delegate_, write_delegate);
356 it->second->force_write();
357 it->second->set_delegates(read_delegate, write_delegate_);
358 }
else if(write_delegate) {
359 it->second->set_delegates(read_delegate_, write_delegate);
360 it->second->force_write();
361 }
else if(read_delegate){
362 it->second->set_delegates(read_delegate, write_delegate_);
364 return it->second->size();
368 boost::mutex::scoped_lock lock(mutex_);
373 return map(e, key,read_delegate, write_delegate);
375 catch(std::out_of_range) {
376 if(sub_index != 0)
throw;
380 return map(e, key, read_delegate, write_delegate);
385 :read_delegate_(read_delegate), write_delegate_(write_delegate), dict_(dict), node_id_(node_id){
393 if(!entry->init_val.is_empty()){
394 boost::unordered_map<ObjectDict::Key, DataSharedPtr >::iterator it =
storage_.find(key);
398 std::pair<boost::unordered_map<ObjectDict::Key, DataSharedPtr >::iterator,
bool> ok =
storage_.insert(std::make_pair(key, data));
408 boost::mutex::scoped_lock lock(
mutex_);
412 boost::mutex::scoped_lock lock(
mutex_);
414 boost::unordered_map<ObjectDict::Key, ObjectDict::EntryConstSharedPtr >::const_iterator entry_it;
415 while(
dict_->iterate(entry_it)){
421 boost::mutex::scoped_lock lock(
mutex_);
422 for(boost::unordered_map<ObjectDict::Key, DataSharedPtr >::iterator it =
storage_.begin(); it !=
storage_.end(); ++it){
427 template<const ObjectDict::DataTypes dt,
typename T> std::string
formatValue(
const T &value){
428 std::stringstream sstr;
432 template<> std::string formatValue<ObjectDict::DEFTYPE_DOMAIN>(
const std::string &value){
435 template<> std::string formatValue<ObjectDict::DEFTYPE_OCTET_STRING>(
const std::string &value){
442 return formatValue<dt>(cached? entry.
get_cached() : entry.
get() );
455 typedef HoldAny (*reader_type)(boost::property_tree::iptree &,
const std::string &);
457 boost::property_tree::iptree pt;
458 pt.put(
"value", value);
459 HoldAny any = reader(pt,
"value");
468 reader_type reader = branch_type<ReadAnyValue, HoldAny (boost::property_tree::iptree &, const std::string &)>(dt);
473 return branch_type<WriteStringValue, boost::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
boost::shared_ptr< ObjectDict > ObjectDictSharedPtr
boost::shared_ptr< Data > DataSharedPtr
boost::function< void(const std::string &)> WriteStringFuncType
void init(const ObjectDict::Key &key)
Entry< T > entry(const ObjectDict::Key &key)
const String & data() const
static boost::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)
static boost::function< void(const std::string &)> func(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
boost::unordered_set< uint16_t > dummy_usage
bool simple_boot_up_slave
std::string formatValue(const T &value)
void set_access(ObjectDict::Entry &entry, std::string access)
boost::function< std::string()> ReadStringFuncType
HoldAny parse_int(boost::property_tree::iptree &pt, const std::string &key)
boost::shared_ptr< const ObjectDict > ObjectDictConstSharedPtr
void read_integer(T &var, boost::property_tree::iptree &pt, const std::string &key)
boost::unordered_set< uint32_t > baudrates
ObjectStorage(ObjectDictConstSharedPtr dict, uint8_t node_id, ReadDelegate read_delegate, WriteDelegate write_delegate)
ObjectDict::ObjectDictSharedPtr ObjectDictSharedPtr
void init_nolock(const ObjectDict::Key &key, const ObjectDict::EntryConstSharedPtr &entry)
ReadDelegate read_delegate_
static R * branch_type(const uint16_t data_type)
boost::unordered_map< ObjectDict::Key, DataSharedPtr > 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)
size_t map(const ObjectDict::EntryConstSharedPtr &e, const ObjectDict::Key &key, const ReadDelegate &read_delegate, const WriteDelegate &write_delegate)
static HoldAny read_value(boost::property_tree::iptree &pt, uint16_t data_type, const std::string &key)
bool iterate(boost::unordered_map< Key, EntryConstSharedPtr >::const_iterator &it) const
boost::shared_ptr< const Entry > EntryConstSharedPtr
WriteDelegate write_delegate_
HoldAny parse_octets(boost::property_tree::iptree &pt, const std::string &key)
bool hex2buffer(std::string &out, const std::string &in_raw, bool pad)
static boost::function< void(const std::string &)> getWriter(ObjectStorage &storage, const ObjectDict::Key &key, bool cached)
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::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)
void read_var(ObjectDict::Entry &entry, boost::property_tree::iptree &object)
HoldAny parse_typed_value(boost::property_tree::iptree &pt, const std::string &key)