summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/can-signals.cpp70
-rw-r--r--src/can-signals.hpp68
-rw-r--r--src/can-utils.cpp28
-rw-r--r--src/can-utils.hpp174
-rw-r--r--src/can_decode_message.cpp105
-rw-r--r--src/can_event_push.cpp39
-rw-r--r--src/low-can-binding.cpp121
-rw-r--r--src/low-can-binding.hpp63
-rw-r--r--src/obd2.cpp2
-rw-r--r--src/obd2.hpp54
-rw-r--r--src/openxc-utils.cpp127
-rw-r--r--src/openxc-utils.hpp53
13 files changed, 533 insertions, 373 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 84e8ecf0..4f95cce5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,7 +65,7 @@ link_libraries(${EXTRAS_LIBRARIES})
message(STATUS "Creation of ${PROJECT_NAME} binding for AFB-DAEMON")
###########################################################################
-add_library(${PROJECT_NAME}-binding MODULE ${PROJECT_NAME}-binding.cpp can-signals.cpp)
+add_library(${PROJECT_NAME}-binding MODULE ${PROJECT_NAME}-binding.cpp can-signals.cpp can-utils.cpp obd2.cpp)
set_target_properties(${PROJECT_NAME}-binding PROPERTIES
PREFIX ""
diff --git a/src/can-signals.cpp b/src/can-signals.cpp
index b2996933..c6a8ae9e 100644
--- a/src/can-signals.cpp
+++ b/src/can-signals.cpp
@@ -15,57 +15,65 @@
* limitations under the License.
*/
-#include <string>
-#include <vector>
-#include <fnmatch.h>
-#include "can-signals.h"
+#include "can-signals.hpp"
-/* Can signal event map making access to afb_event
- * external to openxc existing structure.
- */
-std::map <CanSignal, struct afb_event> subscribed_signals;
-std::map <CanSignal, struct afb_event>::iterator subscribed_signals_i;
+const std::vector<CanSignal> getSignals()
+{
+ return SIGNALS[MESSAGE_SET_ID];
+}
-#define MESSAGE_SET_ID 0
-std::vector <CanSignal> find_can_signals(openxc_DynamicField &key)
+size_t getSignalCount()
{
- std::vector <CanSignal> signals;
- int n_signals, i;
+ return SIGNALS[MESSAGE_SET_ID].size();
+}
- n_signals = getSignalCount();
+std::vector<CanSignal> find_can_signals(openxc_DynamicField& key)
+{
+ std::vector<CanSignal> signals;
- switch(key->type):
+ switch(key.type)
{
case openxc_DynamicField_Type::openxc_DynamicField_Type_STRING:
- for(const CanSignal& s : SIGNALS[MESSAGE_SET_ID])
+ for(const CanSignal& s : getSignals())
{
- if(fnmatch(key->string_value, s.genericName) == 0)
+ if(fnmatch(key.string_value, s.genericName, FNM_CASEFOLD) == 0)
signals.push_back(s);
}
break;
case openxc_DynamicField_Type::openxc_DynamicField_Type_NUM:
- for(const CanSignal& s : SIGNALS[MESSAGE_SET_ID])
+ for(const CanSignal& s : getSignals())
{
CanMessageDefinition *msg_def = s.message;
- if(msg_def->id == key->numeric_value)
- signals.push_back(s)
+ if(msg_def->id == key.numeric_value)
+ signals.push_back(s);
}
break;
default:
ERROR(interface, "find_can_signals: wrong openxc_DynamicField specified. Use openxc_DynamicField_Type_NUM or openxc_DynamicField_Type_STRING type only.");
- return NULL;
+ CanSignal cs;
+ ::memset(&cs, 0, sizeof(CanSignal));
+ signals.push_back(cs);
+ return signals;
break;
}
-
return signals;
}
-std::vector<CanSignal>& getSignals()
-{
- return SIGNALS[MESSAGE_SET_ID];
-}
-
-int getSignalCount()
-{
- return SIGNALS[MESSAGE_SET_ID].size();
-} \ No newline at end of file
+ struct CanMessageDefinition* message;
+ const char* genericName;
+ uint8_t bitPosition;
+ uint8_t bitSize;
+ float factor;
+ float offset;
+ float minValue;
+ float maxValue;
+ FrequencyClock frequencyClock;
+ bool sendSame;
+ bool forceSendChanged;
+ const CanSignalState* states;
+ uint8_t stateCount;
+ bool writable;
+ SignalDecoder decoder;
+ SignalEncoder encoder;
+ bool received;
+ float lastValue; \ No newline at end of file
diff --git a/src/can-signals.hpp b/src/can-signals.hpp
index 27205137..b115263c 100644
--- a/src/can-signals.hpp
+++ b/src/can-signals.hpp
@@ -17,30 +17,53 @@
#pragma once
-#include "can-utils.hpp"
+#include <queue>
#include <string>
+#include <vector>
+#include <fnmatch.h>
+#include <linux/can.h>
+
+#include "can-utils.hpp"
+#include "low-can-binding.hpp"
+
+#define MESSAGE_SET_ID 0
+
+/** Can signal event map making access to afb_event
+ * external to openxc existing structure.
+ */
+static std::map<std::string, struct afb_event> subscribed_signals;
+static std::map<std::string, struct afb_event>::iterator subscribed_signals_i;
+
+/**
+ * @brief Dumb SIGNALS array. It is composed by CanMessageSet
+ * SIGNALS[MESSAGE_SET_ID][CanSignal]
+ */
+std::vector<std::vector<CanSignal>> SIGNALS {
+ { // message set: example
+ }
+};
/** Public: Return the currently active CAN configuration. */
CanMessageSet* getActiveMessageSet();
/** Public: Retrive a list of all possible CAN configurations.
- * *
- * * Returns a pointer to an array of all configurations.
- * */
+ *
+ * Returns a pointer to an array of all configurations.
+ */
CanMessageSet* getMessageSets();
/** Public: Return the length of the array returned by getMessageSets() */
int getMessageSetCount();
/* Public: Return the number of CAN buses configured in the active
- * * configuration. This is limited to 2, as the hardware controller only has 2
- * * CAN channels.
- * */
+ * configuration. This is limited to 2, as the hardware controller only has 2
+ * CAN channels.
+ */
int getCanBusCount();
/* Public: Return an array of all CAN messages to be processed in the active
- * * configuration.
- * */
+ * configuration.
+ */
CanMessageDefinition* getMessages();
/* Public: Return signals from an signals array filtered on name.
@@ -48,10 +71,10 @@ CanMessageDefinition* getMessages();
CanSignal* getSignals(std::string name);
/* Public: Return an array of all OpenXC CAN commands enabled in the active
- * * configuration that can write back to CAN with a custom handler.
- * *
- * * Commands not defined here are handled using a 1-1 mapping from the signals
- * * list.
+ * configuration that can write back to CAN with a custom handler.
+ *
+ * * Commands not defined here are handled using a 1-1 mapping from the signals
+ * list.
* */
CanCommand* getCommands();
@@ -59,17 +82,17 @@ CanCommand* getCommands();
int getCommandCount();
/* Public: Return the length of the array returned by getSignals(). */
-int getSignalCount();
+size_t getSignalCount();
/* Public: Return the length of the array returned by getMessages(). */
int getMessageCount();
-/* Public: Return an array of the metadata for the 2 CAN buses you want to
- * * monitor. The size of this array is fixed at 2.
- * */
+/**
+ * @brief Return an array of the metadata for the 2 CAN buses you want to
+ * monitor. The size of this array is fixed at 2.
+ */
CanBus* getCanBuses();
-
/**
* @brief Find one or many signals based on its name or id
* passed through openxc_DynamicField.
@@ -77,6 +100,11 @@ CanBus* getCanBuses();
* params[openxc_DynamicField&] - a const reference with the key to search into signal.
* Key is either a signal name or its CAN arbitration id.
*
- * return[std::vector<CanSignal>] return found CanSignal array.
+ * return[std::vector<std::string>] return found CanSignal generic name vector.
*/
-std::vector <CanSignal> find_can_signals(const openxc_DynamicField &key) \ No newline at end of file
+std::vector<CanSignal> find_can_signals(const openxc_DynamicField &key);
+
+uint32_t get_CanSignal_id(const CanSignal& sig)
+{
+ return sig.message->id;
+} \ No newline at end of file
diff --git a/src/can-utils.cpp b/src/can-utils.cpp
index 8d5f0252..72f00aa9 100644
--- a/src/can-utils.cpp
+++ b/src/can-utils.cpp
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-#pragma once
+#include "can-utils.hpp"
/********************************************************************************
*
@@ -23,8 +23,7 @@
*
*********************************************************************************/
-
-can_bus_dev_t::can_bus_dev_t(afb_binding_interface *itf, const std:string &dev_name)
+can_bus_dev_t::can_bus_dev_t(const std::string &dev_name)
: device_name_{dev_name}
{
}
@@ -59,7 +58,7 @@ int can_bus_dev_t::open()
/* Attempts to open a socket to CAN bus */
::strcpy(ifr.ifr_name, device);
- if(ioctl(can_socket_, SIOCGIFINDEX, &ifr) < 0)
+ if(::ioctl(can_socket_, SIOCGIFINDEX, &ifr) < 0)
ERROR(interface_, "open_can_dev: ioctl failed");
else
{
@@ -119,6 +118,7 @@ canfd_frame can_bus_dev_t::read()
ERROR(interface_, "read_can: %s interface down", device);
ERROR(interface_, "read_can: Error reading CAN bus");
::memset(&canfd_frame, 0, sizeof(canfd_frame));
+ is_running_ = false;
break;
}
@@ -189,8 +189,8 @@ bool can_bus_dev_t::has_can_message() const
*
*********************************************************************************/
-can_bus_t::can_bus_t(afb_binding_interface *itf, std::ifstream& conf_file)
- : interface{itf}, conf_file_{conf_file}
+can_bus_t::can_bus_t(const afb_binding_interface *itf, int& conf_file)
+ : interface_{itf}, conf_file_{conf_file}
{
}
@@ -205,7 +205,6 @@ void can_bus_t::start_threads()
th_pushing_ = std::thread(can_event_push, this);
}
-
/**
* @brief Initialize as many as can_bus_dev_t objects with their respective reading thread
*
@@ -245,18 +244,17 @@ int init_can_dev()
std::vector<std::string> read_conf()
{
std::vector<std::string> ret;
- std::string fd_conf_content;
json_object jo, canbus;
int n, i, ok;
- /* Open JSON conf file */
if (conf_file_)
{
- conf_file_.seekg(0, std::ios::end);
- conf_file_.resize(conf_file_.tellg());
- conf_file_.seekg(0, std::ios::beg);
- conf_file_.read(&fd_conf_content[0], fd_conf_content.size());
- conf_file_.close();
+ std::string fd_conf_content;
+ std::fseek(conf_file_, 0, SEEK_END);
+ fd_conf_content.resize(std::ftell(conf_file_));
+ std::rewind(fp);
+ std::fread(&fd_conf_content[0], 1, fd_conf_content.size(), conf_file_);
+ std::fclose(conf_file_);
jo = json_tokener_parse(&fd_conf_content);
@@ -441,7 +439,7 @@ void can_message_t::convert_from_canfd_frame(canfd_frame &frame)
ERROR(interface_, "can_message_t: canfd_frame data too long to be stored into CanMessage object");
}
-canfd_frame convert_to_canfd_frame()
+canfd_frame can_message_t::convert_to_canfd_frame()
{
canfd_frame frame;
diff --git a/src/can-utils.hpp b/src/can-utils.hpp
index db97b4bf..0b0971dc 100644
--- a/src/can-utils.hpp
+++ b/src/can-utils.hpp
@@ -17,9 +17,18 @@
#pragma once
+#include <map>
+#include <queue>
+#include <vector>
+#include <cstdio>
#include <string>
+#include <thread>
+#include <linux/can.h>
+
#include "timer.hpp"
#include "openxc.pb.h"
+#include <afb/afb-binding.h>
+#include <afb/afb-service-itf.h>
// TODO actual max is 32 but dropped to 24 for memory considerations
#define MAX_ACCEPTANCE_FILTERS 24
@@ -30,20 +39,21 @@
#define CAN_ACTIVE_TIMEOUT_S 30
-/* Public: The type signature for a CAN signal decoder.
+/**
+ * @brief The type signature for a CAN signal decoder.
*
- * A SignalDecoder transforms a raw floating point CAN signal into a number,
+ * @desc A SignalDecoder transforms a raw floating point CAN signal into a number,
* string or boolean.
*
- * signal - The CAN signal that we are decoding.
- * signals - The list of all signals.
- * signalCount - The length of the signals array.
- * value - The CAN signal parsed from the message as a raw floating point
- * value.
- * send - An output parameter. If the decoding failed or the CAN signal should
- * not send for some other reason, this should be flipped to false.
+ * @param[in] CanSignal signal - The CAN signal that we are decoding.
+ * @param[in] CanSignal signals - The list of all signals.
+ * @param[in] int signalCount - The length of the signals array.
+ * @param[in] float value - The CAN signal parsed from the message as a raw floating point
+ * value.
+ * @param[out] bool send - An output parameter. If the decoding failed or the CAN signal should
+ * not send for some other reason, this should be flipped to false.
*
- * Returns a decoded value in an openxc_DynamicField struct.
+ * @return a decoded value in an openxc_DynamicField struct.
*/
typedef openxc_DynamicField (*SignalDecoder)(struct CanSignal* signal,
CanSignal* signals, int signalCount, float value, bool* send);
@@ -51,7 +61,7 @@ typedef openxc_DynamicField (*SignalDecoder)(struct CanSignal* signal,
/**
* @brief: The type signature for a CAN signal encoder.
*
- * A SignalEncoder transforms a number, string or boolean into a raw floating
+ * @desc A SignalEncoder transforms a number, string or boolean into a raw floating
* point value that fits in the CAN signal.
*
* @params[signal] - The CAN signal to encode.
@@ -62,7 +72,8 @@ typedef openxc_DynamicField (*SignalDecoder)(struct CanSignal* signal,
typedef uint64_t (*SignalEncoder)(struct CanSignal* signal,
openxc_DynamicField* value, bool* send);
-/* Public: The ID format for a CAN message.
+/**
+ * @brief The ID format for a CAN message.
*
* STANDARD - standard 11-bit CAN arbitration ID.
* EXTENDED - an extended frame, with a 29-bit arbitration ID.
@@ -73,13 +84,17 @@ enum CanMessageFormat {
};
typedef enum CanMessageFormat CanMessageFormat;
-/* A compact representation of a single CAN message, meant to be used in in/out
+/**
+ * @brief A compact representation of a single CAN message, meant to be used in in/out
* buffers.
*
- * id - The ID of the message.
- * format - the format of the message's ID.
- * data - The message's data field.
- * length - the length of the data array (max 8).
+ * param[in] uint32_t id - The ID of the message.
+ * param[in] CanMessageFormat format - the format of the message's ID.
+ * param[in] uint8_t data - The message's data field.
+ * @param[in] uint8_t length - the length of the data array (max 8).
+*************************
+* old CanMessage struct *
+*************************
struct CanMessage {
uint32_t id;
CanMessageFormat format;
@@ -90,7 +105,7 @@ typedef struct CanMessage CanMessage;
*/
class can_message_t {
private:
- afb_binding_interface interface_;
+ const struct afb_binding_interface *interface_;
uint32_t id_;
CanMessageFormat format_;
uint8_t data_[CAN_MESSAGE_SIZE];
@@ -115,9 +130,7 @@ class can_message_t {
* @brief Object representing a can device. Handle opening, closing and reading on the
* socket. This is the low level object to be use by can_bus_t.
*
- * @params[*interface_] - afb_binding_interface to the binder. Used to log messages
- * @params[device_name_] - name of the linux device handling the can bus. Generally vcan0, can0, etc.
- *
+ * @params[in] std::string device_name_ - name of the linux device handling the can bus. Generally vcan0, can0, etc.
*/
class can_bus_dev_t {
private:
@@ -133,6 +146,8 @@ class can_bus_dev_t {
bool is_running_;
public:
+ can_bus_dev_t(const std::string& dev_name);
+
int open();
int close();
bool is_running();
@@ -145,13 +160,13 @@ class can_bus_dev_t {
/**
* @brief Object used to handle decoding and manage event queue to be pushed.
*
- * @params[*interface_] - afb_binding_interface to the binder. Used to log messages
- * @params[conf_file_ifstream_] - stream of configuration file used to initialize
- * can_bus_dev_t objects.
+ * @params[in] interface_ - afb_binding_interface pointer to the binder. Used to log messages
+ * @params[in] conf_file_ - configuration file handle used to initialize can_bus_dev_t objects.
*/
class can_bus_t {
private:
- afb_binding_interface *interface_;
+ const struct afb_binding_interface *interface_;
+ int conf_file_;
std::thread th_decoding_;
std::thread th_pushing_;
@@ -160,6 +175,7 @@ class can_bus_t {
std::queue <openxc_VehicleMessage> vehicle_message_q_;
public:
+ can_bus_t(const struct afb_binding_interface *itf, int& conf_file);
int init_can_dev();
std::vector<std::string> read_conf();
@@ -172,11 +188,12 @@ class can_bus_t {
bool has_vehicle_message() const;
};
-/* Public: A state encoded (SED) signal's mapping from numerical values to
+/**
+ * @brief A state encoded (SED) signal's mapping from numerical values to
* OpenXC state names.
*
- * value - The integer value of the state on the CAN bus.
- * name - The corresponding string name for the state in OpenXC.
+ * @param[in] in value - The integer value of the state on the CAN bus.
+ * @param[in] char* name - The corresponding string name for the state in OpenXC.
*/
struct CanSignalState {
const int value;
@@ -184,38 +201,39 @@ struct CanSignalState {
};
typedef struct CanSignalState CanSignalState;
-/* Public: A CAN signal to decode from the bus and output over USB.
+/**
+ * @brief A CAN signal to decode from the bus and output over USB.
*
- * message - The message this signal is a part of.
- * genericName - The name of the signal to be output over USB.
- * bitPosition - The starting bit of the signal in its CAN message (assuming
+ * @param[in] message - The message this signal is a part of.
+ * @param[in] genericName - The name of the signal to be output over USB.
+ * @param[in] bitPosition - The starting bit of the signal in its CAN message (assuming
* non-inverted bit numbering, i.e. the most significant bit of
* each byte is 0)
- * bitSize - The width of the bit field in the CAN message.
- * factor - The final value will be multiplied by this factor. Use 1 if you
+ * @param[in] bitSize - The width of the bit field in the CAN message.
+ * @param[in] factor - The final value will be multiplied by this factor. Use 1 if you
* don't need a factor.
- * offset - The final value will be added to this offset. Use 0 if you
+ * @param[in] offset - The final value will be added to this offset. Use 0 if you
* don't need an offset.
- * minValue - The minimum value for the processed signal.
- * maxValue - The maximum value for the processed signal.
- * frequencyClock - A FrequencyClock struct to control the maximum frequency to
+ * @param[in] minValue - The minimum value for the processed signal.
+ * @param[in] maxValue - The maximum value for the processed signal.
+ * @param[in] frequencyClock - A FrequencyClock struct to control the maximum frequency to
* process and send this signal. To process every value, set the
* clock's frequency to 0.
- * sendSame - If true, will re-send even if the value hasn't changed.
- * forceSendChanged - If true, regardless of the frequency, it will send the
+ * @param[in] sendSame - If true, will re-send even if the value hasn't changed.
+ * @param[in] forceSendChanged - If true, regardless of the frequency, it will send the
* value if it has changed.
- * states - An array of CanSignalState describing the mapping
+ * @param[in] states - An array of CanSignalState describing the mapping
* between numerical and string values for valid states.
- * stateCount - The length of the states array.
- * writable - True if the signal is allowed to be written from the USB host
+ * @param[in] stateCount - The length of the states array.
+ * @param[in] writable - True if the signal is allowed to be written from the USB host
* back to CAN. Defaults to false.
- * decoder - An optional function to decode a signal from the bus to a human
- * readable value. If NULL, the default numerical decoder is used.
- * encoder - An optional function to encode a signal value to be written to
+ * @param[in] decoder - An optional function to decode a signal from the bus to a human
+ * readable value. If NULL, the default numerical decoder is used.
+ * @param[in] encoder - An optional function to encode a signal value to be written to
* CAN into a byte array. If NULL, the default numerical encoder
* is used.
- * received - True if this signal has ever been received.
- * lastValue - The last received value of the signal. If 'received' is false,
+ * @param[in] received - True if this signal has ever been received.
+ * @param[in] lastValue - The last received value of the signal. If 'received' is false,
* this value is undefined.
*/
struct CanSignal {
@@ -240,19 +258,20 @@ struct CanSignal {
};
typedef struct CanSignal CanSignal;
-/* Public: The definition of a CAN message. This includes a lot of metadata, so
+/**
+ * @brief The definition of a CAN message. This includes a lot of metadata, so
* to save memory this struct should not be used for storing incoming and
* outgoing CAN messages.
*
- * bus - A pointer to the bus this message is on.
- * id - The ID of the message.
- * format - the format of the message's ID.
- * clock - an optional frequency clock to control the output of this
+ * @param[in] bus - A pointer to the bus this message is on.
+ * @param[in] id - The ID of the message.
+ * @param[in] format - the format of the message's ID.
+ * @param[in] clock - an optional frequency clock to control the output of this
* message, if sent raw, or simply to mark the max frequency for custom
* handlers to retrieve.
- * forceSendChanged - If true, regardless of the frequency, it will send CAN
+ * @param[in] forceSendChanged - If true, regardless of the frequency, it will send CAN
* message if it has changed when using raw passthrough.
- * lastValue - The last received value of the message. Defaults to undefined.
+ * @param[in] lastValue - The last received value of the message. Defaults to undefined.
* This is required for the forceSendChanged functionality, as the stack
* needs to compare an incoming CAN message with the previous frame.
*/
@@ -292,18 +311,19 @@ struct CanMessageDefinitionListEntry {
LIST_HEAD(CanMessageDefinitionList, CanMessageDefinitionListEntry);
*/
-/** Public: A parent wrapper for a particular set of CAN messages and associated
+/**
+ * @brief A parent wrapper for a particular set of CAN messages and associated
* CAN buses(e.g. a vehicle or program).
*
- * index - A numerical ID for the message set, ideally the index in an array
+ * @param[in] index - A numerical ID for the message set, ideally the index in an array
* for fast lookup
- * name - The name of the message set.
- * busCount - The number of CAN buses defined for this message set.
- * messageCount - The number of CAN messages (across all buses) defined for
+ * @param[in] name - The name of the message set.
+ * @param[in] busCount - The number of CAN buses defined for this message set.
+ * @param[in] messageCount - The number of CAN messages (across all buses) defined for
* this message set.
- * signalCount - The number of CAN signals (across all messages) defined for
+ * @param[in] signalCount - The number of CAN signals (across all messages) defined for
* this message set.
- * commandCount - The number of CanCommmands defined for this message set.
+ * @param[in] commandCount - The number of CanCommmands defined for this message set.
*/
typedef struct {
uint8_t index;
@@ -314,15 +334,16 @@ LIST_HEAD(CanMessageDefinitionList, CanMessageDefinitionListEntry);
unsigned short commandCount;
} CanMessageSet;
-/* Public: The type signature for a function to handle a custom OpenXC command.
+/**
+ * @brief The type signature for a function to handle a custom OpenXC command.
*
- * name - the name of the received command.
- * value - the value of the received command, in a DynamicField. The actual type
+ * @param[in] char* name - the name of the received command.
+ * @param[in] openxc_DynamicField* value - the value of the received command, in a DynamicField. The actual type
* may be a number, string or bool.
- * event - an optional event from the received command, in a DynamicField. The
+ * @param[in] openxc_DynamicField* event - an optional event from the received command, in a DynamicField. The
* actual type may be a number, string or bool.
- * signals - The list of all signals.
- * signalCount - The length of the signals array.
+ * @param[in] CanSignal* signals - The list of all signals.
+ * @param[in] int signalCount - The length of the signals array.
*/
typedef void (*CommandHandler)(const char* name, openxc_DynamicField* value,
openxc_DynamicField* event, CanSignal* signals, int signalCount);
@@ -349,15 +370,16 @@ typedef struct {
CommandHandler handler;
} CanCommand;
-/* Pre initialize actions made before CAN bus initialization
+/**
+ * @brief Pre initialize actions made before CAN bus initialization
*
- * bus - A CanBus struct defining the bus's metadata
- * writable - configure the controller in a writable mode. If false, it will be
+ * @param[in] can_bus_dev_t bus - A CanBus struct defining the bus's metadata
+ * @param[in] bool writable - configure the controller in a writable mode. If false, it will be
* configured as "listen only" and will not allow writes or even CAN ACKs.
- * buses - An array of all CAN buses.
- * busCount - The length of the buses array.
+ * @param[in] buses - An array of all CAN buses.
+ * @param[in] int busCount - The length of the buses array.
*/
-void pre_initialize(CanBus* bus, bool writable, CanBus* buses, const int busCount);
+void pre_initialize(can_bus_dev_t* bus, bool writable, CanBus* buses, const int busCount);
/* Post-initialize actions made after CAN bus initialization and before the
* event loop connection.
@@ -368,7 +390,7 @@ void pre_initialize(CanBus* bus, bool writable, CanBus* buses, const int busCoun
* buses - An array of all CAN buses.
* busCount - The length of the buses array.
*/
-void post_initialize(CanBus* bus, bool writable, CanBus* buses, const int busCount);
+void post_initialize(can_bus_dev_t* bus, bool writable, CanBus* buses, const int busCount);
/* Public: Check if the device is connected to an active CAN bus, i.e. it's
* received a message in the recent past.
@@ -376,7 +398,7 @@ void post_initialize(CanBus* bus, bool writable, CanBus* buses, const int busCou
* Returns true if a message was received on the CAN bus within
* CAN_ACTIVE_TIMEOUT_S seconds.
*/
-bool isBusActive(CanBus* bus);
+bool isBusActive(can_bus_dev_t* bus);
/* Public: Log transfer statistics about all active CAN buses to the debug log.
*
diff --git a/src/can_decode_message.cpp b/src/can_decode_message.cpp
index 7e20f882..a28fa180 100644
--- a/src/can_decode_message.cpp
+++ b/src/can_decode_message.cpp
@@ -26,13 +26,7 @@
#include "can-utils.hpp"
#include "can-decoder.hpp"
#include "openxc.pb.h"
-
-union DynamicField
-{
- char string[100];
- double numeric_value;
- bool boolean_value;
-};
+#include "openxc-utils.hpp"
void can_decode_message(can_bus_t &can_bus)
{
@@ -57,7 +51,7 @@ void can_decode_message(can_bus_t &can_bus)
/* Decoding the message ! Don't kill the messenger ! */
for(const auto& sig : signals)
{
- subscribed_signals_i = subscribed_signals.find(sig);
+ subscribed_signals_i = subscribed_signals.find(sig.genericName);
if(subscribed_signals_i != subscribed_signals.end() &&
afb_event_is_valid(subscribed_signals_i->second))
@@ -73,98 +67,3 @@ void can_decode_message(can_bus_t &can_bus)
}
}
}
-
-/*
- * Build a specific VehicleMessage containing a SimpleMessage.
- */
-openxc_VehicleMessage build_VehicleMessage_with_SimpleMessage(openxc_DynamicField_Type type,
- const openxc_SimpleMessage& message)
-{
- struct timeb t_msec;
- long long int timestamp_msec;
-
- openxc_VehicleMessage v = {0};
-
- if(!ftime(&t_msec))
- {
- timestamp_msec = ((long long int) t_msec.time) * 1000ll +
- (long long int) t_msec.millitm;
-
- v.has_type = true:
- v.type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE;
- v.has_simple_message = true;
- v.simple_message = message;
- v.has_timestamp = true;
- v.timestamp = timestamp_msec;
-
- return v;
- }
-
- v.has_type = true,
- v.type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE;
- v.has_simple_message = true;
- v.simple_message = message;
-
- return v;
-}
-
-/*
- * Build an openxc_SimpleMessage associating a name to an openxc_DynamicField
- */
-openxc_SimpleMessage build_SimpleMessage(const std::string& name, const openxc_DynamicField& value)
-{
-
- openxc_SimpleMessage s = {0};
-
- s.has_name = true;
- ::strncpy(s.name, name.c_str(), 100);
- s.has_value = true;
- s.value = value;
-
- return s;
-}
-
-/*
- * Build an openxc_DynamicField depending what we pass as argument
- */
-openxc_DynamicField build_DynamicField(const std::string& value)
-{
- openxc_DynamicField d = {0}
- d.has_type = true;
- d.type = openxc_DynamicField_Type_STRING;
-
- d.has_string_value = true;
- ::strncpy(d.string_value, value.c_tr(), 100);
-
- return d;
-}
-
-/*
- * Build an openxc_DynamicField depending what we pass as argument
- */
-openxc_DynamicField build_DynamicField(double value)
-{
- openxc_DynamicField d = {0}
- d.has_type = true;
- d.type = openxc_DynamicField_Type_NUM;
-
- d.has_numeric_value = true;
- d.numeric_value = field;
-
- return d;
-}
-
-/*
- * Build an openxc_DynamicField depending what we pass as argument
- */
-openxc_DynamicField build_DynamicField(bool value)
-{
- openxc_DynamicField d = {0}
- d.has_type = true;
- d.type = openxc_DynamicField_Type_BOOL;
-
- d.has_boolean_value = true;
- d.boolean_value = field;
-
- return d;
-} \ No newline at end of file
diff --git a/src/can_event_push.cpp b/src/can_event_push.cpp
index 3964f97c..d3f4cbd6 100644
--- a/src/can_event_push.cpp
+++ b/src/can_event_push.cpp
@@ -23,6 +23,7 @@
#include <afb/afb-binding.h>
#include "can-utils.h"
+#include "openxc-utils.hpp"
#include "openxc.pb.h"
#include "json-c/json.h"
@@ -37,43 +38,9 @@ void can_event_push(can_bus_t& can_bus)
if(v_message = can_bus->next_vehicle_message())
{
s_message = get_simple_message(v_msg);
- const auto& it_event = subscribed_signals.find(s_msg.name);
+ const auto& it_event = subscribed_signals.find(s_message.name);
if(! it_event->end() && afb_event_is_valid(it_event->second))
- afb_event_push(it_event->second, jsonify_simple(s_msg));
+ afb_event_push(it_event->second, jsonify_simple(s_message));
}
}
}
-
-void jsonify_DynamicField(const openxc_DynamicField& field, const json_object& value)
-{
- if(field.has_numeric_value)
- json_object_object_add(value, "value", json_object_new_double(field.numeric_value));
- else if(field.has_boolean_value)
- json_object_object_add(value, "value", json_object_new_boolean(field.boolean_value));
- else if(field.has_string_value)
- json_object_object_add(value, "value", json_object_new_string(field.string_value));
-
- return value;
-}
-
-/* Extract the simple message value from an openxc_VehicleMessage
- * and return it, or null if there isn't.
- */
-openxc_SimpleMessage get_simple_message(const openxc_VehicleMessage& v_msg)
-{
- return v_msg.has_simple_message ? v_msg.simple_message : {0};
-}
-
-json_object jsonify_simple(const openxc_SimpleMessage& s_msg)
-{
- json_object *json;
- json = nullptr;
-
- if(s_msg->has_name)
- {
- json = json_object_new_object();
- json_object_object_add(json, "name", json_object_new_string(s_msg->name));
- jsonify_DynamicField(&s_msg->value, json);
- }
- return json;
-} \ No newline at end of file
diff --git a/src/low-can-binding.cpp b/src/low-can-binding.cpp
index c5fadbe3..23aaf900 100644
--- a/src/low-can-binding.cpp
+++ b/src/low-can-binding.cpp
@@ -33,24 +33,16 @@
#include <functional>
#include <memory>
#include <thread>
-#include <fstream>
#include <json-c/json.h>
#include <openxc.pb.h>
-#include <afb/afb-binding.h>
-#include <afb/afb-service-itf.h>
-
+#include "low-can-binding.hpp"
+#include "openxc-utils.hpp"
#include "obd2.hpp"
#include "can-utils.hpp"
#include "can-signals.hpp"
-/*
- * Interface between the daemon and the binding
- */
-static const struct afb_binding_interface *interface;
-static obd2_handler_t obd2_handler();
-
/********************************************************************************
*
* Event management
@@ -63,11 +55,11 @@ static obd2_handler_t obd2_handler();
*
*********************************************************************************/
-static int subscribe_unsubscribe_signal(struct afb_req request, bool subscribe, std::vector<CanSignal>::const_iterator& sig_i)
+static int subscribe_unsubscribe_signal(struct afb_req request, bool subscribe, const CanSignal& sig)
{
int ret;
- const auto& ss_i = subscribed_signals.find(sig_i);
+ const auto& ss_i = subscribed_signals.find(sig.genericName);
if (ss_i != subscribed_signals.end())
{
if(!afb_event_is_valid(ss_i->second))
@@ -79,7 +71,7 @@ static int subscribe_unsubscribe_signal(struct afb_req request, bool subscribe,
}
else
{
- ss_i->second = afb_daemon_make_event(interface->daemon, ss_i->first.genericName);
+ ss_i->second = afb_daemon_make_event(interface->daemon, ss_i->first.c_str());
if (!afb_event_is_valid(ss_i->second))
{
ERROR(interface, "Can't create an event, something goes wrong.");
@@ -90,7 +82,7 @@ static int subscribe_unsubscribe_signal(struct afb_req request, bool subscribe,
}
else
{
- subscribed_signals[sig_i] = afb_daemon_make_event(interface->daemon, sig_i->genericName);
+ subscribed_signals[sig.genericName] = afb_daemon_make_event(interface->daemon, sig.genericName);
if (!afb_event_is_valid(ss_i->second))
{
ERROR(interface, "Can't create an event, something goes wrong.");
@@ -98,9 +90,9 @@ static int subscribe_unsubscribe_signal(struct afb_req request, bool subscribe,
}
}
- if (((subscribe ? afb_req_subscribe : afb_req_unsubscribe)(request, subscribed_signals[sig_i])) < 0)
+ if (((subscribe ? afb_req_subscribe : afb_req_unsubscribe)(request, subscribed_signals[sig.genericName])) < 0)
{
- ERROR(interface, "Operation goes wrong for signal: %s", sig_i->genericName);
+ ERROR(interface, "Operation goes wrong for signal: %s", sig.genericName);
ret = 0;
}
else
@@ -124,12 +116,11 @@ static int subscribe_unsubscribe_signals(struct afb_req request, bool subscribe,
static int subscribe_unsubscribe_all(struct afb_req request, bool subscribe)
{
- int n, e;
+ int e = 0;
- n = obd2_handler.OBD2_PIDS.size();
- e = 0;
- for (const auto& pid : obd2_handler.OBD2_PIDS)
- e += !subscribe_unsubscribe_signals(request, subscribe, pid);
+ //for (const auto& sig : SIGNALS)
+ // e += !subscribe_unsubscribe_signals(request, subscribe, sig);
+ e += !subscribe_unsubscribe_signals(request, subscribe, SIGNALS[MESSAGE_SET_ID]);
return e == 0;
}
@@ -150,7 +141,8 @@ static int subscribe_unsubscribe_name(struct afb_req request, bool subscribe, co
}
else
{
- sig = find_can_signals(name);
+ openxc_DynamicField search_key = build_DynamicField(name);
+ sig = find_can_signals(search_key);
if (sig.empty())
ret = 0;
}
@@ -188,57 +180,60 @@ static void subscribe_unsubscribe(struct afb_req request, bool subscribe)
afb_req_fail(request, "error", NULL);
}
-static void subscribe(struct afb_req request)
-{
- subscribe_unsubscribe(request, true);
-}
-
-static void unsubscribe(struct afb_req request)
-{
- subscribe_unsubscribe(request, false);
-}
-
static const struct afb_verb_desc_v1 verbs[]=
{
- { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." },
- { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." }
+ { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." },
+ { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." }
};
-static const struct afb_binding binding_desc = {
- .type = AFB_BINDING_VERSION_1,
- .v1 = {
- .info = "CAN bus service",
- .prefix = "can",
- .verbs = verbs
+static const struct afb_binding binding_desc {
+ AFB_BINDING_VERSION_1,
+ {
+ "CAN bus service",
+ "can",
+ verbs
}
};
-const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
+extern "C"
{
- interface = itf;
-
- return &binding_desc;
-}
+ static void subscribe(struct afb_req request)
+ {
+ subscribe_unsubscribe(request, true);
+ }
-/**
- * @brief Initialize the binding.
- *
- * @param[in] service Structure which represent the Application Framework Binder.
- *
- * @return Exit code, zero if success.
- */
-int afbBindingV1ServiceInit(struct afb_service service)
-{
- std::ifstream fd_conf;
- fd_conf = afb_daemon_rootdir_open_locale(interface->daemon, "can_bus.json", O_RDONLY, NULL);
+ static void unsubscribe(struct afb_req request)
+ {
+ subscribe_unsubscribe(request, false);
+ }
- /* Open CAN socket */
- can_bus_t can_bus_handler(interface, fd_conf);
- if(can_bus_handler.init_can_dev() == 0)
+ const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
{
- can_bus_handler.start_threads();
- return 0;
+ interface = itf;
+
+ return &binding_desc;
}
- return 1;
-}
+ /**
+ * @brief Initialize the binding.
+ *
+ * @param[in] service Structure which represent the Application Framework Binder.
+ *
+ * @return Exit code, zero if success.
+ */
+ int afbBindingV1ServiceInit(struct afb_service service)
+ {
+ int fd_conf;
+ fd_conf = afb_daemon_rootdir_open_locale(interface->daemon, "can_bus.json", O_RDONLY, NULL);
+
+ /* Open CAN socket */
+ can_bus_t can_bus_handler(interface, fd_conf);
+ if(can_bus_handler.init_can_dev() == 0)
+ {
+ can_bus_handler.start_threads();
+ return 0;
+ }
+
+ return 1;
+ }
+} \ No newline at end of file
diff --git a/src/low-can-binding.hpp b/src/low-can-binding.hpp
new file mode 100644
index 00000000..20dc5dc4
--- /dev/null
+++ b/src/low-can-binding.hpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Romain Forlot" <romain.forlot@iot.bzh>
+ * Author "Loic Collignon" <loic.collignon@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.
+ */
+
+#pragma once
+
+#include "can-signals.hpp"
+
+extern "C"
+{
+ #include <afb/afb-binding.h>
+ #include <afb/afb-service-itf.h>
+
+ static void subscribe(struct afb_req request);
+ static void unsubscribe(struct afb_req request);
+
+ /**
+ * @brief Register the binding.
+ *
+ * @desc - A binding V1 MUST have a function of this name and signature.
+ * This function is called during loading of the binding. It
+ * receives an 'interface' that should be recorded for later access to
+ * functions provided by the framework.
+ *
+ * This function MUST return the address of a structure that describes
+ * the binding and its implemented verbs.
+ *
+ * In case of initialisation error, NULL must be returned.
+ *
+ * @param[in] const struct afb_binding_interface *itf - interface to the application framework binder.
+ *
+ * @return pointer to the binding or NULL in case of error
+ */
+ const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf);
+
+ /**
+ * @brief Initialize the binding.
+ *
+ * @param[in] service Structure which represent the Application Framework Binder.
+ *
+ * @return Exit code, zero if success.
+ */
+ int afbBindingV1ServiceInit(struct afb_service service);
+}
+
+/*
+ * Interface between the daemon and the binding
+ */
+static const struct afb_binding_interface *interface; \ No newline at end of file
diff --git a/src/obd2.cpp b/src/obd2.cpp
index 96b6c083..25416cd1 100644
--- a/src/obd2.cpp
+++ b/src/obd2.cpp
@@ -55,7 +55,7 @@ bool obd2_handler_t::is_obd2_request(DiagnosticRequest* request)
bool obd2_handler_t::is_obd2_signal(const char *name)
{
- if(fnmatch("obd2.*", name, NULL) == 0)
+ if(fnmatch("obd2.*", name, FNM_CASEFOLD) == 0)
return true;
return false;
}
diff --git a/src/obd2.hpp b/src/obd2.hpp
index b5bd0f87..365c683d 100644
--- a/src/obd2.hpp
+++ b/src/obd2.hpp
@@ -68,6 +68,31 @@ typedef struct _Obd2Pid {
struct afb_event event;
} Obd2Pid;
+/*
+ * Pre-defined OBD-II PIDs to query for if supported by the vehicle.
+ */
+const std::vector<Obd2Pid> OBD2_PIDS {
+ { pid: 0x04, name: "obd2.engine.load", min:0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x05, name: "obd2.engine.coolant.temperature", min: -40, max: 215, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x0a, name: "obd2.fuel.pressure", min: 0, max: 765, unit: KPA, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x0b, name: "obd2.intake.manifold.pressure", min: 0, max: 255, unit: KPA, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x0c, name: "obd2.engine.speed", min: 0, max: 16383, unit: RPM, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x0d, name: "obd2.vehicle.speed", min: 0, max: 255, unit: KM_H, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x0f, name: "obd2.intake.air.temperature", min: -40, max:215, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x10, name: "obd2.mass.airflow", min: 0, max: 655, unit: GRAMS_SEC, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x11, name: "obd2.throttle.position", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x1f, name: "obd2.running.time", min: 0, max: 65535, unit: SECONDS, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x2d, name: "obd2.EGR.error", min: -100, max: 99, unit: POURCENT, frequency: 0, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x2f, name: "obd2.fuel.level", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x33, name: "obd2.barometric.pressure", min: 0, max: 255, unit: KPA, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x4c, name: "obd2.commanded.throttle.position", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x52, name: "obd2.ethanol.fuel.percentage", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x5a, name: "obd2.accelerator.pedal.position", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x5b, name: "obd2.hybrid.battery-pack.remaining.life", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x5c, name: "obd2.engine.oil.temperature",min: -40, max: 210, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: {nullptr, nullptr} },
+ { pid: 0x63, name: "obd2.engine.torque", min: 0, max: 65535, unit: NM, frequency: 1, supported: false, event: {nullptr, nullptr} }
+};
+
/* Public: Check if a request is an OBD-II PID request.
*
* Returns true if the request is a mode 1 request and it has a 1 byte PID.
@@ -83,39 +108,14 @@ bool isObd2Request(DiagnosticRequest* request);
*/
float handleObd2Pid(const DiagnosticResponse* response, float parsedPayload);
-/*
- * Object to handle obd2 session with pre-scan of supported pid
+/**
+ * @brief - Object to handle obd2 session with pre-scan of supported pid
* then request them regularly
*/
class obd2_handler_t {
private:
public:
- /*
- * Pre-defined OBD-II PIDs to query for if supported by the vehicle.
- */
- const Obd2Pid OBD2_PIDS[] = {
- { pid: 0x04, name: "obd2.engine.load", min:0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: nullptr },
- { pid: 0x05, name: "obd2.engine.coolant.temperature", min: -40, max: 215, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: nullptr},
- { pid: 0x0a, name: "obd2.fuel.pressure", min: 0, max: 765, unit: KPA, frequency: 1, supported: false, event: nullptr },
- { pid: 0x0b, name: "obd2.intake.manifold.pressure", min: 0, max: 255, unit: KPA, frequency: 1, supported: false, event: nullptr },
- { pid: 0x0c, name: "obd2.engine.speed", min: 0, max: 16383, unit: RPM, frequency: 5, supported: false, event: nullptr },
- { pid: 0x0d, name: "obd2.vehicle.speed", min: 0, max: 255, unit: KM_H, frequency: 5, supported: false, event: nullptr },
- { pid: 0x0f, name: "obd2.intake.air.temperature", min: -40, max:215, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: nullptr },
- { pid: 0x10, name: "obd2.mass.airflow", min: 0, max: 655, unit: GRAMS_SEC, frequency: 5, supported: false, event: nullptr },
- { pid: 0x11, name: "obd2.throttle.position", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: nullptr },
- { pid: 0x1f, name: "obd2.running.time", min: 0, max: 65535, unit: SECONDS, frequency: 1, supported: false, event: nullptr },
- { pid: 0x2d, name: "obd2.EGR.error", min: -100, max: 99, unit: POURCENT, frequency: 0, supported: false, event: nullptr },
- { pid: 0x2f, name: "obd2.fuel.level", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: nullptr },
- { pid: 0x33, name: "obd2.barometric.pressure", min: 0, max: 255, unit: KPA, frequency: 1, supported: false, event: nullptr },
- { pid: 0x4c, name: "obd2.commanded.throttle.position", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: nullptr },
- { pid: 0x52, name: "obd2.ethanol.fuel.percentage", min: 0, max: 100, unit: POURCENT, frequency: 1, supported: false, event: nullptr },
- { pid: 0x5a, name: "obd2.accelerator.pedal.position", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: nullptr },
- { pid: 0x5b, name: "obd2.hybrid.battery-pack.remaining.life", min: 0, max: 100, unit: POURCENT, frequency: 5, supported: false, event: nullptr },
- { pid: 0x5c, name: "obd2.engine.oil.temperature",min: -40, max: 210, unit: DEGREES_CELSIUS, frequency: 1, supported: false, event: nullptr },
- { pid: 0x63, name: "obd2.engine.torque", min: 0, max: 65535, unit: NM, frequency: 1, supported: false, event: nullptr }
- };
-
/**
* @brief:
*
diff --git a/src/openxc-utils.cpp b/src/openxc-utils.cpp
new file mode 100644
index 00000000..b53a5eb3
--- /dev/null
+++ b/src/openxc-utils.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Romain Forlot" <romain.forlot@iot.bzh>
+ * Author "Loic Collignon" <loic.collignon@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.
+ */
+
+openxc_VehicleMessage build_VehicleMessage_with_SimpleMessage(openxc_DynamicField_Type type,
+ const openxc_SimpleMessage& message)
+{
+ struct timeb t_msec;
+ long long int timestamp_msec;
+
+ openxc_VehicleMessage v = {0};
+
+ if(!ftime(&t_msec))
+ {
+ timestamp_msec = ((long long int) t_msec.time) * 1000ll +
+ (long long int) t_msec.millitm;
+
+ v.has_type = true:
+ v.type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE;
+ v.has_simple_message = true;
+ v.simple_message = message;
+ v.has_timestamp = true;
+ v.timestamp = timestamp_msec;
+
+ return v;
+ }
+
+ v.has_type = true,
+ v.type = openxc_VehicleMessage_Type::openxc_VehicleMessage_Type_SIMPLE;
+ v.has_simple_message = true;
+ v.simple_message = message;
+
+ return v;
+}
+
+openxc_SimpleMessage build_SimpleMessage(const std::string& name, const openxc_DynamicField& value)
+{
+ openxc_SimpleMessage s = {0};
+
+ s.has_name = true;
+ ::strncpy(s.name, name.c_str(), 100);
+ s.has_value = true;
+ s.value = value;
+
+ return s;
+}
+
+openxc_DynamicField build_DynamicField(const std::string& value)
+{
+ openxc_DynamicField d = {0}
+ d.has_type = true;
+ d.type = openxc_DynamicField_Type_STRING;
+
+ d.has_string_value = true;
+ ::strncpy(d.string_value, value.c_tr(), 100);
+
+ return d;
+}
+
+openxc_DynamicField build_DynamicField(double value)
+{
+ openxc_DynamicField d = {0}
+ d.has_type = true;
+ d.type = openxc_DynamicField_Type_NUM;
+
+ d.has_numeric_value = true;
+ d.numeric_value = field;
+
+ return d;
+}
+
+openxc_DynamicField build_DynamicField(bool value)
+{
+ openxc_DynamicField d = {0}
+ d.has_type = true;
+ d.type = openxc_DynamicField_Type_BOOL;
+
+ d.has_boolean_value = true;
+ d.boolean_value = field;
+
+ return d;
+}
+
+void jsonify_DynamicField(const openxc_DynamicField& field, const json_object& value)
+{
+ if(field.has_numeric_value)
+ json_object_object_add(value, "value", json_object_new_double(field.numeric_value));
+ else if(field.has_boolean_value)
+ json_object_object_add(value, "value", json_object_new_boolean(field.boolean_value));
+ else if(field.has_string_value)
+ json_object_object_add(value, "value", json_object_new_string(field.string_value));
+
+ return value;
+}
+
+openxc_SimpleMessage get_simple_message(const openxc_VehicleMessage& v_msg)
+{
+ return v_msg.has_simple_message ? v_msg.simple_message : {0};
+}
+
+json_object jsonify_simple(const openxc_SimpleMessage& s_msg)
+{
+ json_object *json;
+ json = nullptr;
+
+ if(s_msg->has_name)
+ {
+ json = json_object_new_object();
+ json_object_object_add(json, "name", json_object_new_string(s_msg->name));
+ jsonify_DynamicField(&s_msg->value, json);
+ }
+ return json;
+} \ No newline at end of file
diff --git a/src/openxc-utils.hpp b/src/openxc-utils.hpp
new file mode 100644
index 00000000..f078c6eb
--- /dev/null
+++ b/src/openxc-utils.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Romain Forlot" <romain.forlot@iot.bzh>
+ * Author "Loic Collignon" <loic.collignon@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.
+ */
+
+#pragma once
+
+/*
+ * Build a specific VehicleMessage containing a SimpleMessage.
+ */
+openxc_VehicleMessage build_VehicleMessage_with_SimpleMessage(openxc_DynamicField_Type type,
+ const openxc_SimpleMessage& message);
+
+/*
+ * Build an openxc_SimpleMessage associating a name to an openxc_DynamicField
+ */
+openxc_SimpleMessage build_SimpleMessage(const std::string& name, const openxc_DynamicField& value);
+/*
+ * Build an openxc_DynamicField depending what we pass as argument
+ */
+openxc_DynamicField build_DynamicField(const std::string& value);
+
+/*
+ * Build an openxc_DynamicField depending what we pass as argument
+ */
+openxc_DynamicField build_DynamicField(double value);
+
+/*
+ * Build an openxc_DynamicField depending what we pass as argument
+ */
+openxc_DynamicField build_DynamicField(bool value);
+
+void jsonify_DynamicField(const openxc_DynamicField& field, const json_object& value);
+
+/* Extract the simple message value from an openxc_VehicleMessage
+ * and return it, or null if there isn't.
+ */
+openxc_SimpleMessage get_simple_message(const openxc_VehicleMessage& v_msg);
+
+json_object jsonify_simple(const openxc_SimpleMessage& s_msg); \ No newline at end of file