Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
libuavcan_drivers/linux/apps/uavcan_nodetool.cpp
- Committer:
- RuslanUrya
- Date:
- 2018-04-14
- Revision:
- 0:dfe6edabb8ec
File content as of revision 0:dfe6edabb8ec:
/* * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> */ #include <iostream> #include <iomanip> #include <thread> #include <mutex> #include <map> #include <algorithm> #include <iterator> #include <uavcan_linux/uavcan_linux.hpp> #include <uavcan/protocol/node_status_monitor.hpp> #include "debug.hpp" #include <uavcan/protocol/param/GetSet.hpp> #include <uavcan/protocol/param/ExecuteOpcode.hpp> #include <uavcan/equipment/hardpoint/Command.hpp> namespace { class StdinLineReader { mutable std::mutex mutex_; std::thread thread_; std::queue<std::string> queue_; void worker() { while (true) { std::string input; std::getline(std::cin, input); std::lock_guard<std::mutex> lock(mutex_); queue_.push(input); } } public: StdinLineReader() : thread_(&StdinLineReader::worker, this) { thread_.detach(); } bool hasPendingInput() const { std::lock_guard<std::mutex> lock(mutex_); return !queue_.empty(); } std::string getLine() { std::lock_guard<std::mutex> lock(mutex_); if (queue_.empty()) { throw std::runtime_error("Input queue is empty"); } auto ret = queue_.front(); queue_.pop(); return ret; } std::vector<std::string> getSplitLine() { std::istringstream iss(getLine()); std::vector<std::string> out; std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(out)); return out; } }; uavcan_linux::NodePtr initNode(const std::vector<std::string>& ifaces, uavcan::NodeID nid, const std::string& name) { auto node = uavcan_linux::makeNode(ifaces, name.c_str(), uavcan::protocol::SoftwareVersion(), uavcan::protocol::HardwareVersion(), nid); node->setModeOperational(); return node; } template <typename DataType> typename DataType::Response call(uavcan_linux::BlockingServiceClient<DataType>& client, uavcan::NodeID server_node_id, const typename DataType::Request& request) { const int res = client.blockingCall(server_node_id, request, uavcan::MonotonicDuration::fromMSec(100)); ENFORCE(res >= 0); ENFORCE(client.wasSuccessful()); return client.getResponse(); } /* * Command table. * The structure is: * command_name : (command_usage_info, command_entry_point) * This code was written while listening to some bad dubstep so I'm not sure about its quality. */ const std::map<std::string, std::pair<std::string, std::function<void(const uavcan_linux::NodePtr&, const uavcan::NodeID, const std::vector<std::string>&)> > > commands = { { "param", { "No arguments supplied - requests all params from a remote node\n" "<param_name> <param_value> - assigns parameter <param_name> to value <param_value>", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>& args) { auto client = node->makeBlockingServiceClient<uavcan::protocol::param::GetSet>(); uavcan::protocol::param::GetSet::Request request; if (args.empty()) { while (true) { auto response = call(*client, node_id, request); if (response.name.empty()) { break; } std::cout << response << "\n" << std::string(80, '-') << std::endl; request.index++; } } else { request.name = args.at(0).c_str(); // TODO: add support for string parameters request.value.to<uavcan::protocol::param::Value::Tag::real_value>() = std::stof(args.at(1)); std::cout << call(*client, node_id, request) << std::endl; } } } }, { "param_save", { "Calls uavcan.protocol.param.ExecuteOpcode on a remote node with OPCODE_SAVE", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&) { auto client = node->makeBlockingServiceClient<uavcan::protocol::param::ExecuteOpcode>(); uavcan::protocol::param::ExecuteOpcode::Request request; request.opcode = request.OPCODE_SAVE; std::cout << call(*client, node_id, request) << std::endl; } } }, { "param_erase", { "Calls uavcan.protocol.param.ExecuteOpcode on a remote node with OPCODE_ERASE", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&) { auto client = node->makeBlockingServiceClient<uavcan::protocol::param::ExecuteOpcode>(); uavcan::protocol::param::ExecuteOpcode::Request request; request.opcode = request.OPCODE_ERASE; std::cout << call(*client, node_id, request) << std::endl; } } }, { "restart", { "Restarts a remote node using uavcan.protocol.RestartNode", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&) { auto client = node->makeBlockingServiceClient<uavcan::protocol::RestartNode>(); uavcan::protocol::RestartNode::Request request; request.magic_number = request.MAGIC_NUMBER; (void)client->blockingCall(node_id, request); if (client->wasSuccessful()) { std::cout << client->getResponse() << std::endl; } else { std::cout << "<NO RESPONSE>" << std::endl; } } } }, { "info", { "Calls uavcan.protocol.GetNodeInfo on a remote node", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&) { auto client = node->makeBlockingServiceClient<uavcan::protocol::GetNodeInfo>(); std::cout << call(*client, node_id, uavcan::protocol::GetNodeInfo::Request()) << std::endl; } } }, { "transport_stats", { "Calls uavcan.protocol.GetTransportStats on a remote node", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&) { auto client = node->makeBlockingServiceClient<uavcan::protocol::GetTransportStats>(); std::cout << call(*client, node_id, uavcan::protocol::GetTransportStats::Request()) << std::endl; } } }, { "hardpoint", { "Publishes uavcan.equipment.hardpoint.Command\n" "Expected argument: command", [](const uavcan_linux::NodePtr& node, const uavcan::NodeID, const std::vector<std::string>& args) { uavcan::equipment::hardpoint::Command msg; msg.command = std::stoi(args.at(0)); auto pub = node->makePublisher<uavcan::equipment::hardpoint::Command>(); (void)pub->broadcast(msg); } } } }; void runForever(const uavcan_linux::NodePtr& node) { StdinLineReader stdin_reader; std::cout << "> " << std::flush; while (true) { ENFORCE(node->spin(uavcan::MonotonicDuration::fromMSec(10)) >= 0); if (!stdin_reader.hasPendingInput()) { continue; } const auto words = stdin_reader.getSplitLine(); bool command_is_known = false; try { if (words.size() >= 2) { const auto cmd = words.at(0); const uavcan::NodeID node_id(std::stoi(words.at(1))); auto it = commands.find(cmd); if (it != std::end(commands)) { command_is_known = true; it->second.second(node, node_id, std::vector<std::string>(words.begin() + 2, words.end())); } } } catch (std::exception& ex) { std::cout << "FAILURE\n" << ex.what() << std::endl; } if (!command_is_known) { std::cout << "<command> <remote node id> [args...]\n"; std::cout << "Say 'help' to get help.\n"; // I'll show myself out. if (!words.empty() && words.at(0) == "help") { std::cout << "Usage:\n\n"; for (auto& cmd : commands) { std::cout << cmd.first << "\n" << cmd.second.first << "\n\n"; } } } std::cout << "> " << std::flush; } } } int main(int argc, const char** argv) { try { if (argc < 3) { std::cerr << "Usage:\n\t" << argv[0] << " <node-id> <can-iface-name-1> [can-iface-name-N...]" << std::endl; return 1; } const int self_node_id = std::stoi(argv[1]); const std::vector<std::string> iface_names(argv + 2, argv + argc); uavcan_linux::NodePtr node = initNode(iface_names, self_node_id, "org.uavcan.linux_app.nodetool"); runForever(node); return 0; } catch (const std::exception& ex) { std::cerr << "Error: " << ex.what() << std::endl; return 1; } }