An embedded device where Cyphal is the only external communication interface must ensure that it is always reachable over the network regardless of bad configuration to avoid brickage
. The two externally configured and thus potentially problematic parameters are the namespace and the remap string, where the latter can also be used to configure the namespace (using the =namespace syntax). Transport settings, if any, of course also matter but their handling is application-specific.
Retry cy_new() with empty namespace and empty remap
cy_new() may error out if the given namespace and/or remap string are invalid. If it fails, it should be retried with blank namespace and remap; the node may appear on the network differently but at least it will still be reachable. Example from a real codebase:
const auto cy_home = make_cy_home(get_uid_hash());
cy_t* cy = cy_new(cy_platform, cy_str(cy_home.data()), cy_str(""), remap);
if (cy == nullptr) {
// The remap string may be ill-formed; enter default-config recovery mode to remain reachable.
cy = cy_new(cy_platform, cy_str(cy_home.data()), cy_str(""), cy_str(""));
}
Configuration/management topics must always be available
Let’s say we have a management topic ~/manage that must be available so that the device is possible to configure. One might configure a bad remapping for it, which we must be able to mitigate. One example is when the namespace is long enough for the resolved topic name to spill over the length limit. There is no need to apply this solution to all topics, only to the critical ones (of which there is usually only one).
The solution is to make the topic name non-namespace-prefixable by making it either absolute (/foo) or homeful (~/foo) unless the home name can also be set externally.
manage_subscription_ = cy_subscribe(&cy_, cy_str("~/manage"), extent));
if (manage_subscription_ == nullptr) { // oops, cannot operate without the management topic!
cy_unremap(&cy_, cy_str("~/manage")); // erase potentially bad remapping if any (no op if no match)
manage_subscription_ = cy_subscribe(&cy_, cy_str("~/manage"), extent)); // retry
}
// Only if the home is remotely configurable:
if (manage_subscription_ == nullptr) {
cy_unremap(&cy_, cy_str("/manage_recovery"));
manage_subscription_ = cy_subscribe(&cy_, cy_str("/manage_recovery"), extent));
}