aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2017-06-13 17:20:05 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2017-06-13 17:20:05 +0200
commit014ba2dd29eaadb4d61948ca417c25112f76ee0e (patch)
tree85a9e9540ebcea63053a817993290eac45076962 /src
parent21ffc6687e175d5cfb73500e45e61195d061ec72 (diff)
Import CAN generator from low-level-can-service
Also use the app-templates CMake helpers. Change-Id: I034e5efa9baa0f686a081f60df5c3588e4b3bd51 Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt44
-rw-r--r--src/main.cpp395
-rw-r--r--src/main.hpp55
-rwxr-xr-xsrc/openxc/can_bus.cpp89
-rwxr-xr-xsrc/openxc/can_bus.hpp42
-rwxr-xr-xsrc/openxc/can_message.cpp126
-rwxr-xr-xsrc/openxc/can_message.hpp49
-rwxr-xr-xsrc/openxc/command.cpp45
-rwxr-xr-xsrc/openxc/command.hpp25
-rwxr-xr-xsrc/openxc/diagnostic_message.cpp80
-rwxr-xr-xsrc/openxc/diagnostic_message.hpp35
-rwxr-xr-xsrc/openxc/mapping.cpp59
-rwxr-xr-xsrc/openxc/mapping.hpp29
-rwxr-xr-xsrc/openxc/message_set.cpp145
-rwxr-xr-xsrc/openxc/message_set.hpp59
-rwxr-xr-xsrc/openxc/signal.cpp142
-rwxr-xr-xsrc/openxc/signal.hpp53
17 files changed, 1472 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..263185f
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,44 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Romain Forlot <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(can-config-generator)
+
+ # Define project Targets
+ add_executable(${TARGET_NAME}
+ main.cpp
+ openxc/message_set.cpp
+ openxc/can_bus.cpp
+ openxc/can_message.cpp
+ openxc/command.cpp
+ openxc/diagnostic_message.cpp
+ openxc/mapping.cpp
+ openxc/signal.cpp)
+
+ TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/json
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(can-config-generator
+ ${link_libraries}
+ )
+
+ # installation directory
+ INSTALL(TARGETS can-config-generator
+RUNTIME DESTINATION ${BINDINGS_INSTALL_DIR})
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..d30428e
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Loïc Collignon" <loic.collignon@iot.bzh>
+ * Author "Romain Forlot" <romain.forlot@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <exception>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <numeric>
+#include <iterator>
+#include <json.hpp>
+#include "openxc/message_set.hpp"
+
+#define EXIT_SUCCESS 0
+#define EXIT_UNKNOWN_ERROR 1
+#define EXIT_COMMAND_LINE_ERROR 2
+#define EXIT_PROGRAM_ERROR 3
+
+template <typename T>
+struct generator
+{
+ T v_;
+ std::string line_prefix_;
+ generator(T v, std::string line_prefix = "") : v_{v}, line_prefix_{line_prefix} {}
+};
+
+template <>
+struct generator<openxc::signal>
+{
+ const openxc::signal& v_;
+ std::uint32_t index_;
+ std::string line_prefix_;
+ generator(const openxc::signal& v, std::uint32_t index, std::string line_prefix = "")
+ : v_{v}, index_{index}, line_prefix_{line_prefix}
+ {
+ }
+};
+
+template <typename T>
+generator<T> gen(const T& v, std::string line_prefix = "") { return generator<T>(v, line_prefix); }
+
+generator<openxc::signal> gen(const openxc::signal& v, std::uint32_t index, std::string line_prefix = "")
+{
+ return generator<openxc::signal>(v, index, line_prefix);
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& o, const generator<T>& v)
+{
+ o << v.line_prefix_ << v.v_;
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<bool>& v)
+{
+ o << v.line_prefix_ << (v.v_ ? "true" : "false");
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<float>& v)
+{
+ o << v.line_prefix_ << std::showpoint << v.v_ << "f";
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<std::string>& v)
+{
+ o << v.line_prefix_ << '\"' << v.v_ << '\"';
+ return o;
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& o, const generator<std::vector<T>>& v)
+{
+// o << v.line_prefix_;
+ auto sz = v.v_.size();
+ for(const T& i : v.v_)
+ {
+ o << gen(i, v.line_prefix_ + '\t');
+ if (sz > 1) o << ",";
+ --sz;
+// o << '\n';
+ }
+// o << v.line_prefix_;
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<openxc::message_set>& v)
+{
+ o << v.line_prefix_
+ << "{std::make_shared<can_message_set_t>(can_message_set_t{"
+ << "0,"
+ << gen(v.v_.name()) << ",\n"
+ << "\t\t\t{ // beginning can_message_definition_ vector\n"
+ << gen(v.v_.messages(), "\t\t\t")
+ << "\n\t\t}, // end can_message_definition vector\n"
+ << "\t\t\t{ // beginning diagnostic_messages_ vector\n"
+ << gen(v.v_.diagnostic_messages(),"\t\t\t") << "\n"
+ << "\t\t\t} // end diagnostic_messages_ vector\n"
+ << "\t\t})} // end can_message_set entry\n";
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<std::map<std::string, std::vector<std::uint32_t>>>& v)
+{
+ o << v.line_prefix_ << "{\n";
+ std::uint32_t c1 = (uint32_t)v.v_.size();
+ for(const auto& state : v.v_)
+ {
+ std::uint32_t c2 = (uint32_t)state.second.size();
+ for(const auto& i : state.second)
+ {
+ o << v.line_prefix_ << "\t" << "{" << i << "," << gen(state.first) << "}";
+ if (c1 > 1 || c2 > 1) o << ',';
+ o << '\n';
+ --c2;
+ }
+ --c1;
+ }
+ o << v.line_prefix_ << "}";
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<openxc::signal>& v)
+{
+ o << v.line_prefix_ << "{std::make_shared<can_signal_t> (can_signal_t{\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.generic_name()) << ",\n"
+ << v.line_prefix_ << "\t" << v.v_.bit_position() << ",\n"
+ << v.line_prefix_ << "\t" << v.v_.bit_size() << ",\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.factor()) << ",\n"
+ << v.line_prefix_ << "\t" << v.v_.offset() << ",\n"
+ << v.line_prefix_ << "\t" << "0,\n"
+ << v.line_prefix_ << "\t" << "0,\n"
+ << v.line_prefix_ << "\tfrequency_clock_t(" << gen(v.v_.max_frequency()) << "),\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.send_same()) << ",\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.force_send_changed()) << ",\n"
+ << gen(v.v_.states(), v.line_prefix_ + '\t') << ",\n"
+ << v.line_prefix_ << '\t' << gen(v.v_.writable()) << ",\n"
+ << v.line_prefix_ << '\t' << (v.v_.decoder().size() ? v.v_.decoder() : "nullptr") << ",\n"
+ << v.line_prefix_ << '\t' << (v.v_.encoder().size() ? v.v_.encoder() : "nullptr") << ",\n"
+ << v.line_prefix_ << '\t' << "false\n"
+ << v.line_prefix_ << "})}";
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<openxc::can_message>& v)
+{
+ o << v.line_prefix_
+ << "{std::make_shared<can_message_definition_t>(can_message_definition_t{"
+ << gen(v.v_.bus()) << ","
+ << v.v_.id() << ","
+ << "can_message_format_t::STANDARD,"
+ << "frequency_clock_t(" << gen(v.v_.max_frequency()) << "),"
+ << gen(v.v_.force_send_changed()) << ",\n";
+ std::uint32_t index = 0;
+ o << "\t\t\t\t\t{ // beginning can_signals vector\n";
+ std::uint32_t signal_count = (uint32_t)v.v_.signals().size();
+ for(const openxc::signal& s : v.v_.signals())
+ {
+ o << gen(s, index,"\t\t\t\t\t\t");
+ if (signal_count > 1) o << ',';
+ --signal_count;
+ o << '\n';
+ }
+ o << "\t\t\t\t\t} // end can_signals vector\n"
+ << "\t\t\t\t})} // end can_message_definition entry\n";
+ return o;
+}
+
+template <>
+std::ostream& operator<<(std::ostream& o, const generator<openxc::diagnostic_message>& v)
+{
+ o << v.line_prefix_ << "{std::make_shared<diagnostic_message_t>(diagnostic_message_t{\n"
+ << v.line_prefix_ << "\t" << v.v_.pid() << ",\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.name()) << ",\n"
+ << v.line_prefix_ << "\t" << 0 << ",\n"
+ << v.line_prefix_ << "\t" << 0 << ",\n"
+ << v.line_prefix_ << "\t" << "UNIT::INVALID" << ",\n"
+ << v.line_prefix_ << "\t" << gen(v.v_.frequency()) << ",\n"
+ << v.line_prefix_ << "\t" << (v.v_.decoder().size() ? v.v_.decoder() : "nullptr") << ",\n"
+ << v.line_prefix_ << "\t" << (v.v_.callback().size() ? v.v_.callback() : "nullptr") << ",\n"
+ << v.line_prefix_ << "\t" << "true" << "\n"
+ << v.line_prefix_ << "})}\n";
+ return o;
+}
+
+/// @brief Generate the application code.
+/// @param[in] header Content to be inserted as a header.
+/// @param[in] footer Content to be inserted as a footer.
+/// @param[in] message_set application read from the json file.
+/// @param[in] out Stream to write on.
+void generate(const std::string& header, const std::string& footer, const openxc::message_set& message_set, std::ostream& out)
+{
+ out << "#include \"application.hpp\"\n"
+ << "#include \"../can/can-decoder.hpp\"\n\n";
+
+ if (header.size()) out << header << "\n";
+
+ out << "application_t::application_t()\n"
+ << " : can_bus_manager_{utils::config_parser_t{\"/etc/dev-mapping.conf\"}}\n"
+ << " , can_message_set_{\n"
+ << gen(message_set, "\t\t")
+ << "\t} // end can_message_set vector\n"
+ << "{\n"
+ << " for(auto& cms: can_message_set_)\n"
+ << " {\n"
+ << " std::vector<std::shared_ptr<can_message_definition_t> >& can_messages_definition = cms->get_can_message_definition();\n"
+ << " for(auto& cmd : can_messages_definition)\n"
+ << " {\n"
+ << " cmd->set_parent(cms.get());\n"
+ << " std::vector<std::shared_ptr<can_signal_t> >& can_signals = cmd->get_can_signals();\n"
+ << " for(auto& sig: can_signals)\n"
+ << " {\n"
+ << " sig->set_parent(cmd.get());\n"
+ << " }\n"
+ << " }\n\n"
+ << " std::vector<std::shared_ptr<diagnostic_message_t> >& diagnostic_messages = cms->get_diagnostic_messages();\n"
+ << " for(auto& dm : diagnostic_messages)\n"
+ << " {\n"
+ << " dm->set_parent(cms.get());\n"
+ << " }\n"
+ << " }\n"
+ << " }\n\n"
+ << "const std::string application_t::get_diagnostic_bus() const\n"
+ << "{\n";
+
+ std::string active_bus = "";
+ for (const auto& d : message_set.diagnostic_messages())
+ {
+ if (d.bus().size() == 0) std::cerr << "ERROR: The bus name should be set for each diagnostic message." << std::endl;
+ if (active_bus.size() == 0) active_bus = d.bus();
+ if (active_bus != d.bus()) std::cerr << "ERROR: The bus name should be the same for each diagnostic message." << std::endl;
+ }
+
+ out << "\treturn " << gen(active_bus) << ";\n"
+ << "}\n\n";
+ out << footer << std::endl;
+}
+
+/// @brief Read whole file content to a string.
+/// @param[in] file Path to the file.
+/// @return A std::string which contains the file content. If @c file is an empty string, the return value is also empty.
+/// @exception std::runtime_error Throw this exception if the specified file is not found or cannot be opened.
+std::string read_file(const std::string& file)
+{
+ if(file.size() == 0) return std::string();
+
+ std::string content;
+ std::ifstream stream(file);
+ if (stream)
+ {
+ stream.seekg(0, std::ios::end);
+ content.reserve(stream.tellg());
+ stream.seekg(0, std::ios::beg);
+ content.assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
+ return content;
+ }
+ std::stringstream ss;
+ ss << "The specified file (" << file << ") is not found!";
+ throw std::runtime_error(ss.str());
+}
+
+/// @brief Read whole file content as a json document.
+/// @param[in] file Path to the file.
+/// @return A @c nlohmann::json object.
+/// @exception std::runtime_error Throw this exception if the specified file is not found or cannot be opened.
+nlohmann::json read_json(const std::string& file)
+{
+ std::ifstream stream(file);
+ if (stream)
+ {
+ nlohmann::json result;
+ stream >> result;
+ return result;
+ }
+ std::stringstream ss;
+ ss << "The specified file (" << file << ") is not found!";
+ throw std::runtime_error(ss.str());
+}
+
+// function that show the help information
+void showhelpinfo(char *s)
+{
+std::cout<<"Usage: "<<s<<" <-m inpout.json> [-o application-generated.cpp]"<< std::endl;
+std::cout<<"option: "<<"-m input.json : JSON file describing CAN messages and signals"<< std::endl;
+std::cout<<" "<<"-h header.cpp : header source file insert at the beginning of generated file"<< std::endl;
+std::cout<<" "<<"-f footer.cpp : footer source file append to generated file."<< std::endl;
+std::cout<<" "<<"-o application-generated.cpp : output source file. Name has to be application-generated.cpp"<< std::endl;
+}
+
+/// @brief Entry point.
+/// @param[in] argc Argument's count.
+/// @param[in] argv Argument's array.
+/// @return Exit code, zero if success.
+int main(int argc, char *argv[])
+{
+ try
+ {
+ std::string appName = argv[0];
+ std::string message_set_file;
+ std::string output_file;
+ std::string header_file;
+ std::string footer_file;
+
+ char tmp;
+ /*if the program is ran witout options ,it will show the usgage and exit*/
+ if(argc == 1)
+ {
+ showhelpinfo(argv[0]);
+ exit(1);
+ }
+ /*use function getopt to get the arguments with option."hu:p:s:v" indicate
+ that option h,v are the options without arguments while u,p,s are the
+ options with arguments*/
+ while((tmp=(char)getopt(argc,argv,"m:h:f:o:"))!=-1)
+ {
+ switch(tmp)
+ {
+ case 'h':
+ header_file = optarg;
+ break;
+ case 'f':
+ footer_file = optarg;
+ break;
+ case 'm':
+ message_set_file = optarg;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ default:
+ showhelpinfo(argv[0]);
+ break;
+ }
+ }
+
+ std::stringstream header;
+ header << read_file(header_file);
+
+ std::string footer = read_file(footer_file);
+ openxc::message_set message_set;
+ message_set.from_json(read_json(message_set_file));
+
+ std::string message_set_path = dirname(strdup(message_set_file.c_str()));
+ for(const auto& s : message_set.extra_sources())
+ {
+ std::string extra_source = s;
+ extra_source = message_set_path + "/" + extra_source;
+ header << "\n// >>>>> " << s << " >>>>>\n" << read_file(extra_source) << "\n// <<<<< " << s << " <<<<<\n";
+ }
+
+ std::ofstream out;
+ if (output_file.size())
+ {
+ out.open(output_file);
+ if(!out)
+ {
+ std::stringstream ss;
+ ss << "Can't open the ouput file (" << output_file << ") for writing!";
+ throw std::runtime_error(ss.str());
+ }
+ }
+ generate(header.str(), footer, message_set, output_file.size() ? out : std::cout);
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "ERROR: Unhandled exception - " << e.what() << std::endl;
+ return EXIT_UNKNOWN_ERROR;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/main.hpp b/src/main.hpp
new file mode 100644
index 0000000..cf08e1a
--- /dev/null
+++ b/src/main.hpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015, 20"IoT.bzh"
+ * Author "Romain Forlot" <romain.forlot@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+struct afb_config_list {
+ struct afb_config_list *next;
+ char *value;
+};
+
+// main config structure
+struct afb_config {
+ char *console; // console device name (can be a file or a tty)
+ char *rootdir; // base dir for files
+ char *roothttp; // directory for http files
+ char *rootbase; // Angular HTML5 base URL
+ char *rootapi; // Base URL for REST APIs
+ char *workdir; // where to run the program
+ char *uploaddir; // where to store transient files
+ char *token; // initial authentication token [default NULL no session]
+
+ struct afb_config_list *aliases;
+ struct afb_config_list *dbus_clients;
+ struct afb_config_list *dbus_servers;
+ struct afb_config_list *ws_clients;
+ struct afb_config_list *ws_servers;
+ struct afb_config_list *so_bindings;
+ struct afb_config_list *ldpaths;
+
+ char **exec;
+
+ int httpdPort;
+ int background; // run in backround mode
+ int cacheTimeout;
+ int apiTimeout;
+ int cntxTimeout; // Client Session Context timeout
+ int nbSessionMax; // max count of sessions
+ int mode; // mode of listening
+ int tracereq;
+ int noHttpd;
+};
+
+extern struct afb_config *parse_arguments(int argc, char **argv); \ No newline at end of file
diff --git a/src/openxc/can_bus.cpp b/src/openxc/can_bus.cpp
new file mode 100755
index 0000000..0a968a9
--- /dev/null
+++ b/src/openxc/can_bus.cpp
@@ -0,0 +1,89 @@
+#include "can_bus.hpp"
+
+namespace openxc
+{
+ std::uint32_t can_bus::controller() const
+ {
+ return controller_;
+ }
+
+ std::uint32_t can_bus::speed() const
+ {
+ return speed_;
+ }
+
+ can_bus_mode can_bus::raw_can_mode() const
+ {
+ return raw_can_mode_;
+ }
+
+ bool can_bus::raw_writable() const
+ {
+ return raw_writable_;
+ }
+
+ float can_bus::max_message_frequency() const
+ {
+ return max_message_frequency_;
+ }
+
+ bool can_bus::force_send_changed() const
+ {
+ return force_send_changed_;
+ }
+
+ void can_bus::from_json(const nlohmann::json& j)
+ {
+ controller_ = j.count("controller") ? j["controller"].get<std::uint32_t>() : 1;
+ speed_ = j.count("speed") ? j["speed"].get<std::uint32_t>() : 0;
+ raw_can_mode_ = j.count("raw_can_mode") ? j["raw_can_mode"].get<can_bus_mode>() : can_bus_mode::off;
+ raw_writable_ = j.count("raw_writable") ? j["raw_writable"].get<bool>() : false;
+ max_message_frequency_ = j.count("max_message_frequency") ? j["max_message_frequency"].get<float>() : 0;
+ force_send_changed_ = j.count("force_send_changed") ? j["force_send_changed"].get<bool>() : false;
+ }
+
+ nlohmann::json can_bus::to_json() const
+ {
+ nlohmann::json j;
+ j["controller"] = controller_;
+ j["speed"] = speed_;
+ j["raw_can_mode"] = raw_can_mode_;
+ j["raw_writable"] = raw_writable_;
+ j["max_message_frequency"] = max_message_frequency_;
+ j["force_send_changed"] = force_send_changed_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const can_bus& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, can_bus& p)
+ {
+ p.from_json(j);
+ }
+
+ void to_json(nlohmann::json& j, const can_bus_mode& p)
+ {
+ switch (p)
+ {
+ case can_bus_mode::off:
+ j = std::string("off");
+ break;
+ case can_bus_mode::filtered:
+ j = std::string("filtered");
+ break;
+ case can_bus_mode::unfiltered:
+ j = std::string("unfiltered");
+ break;
+ }
+ }
+
+ void from_json(const nlohmann::json& j, can_bus_mode& p)
+ {
+ if (j.get<std::string>() == "off") p = can_bus_mode::off;
+ else if (j.get<std::string>() == "filtered") p = can_bus_mode::filtered;
+ else p = can_bus_mode::unfiltered;
+ }
+}
diff --git a/src/openxc/can_bus.hpp b/src/openxc/can_bus.hpp
new file mode 100755
index 0000000..74e1273
--- /dev/null
+++ b/src/openxc/can_bus.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <cstdint>
+#include <json.hpp>
+
+namespace openxc
+{
+ enum class can_bus_mode
+ {
+ off,
+ filtered,
+ unfiltered
+ };
+
+ class can_bus
+ {
+ private:
+ std::uint32_t controller_;
+ std::uint32_t speed_;
+ can_bus_mode raw_can_mode_;
+ bool raw_writable_;
+ float max_message_frequency_;
+ bool force_send_changed_;
+
+ public:
+ std::uint32_t controller() const;
+ std::uint32_t speed() const;
+ can_bus_mode raw_can_mode() const;
+ bool raw_writable() const;
+ float max_message_frequency() const;
+ bool force_send_changed() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const can_bus& p);
+ void from_json(const nlohmann::json& j, can_bus& p);
+
+ void to_json(nlohmann::json& j, const can_bus_mode& p);
+ void from_json(const nlohmann::json& j, can_bus_mode& p);
+}
diff --git a/src/openxc/can_message.cpp b/src/openxc/can_message.cpp
new file mode 100755
index 0000000..40e897b
--- /dev/null
+++ b/src/openxc/can_message.cpp
@@ -0,0 +1,126 @@
+#include "can_message.hpp"
+
+namespace openxc
+{
+ std::string can_message::id() const
+ {
+ return id_;
+ }
+
+ void can_message::id(const std::string& id)
+ {
+ id_ = id;
+ }
+
+ std::string can_message::bus() const
+ {
+ return bus_;
+ }
+
+ bool can_message::bit_numbering_inverted() const
+ {
+ return bit_numbering_inverted_;
+ }
+
+ const std::vector<signal>& can_message::signals() const
+ {
+ return signals_;
+ }
+
+ std::string can_message::name() const
+ {
+ return name_;
+ }
+
+ std::vector<std::string> can_message::handlers() const
+ {
+ return handlers_;
+ }
+
+ bool can_message::enabled() const
+ {
+ return enabled_;
+ }
+
+ float can_message::max_frequency() const
+ {
+ return max_frequency_;
+ }
+
+ float can_message::max_signal_frequency() const
+ {
+ return max_signal_frequency_;
+ }
+
+ bool can_message::force_send_changed() const
+ {
+ return force_send_changed_;
+ }
+
+ bool can_message::force_send_changed_signals() const
+ {
+ return force_send_changed_;
+ }
+
+ void can_message::from_json(const nlohmann::json& j)
+ {
+ bus_ = j.count("bus") ? j["bus"].get<std::string>() : "";
+ bit_numbering_inverted_ = j.count("bit_numbering_inverted") ? j["bit_numbering_inverted"].get<bool>() : false;
+ name_ = j.count("name") ? j["name"].get<std::string>() : "";
+ handlers_ = j.count("handlers") ? j["handlers"].get<std::vector<std::string>>() : std::vector<std::string>();
+ enabled_ = j.count("enabled") ? j["enabled"].get<bool>() : true;
+ max_frequency_ = (float)j.count("max_frequency") ? j["max_frequency"].get<float>() : 5;
+ max_signal_frequency_ = j.count("max_signal_frequency") ? j["max_signal_frequency"].get<float>() : 5;
+ force_send_changed_ = j.count("force_send_changed") ? j["force_send_changed"].get<bool>() : true;
+ force_send_changed_signals_ = j.count("force_send_changed_signals") ? j["force_send_changed_signals"].get<bool>() : false;
+
+ if(j.count("signals"))
+ {
+ std::map<std::string, nlohmann::json> signals = j["signals"];
+ for(const auto& s : signals)
+ {
+ signal sig = s.second.get<signal>();
+ sig.id(s.first);
+ signals_.push_back(sig);
+ }
+ }
+
+ }
+
+ std::uint32_t can_message::get_signals_count() const
+ {
+ return (uint32_t)signals_.size();
+ }
+
+ nlohmann::json can_message::to_json() const
+ {
+ nlohmann::json j;
+ j["bus"] = bus_;
+ j["bit_numbering_inverted"] = bit_numbering_inverted_;
+ j["signals"] = signals_;
+ j["name"] = name_;
+ j["handlers"] = handlers_;
+ j["enabled"] = enabled_;
+ j["max_frequency"] = max_frequency_;
+ j["max_signal_frequency"] = max_signal_frequency_;
+ j["force_send_changed"] = force_send_changed_;
+ j["force_send_changed_signals"] = force_send_changed_signals_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const can_message& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, can_message& p)
+ {
+ p.from_json(j);
+ }
+
+ void from_json(const nlohmann::json& j, can_message& p, const std::string& id)
+ {
+ p.from_json(j);
+ p.id(id);
+ }
+}
diff --git a/src/openxc/can_message.hpp b/src/openxc/can_message.hpp
new file mode 100755
index 0000000..3f7b018
--- /dev/null
+++ b/src/openxc/can_message.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <json.hpp>
+
+#include "signal.hpp"
+
+namespace openxc
+{
+ class can_message
+ {
+ private:
+ std::string id_;
+ std::string bus_;
+ bool bit_numbering_inverted_;
+ std::vector<signal> signals_;
+ std::string name_;
+ std::vector<std::string> handlers_;
+ bool enabled_;
+ float max_frequency_;
+ float max_signal_frequency_;
+ bool force_send_changed_;
+ bool force_send_changed_signals_;
+
+ public:
+ std::string id() const;
+ void id(const std::string& id);
+ std::string bus() const;
+ bool bit_numbering_inverted() const;
+ const std::vector<signal>& signals() const;
+ std::string name() const;
+ std::vector<std::string> handlers() const;
+ bool enabled() const;
+ float max_frequency() const;
+ float max_signal_frequency() const;
+ bool force_send_changed() const;
+ bool force_send_changed_signals() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+
+ std::uint32_t get_signals_count() const;
+ };
+
+ void to_json(nlohmann::json& j, const can_message& p);
+ void from_json(const nlohmann::json& j, can_message& p);
+ void from_json(const nlohmann::json& j, can_message& p, const std::string& id);
+}
diff --git a/src/openxc/command.cpp b/src/openxc/command.cpp
new file mode 100755
index 0000000..4cc0682
--- /dev/null
+++ b/src/openxc/command.cpp
@@ -0,0 +1,45 @@
+#include "command.hpp"
+
+namespace openxc
+{
+ std::string command::name() const
+ {
+ return name_;
+ }
+
+ bool command::enabled() const
+ {
+ return enabled_;
+ }
+
+ std::string command::handler() const
+ {
+ return handler_;
+ }
+
+ void command::from_json(const nlohmann::json& j)
+ {
+ name_ = j.count("name") ? j["name"].get<std::string>() : "";
+ enabled_ = j.count("enabled") ? j["enabled"].get<bool>() : true;
+ handler_ = j.count("handler") ? j["handler"].get<std::string>() : "";
+ }
+
+ nlohmann::json command::to_json() const
+ {
+ nlohmann::json j;
+ j["name"] = name_;
+ j["enabled"] = enabled_;
+ j["handler"] = handler_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const command& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, command& p)
+ {
+ p.from_json(j);
+ }
+}
diff --git a/src/openxc/command.hpp b/src/openxc/command.hpp
new file mode 100755
index 0000000..2c05226
--- /dev/null
+++ b/src/openxc/command.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <string>
+#include <json.hpp>
+
+namespace openxc
+{
+ class command
+ {
+ private:
+ std::string name_;
+ bool enabled_;
+ std::string handler_;
+ public:
+ std::string name() const;
+ bool enabled() const;
+ std::string handler() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const command& p);
+ void from_json(const nlohmann::json& j, command& p);
+}
diff --git a/src/openxc/diagnostic_message.cpp b/src/openxc/diagnostic_message.cpp
new file mode 100755
index 0000000..3881abe
--- /dev/null
+++ b/src/openxc/diagnostic_message.cpp
@@ -0,0 +1,80 @@
+#include "diagnostic_message.hpp"
+
+namespace openxc
+{
+ std::string diagnostic_message::bus() const
+ {
+ return bus_;
+ }
+
+ std::uint32_t diagnostic_message::id() const
+ {
+ return id_;
+ }
+
+ std::uint32_t diagnostic_message::mode() const
+ {
+ return mode_;
+ }
+
+ float diagnostic_message::frequency() const
+ {
+ return frequency_;
+ }
+
+ std::uint32_t diagnostic_message::pid() const
+ {
+ return pid_;
+ }
+
+ std::string diagnostic_message::name() const
+ {
+ return name_;
+ }
+
+ std::string diagnostic_message::decoder() const
+ {
+ return decoder_;
+ }
+
+ std::string diagnostic_message::callback() const
+ {
+ return callback_;
+ }
+
+ void diagnostic_message::from_json(const nlohmann::json& j)
+ {
+ bus_ = j.count("bus") ? j["bus"].get<std::string>() : "";
+ id_ = j.count("id") ? j["id"].get<std::uint32_t>() : 0;
+ mode_ = j.count("mode") ? j["mode"].get<std::uint32_t>() : 1;
+ frequency_ = j.count("frequency") ? j["frequency"].get<float>() : 0;
+ pid_ = j.count("pid") ? j["pid"].get<std::uint32_t>() : 0;
+ name_ = j.count("name") ? j["name"].get<std::string>() : "";
+ decoder_ = j.count("decoder") ? j["decoder"].get<std::string>() : "";
+ callback_ = j.count("callback") ? j["callback"].get<std::string>() : "";
+ }
+
+ nlohmann::json diagnostic_message::to_json() const
+ {
+ nlohmann::json j;
+ j["bus"] = bus_;
+ j["id"] = id_;
+ j["mode"] = mode_;
+ j["frequency"] = frequency_;
+ j["pid"] = pid_;
+ j["name"] = name_;
+ j["decoder"] = decoder_;
+ j["callback"] = callback_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const diagnostic_message& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, diagnostic_message& p)
+ {
+ p.from_json(j);
+ }
+}
diff --git a/src/openxc/diagnostic_message.hpp b/src/openxc/diagnostic_message.hpp
new file mode 100755
index 0000000..1ceba1b
--- /dev/null
+++ b/src/openxc/diagnostic_message.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <string>
+#include <json.hpp>
+
+namespace openxc
+{
+ class diagnostic_message
+ {
+ private:
+ std::string bus_;
+ std::uint32_t id_;
+ std::uint32_t mode_;
+ float frequency_;
+ std::uint32_t pid_;
+ std::string name_;
+ std::string decoder_;
+ std::string callback_;
+ public:
+ std::string bus() const;
+ std::uint32_t id() const;
+ std::uint32_t mode() const;
+ float frequency() const;
+ std::uint32_t pid() const;
+ std::string name() const;
+ std::string decoder() const;
+ std::string callback() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const diagnostic_message& p);
+ void from_json(const nlohmann::json& j, diagnostic_message& p);
+}
diff --git a/src/openxc/mapping.cpp b/src/openxc/mapping.cpp
new file mode 100755
index 0000000..74d5c94
--- /dev/null
+++ b/src/openxc/mapping.cpp
@@ -0,0 +1,59 @@
+#include "mapping.hpp"
+
+namespace openxc
+{
+ std::string mapping::mapping_name() const
+ {
+ return mapping_name_;
+ }
+
+ std::string mapping::bus() const
+ {
+ return bus_;
+ }
+
+ std::string mapping::database() const
+ {
+ return database_;
+ }
+
+ bool mapping::bit_numbering_inverted() const
+ {
+ return bit_numbering_inverted_;
+ }
+
+ bool mapping::enabled() const
+ {
+ return enabled_;
+ }
+
+ void mapping::from_json(const nlohmann::json& j)
+ {
+ mapping_name_ = j.count("mapping") ? j["mapping"].get<std::string>() : "";
+ bus_ = j.count("bus") ? j["bus"].get<std::string>() : "";
+ database_ = j.count("database") ? j["database"].get<std::string>() : "";
+ bit_numbering_inverted_ = j.count("bit_numbering_inverted") ? j["bit_numbering_inverted"].get<bool>() : false;
+ enabled_ = j.count("enabled") ? j["enabled"].get<bool>() : true;
+ }
+
+ nlohmann::json mapping::to_json() const
+ {
+ nlohmann::json j;
+ j["mapping"] = mapping_name_;
+ j["bus"] = bus_;
+ j["database"] = database_;
+ j["bit_numbering_inverted"] = bit_numbering_inverted_;
+ j["enabled"] = enabled_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const mapping& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, mapping& p)
+ {
+ p.from_json(j);
+ }
+}
diff --git a/src/openxc/mapping.hpp b/src/openxc/mapping.hpp
new file mode 100755
index 0000000..30895cb
--- /dev/null
+++ b/src/openxc/mapping.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <string>
+#include <json.hpp>
+
+namespace openxc
+{
+ class mapping
+ {
+ private:
+ std::string mapping_name_;
+ std::string bus_;
+ std::string database_;
+ bool bit_numbering_inverted_;
+ bool enabled_;
+ public:
+ std::string mapping_name() const;
+ std::string bus() const;
+ std::string database() const;
+ bool bit_numbering_inverted() const;
+ bool enabled() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const mapping& p);
+ void from_json(const nlohmann::json& j, mapping& p);
+}
diff --git a/src/openxc/message_set.cpp b/src/openxc/message_set.cpp
new file mode 100755
index 0000000..d6745bf
--- /dev/null
+++ b/src/openxc/message_set.cpp
@@ -0,0 +1,145 @@
+#include <sstream>
+#include "message_set.hpp"
+
+namespace openxc
+{
+ message_set::message_set()
+ : name_{""}
+ , bit_numbering_inverted_{false}
+ , max_message_frequency_{0}
+ , raw_can_mode_{can_bus_mode::off}
+ , parents_{}
+ , initializers_{}
+ , loopers_{}
+ , buses_{}
+ , messages_{}
+ , diagnostic_messages_{}
+ , mappings_{}
+ , extra_sources_{}
+ , commands_{}
+ {
+ }
+
+ std::string message_set::name() const
+ {
+ return name_;
+ }
+
+ bool message_set::bit_numbering_inverted() const
+ {
+ return bit_numbering_inverted_;
+ }
+
+ float message_set::max_message_frequency() const
+ {
+ return max_message_frequency_;
+ }
+
+ can_bus_mode message_set::raw_can_mode() const
+ {
+ return raw_can_mode_;
+ }
+
+ const std::vector<std::string>& message_set::parents() const
+ {
+ return parents_;
+ }
+
+ const std::vector<std::string>& message_set::initializers() const
+ {
+ return initializers_;
+ }
+
+ const std::vector<std::string>& message_set::loopers() const
+ {
+ return loopers_;
+ }
+
+ const std::map<std::string, can_bus>& message_set::buses() const
+ {
+ return buses_;
+ }
+
+ const std::vector<can_message>& message_set::messages() const
+ {
+ return messages_;
+ }
+
+ const std::vector<diagnostic_message>& message_set::diagnostic_messages() const
+ {
+ return diagnostic_messages_;
+ }
+
+ const std::vector<mapping>& message_set::mappings() const
+ {
+ return mappings_;
+ }
+
+ const std::vector<std::string>& message_set::extra_sources() const
+ {
+ return extra_sources_;
+ }
+
+ const std::vector<command>& message_set::commands() const
+ {
+ return commands_;
+ }
+
+ void message_set::from_json(const nlohmann::json& j)
+ {
+ name_ = j["name"].get<std::string>();
+ bit_numbering_inverted_ = j.count("bit_numbering_inverted") ? j["bit_numbering_inverted"].get<bool>() : false; // TODO: should be true by default if database-backed.
+ max_message_frequency_ = j.count("max_message_frequency") ? j["max_message_frequency"].get<float>() : 0.0f;
+ raw_can_mode_ = j.count("raw_can_mode") ? j["raw_can_mode"].get<can_bus_mode>() : can_bus_mode::off;
+ parents_ = j.count("parents") ? j["parents"].get<std::vector<std::string>>() : std::vector<std::string>();
+ initializers_ = j.count("initializers") ? j["initializers"].get<std::vector<std::string>>() : std::vector<std::string>();
+ loopers_ = j.count("loopers") ? j["loopers"].get<std::vector<std::string>>() : std::vector<std::string>();
+ buses_ = j.count("buses") ? j["buses"].get<std::map<std::string, can_bus>>() : std::map<std::string, can_bus>();
+ //messages_ = j.count("messages") ? j["messages"].get<std::map<std::string, can_message>>() : std::map<std::string, can_message>();
+ diagnostic_messages_ = j.count("diagnostic_messages") ? j["diagnostic_messages"].get<std::vector<diagnostic_message>>() : std::vector<diagnostic_message>();
+ mappings_ = j.count("mappings") ? j["mappings"].get<std::vector<mapping>>() : std::vector<mapping>();
+ extra_sources_ = j.count("extra_sources") ? j["extra_sources"].get<std::vector<std::string>>() : std::vector<std::string>();
+ commands_ = j.count("commands") ? j["commands"].get<std::vector<command>>() : std::vector<command>();
+
+
+ if (j.count("messages"))
+ {
+ std::map<std::string, nlohmann::json> messages = j["messages"];
+ for(const std::map<std::string, nlohmann::json>::value_type& m : messages)
+ {
+ can_message cm = m.second.get<can_message>();
+ cm.id(m.first);
+ messages_.push_back(cm);
+ }
+ }
+ }
+
+ nlohmann::json message_set::to_json() const
+ {
+ nlohmann::json j;
+ j["name_"] = name_;
+ j["bit_numbering_inverted"] = bit_numbering_inverted_;
+ j["max_message_frequency"] = max_message_frequency_;
+ j["raw_can_mode"] = raw_can_mode_;
+ j["parents"] = parents_;
+ j["initializers"] = initializers_;
+ j["loopers"] = loopers_;
+ j["buses"] = buses_;
+ j["messages"] = messages_;
+ j["diagnostic_messages"] = diagnostic_messages_;
+ j["mappings"] = mappings_;
+ j["extra_sources"] = extra_sources_;
+ j["commands"] = commands_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const message_set& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, message_set& p)
+ {
+ p.from_json(j);
+ }
+}
diff --git a/src/openxc/message_set.hpp b/src/openxc/message_set.hpp
new file mode 100755
index 0000000..935817e
--- /dev/null
+++ b/src/openxc/message_set.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <map>
+#include <json.hpp>
+
+#include "can_bus.hpp"
+#include "can_message.hpp"
+#include "diagnostic_message.hpp"
+#include "mapping.hpp"
+#include "command.hpp"
+
+namespace openxc
+{
+ class message_set
+ {
+ private:
+ std::string name_;
+ bool bit_numbering_inverted_;
+ float max_message_frequency_;
+ can_bus_mode raw_can_mode_;
+ std::vector<std::string> parents_;
+ std::vector<std::string> initializers_;
+ std::vector<std::string> loopers_;
+ std::map<std::string, can_bus> buses_;
+ //std::map<std::string, can_message> messages_;
+ std::vector<can_message> messages_;
+ std::vector<diagnostic_message> diagnostic_messages_;
+ std::vector<mapping> mappings_;
+ std::vector<std::string> extra_sources_;
+ std::vector<command> commands_;
+
+ public:
+ message_set();
+ message_set(const message_set&) = default;
+ message_set(message_set&&) = default;
+
+ std::string name() const;
+ bool bit_numbering_inverted() const;
+ float max_message_frequency() const;
+ can_bus_mode raw_can_mode() const;
+ const std::vector<std::string>& parents() const;
+ const std::vector<std::string>& initializers() const;
+ const std::vector<std::string>& loopers() const;
+ const std::map<std::string, can_bus>& buses() const;
+ const std::vector<can_message>& messages() const;
+ const std::vector<diagnostic_message>& diagnostic_messages() const;
+ const std::vector<mapping>& mappings() const;
+ const std::vector<std::string>& extra_sources() const;
+ const std::vector<command>& commands() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const message_set& p);
+ void from_json(const nlohmann::json& j, message_set& p);
+}
diff --git a/src/openxc/signal.cpp b/src/openxc/signal.cpp
new file mode 100755
index 0000000..e9c1088
--- /dev/null
+++ b/src/openxc/signal.cpp
@@ -0,0 +1,142 @@
+#include "signal.hpp"
+
+namespace openxc
+{
+ std::string signal::id() const
+ {
+ return id_;
+ }
+
+ void signal::id(const std::string& id)
+ {
+ id_ = id;
+ }
+
+ void id(const std::string& id);
+
+ std::string signal::generic_name() const
+ {
+ return generic_name_;
+ }
+
+ std::uint32_t signal::bit_position() const
+ {
+ return bit_position_;
+ }
+
+ std::uint32_t signal::bit_size() const
+ {
+ return bit_size_;
+ }
+
+ float signal::factor() const
+ {
+ return factor_;
+ }
+
+ float signal::offset() const
+ {
+ return offset_;
+ }
+
+ std::string signal::decoder() const
+ {
+ return decoder_;
+ }
+
+ bool signal::ignore() const
+ {
+ return ignore_;
+ }
+
+ bool signal::enabled() const
+ {
+ return enabled_;
+ }
+
+ const std::map<std::string, std::vector<std::uint32_t>>& signal::states() const
+ {
+ return states_;
+ }
+
+ float signal::max_frequency() const
+ {
+ return max_frequency_;
+ }
+
+ bool signal::send_same() const
+ {
+ return send_same_;
+ }
+
+ bool signal::force_send_changed() const
+ {
+ return force_send_changed_;
+ }
+
+ bool signal::writable() const
+ {
+ return writable_;
+ }
+
+ std::string signal::encoder() const
+ {
+ return encoder_;
+ }
+
+ void signal::from_json(const nlohmann::json& j)
+ {
+ generic_name_ = j.count("generic_name") ? j["generic_name"].get<std::string>() : "";
+ bit_position_ = j.count("bit_position") ? j["bit_position"].get<std::uint32_t>() : 0;
+ bit_size_ = j.count("bit_size") ? j["bit_size"].get<std::uint32_t>() : 0;
+ factor_ = j.count("factor") ? j["factor"].get<float>() : 1.0f;
+ offset_ = j.count("offset") ? j["offset"].get<float>() : 0.0f;
+ decoder_ = j.count("decoder") ? j["decoder"].get<std::string>() : "";
+ ignore_ = j.count("ignore") ? j["ignore"].get<bool>() : false;
+ enabled_ = j.count("enabled") ? j["enabled"].get<bool>() : true;
+ max_frequency_ = j.count("max_frequency") ? j["max_frequency"].get<float>() : 0.0f;
+ send_same_ = j.count("send_same") ? j["send_same"].get<bool>() : true;
+ force_send_changed_ = j.count("force_send_changed") ? j["force_send_changed"].get<bool>() : false;
+ writable_ = j.count("writable") ? j["writable"].get<bool>() : false;
+ encoder_ = j.count("encoder") ? j["encoder"].get<std::string>() : "";
+
+ if (j.count("states"))
+ {
+ std::map<std::string, nlohmann::json> items = j["states"];
+ for(const auto& i : items)
+ {
+ states_[i.first] = i.second.get<std::vector<std::uint32_t>>();
+ }
+ }
+ }
+
+ nlohmann::json signal::to_json() const
+ {
+ nlohmann::json j;
+ j["generic_name"] = generic_name_;
+ j["bit_position"] = bit_position_;
+ j["bit_size"] = bit_size_;
+ j["factor"] = factor_;
+ j["offset"] = offset_;
+ j["decoder"] = decoder_;
+ j["ignore"] = ignore_;
+ j["enabled"] = enabled_;
+ j["states"] = states_;
+ j["max_frequency"] = max_frequency_;
+ j["send_same"] = send_same_;
+ j["force_send_changed"] = force_send_changed_;
+ j["writable"] = writable_;
+ j["encoder"] = encoder_;
+ return j;
+ }
+
+ void to_json(nlohmann::json& j, const signal& p)
+ {
+ j = p.to_json();
+ }
+
+ void from_json(const nlohmann::json& j, signal& p)
+ {
+ p.from_json(j);
+ }
+}
diff --git a/src/openxc/signal.hpp b/src/openxc/signal.hpp
new file mode 100755
index 0000000..e0124c3
--- /dev/null
+++ b/src/openxc/signal.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+#include <cstdint>
+#include <json.hpp>
+
+namespace openxc
+{
+ class signal
+ {
+ private:
+ std::string id_;
+ std::string generic_name_;
+ std::uint32_t bit_position_;
+ std::uint32_t bit_size_;
+ float factor_;
+ float offset_;
+ std::string decoder_;
+ bool ignore_;
+ bool enabled_;
+ std::map<std::string, std::vector<std::uint32_t>> states_;
+ float max_frequency_;
+ bool send_same_;
+ bool force_send_changed_;
+ bool writable_;
+ std::string encoder_;
+ public:
+ std::string id() const;
+ void id(const std::string& id);
+ std::string generic_name() const;
+ std::uint32_t bit_position() const;
+ std::uint32_t bit_size() const;
+ float factor() const;
+ float offset() const;
+ std::string decoder() const;
+ bool ignore() const;
+ bool enabled() const;
+ const std::map<std::string, std::vector<std::uint32_t>>& states() const;
+ float max_frequency() const;
+ bool send_same() const;
+ bool force_send_changed() const;
+ bool writable() const;
+ std::string encoder() const;
+
+ void from_json(const nlohmann::json& j);
+ nlohmann::json to_json() const;
+ };
+
+ void to_json(nlohmann::json& j, const signal& p);
+ void from_json(const nlohmann::json& j, signal& p);
+}