Fix: OBD2_PIDS array initialization
authorRomain Forlot <romain.forlot@iot.bzh>
Mon, 20 Feb 2017 09:50:32 +0000 (09:50 +0000)
committerRomain Forlot <romain.forlot@iot.bzh>
Tue, 21 Feb 2017 10:59:19 +0000 (10:59 +0000)
Change-Id: Ic2c297e4ff94a13872f066ca42ee42beb45451ca
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
13 files changed:
src/CMakeLists.txt
src/can-signals.cpp
src/can-signals.hpp
src/can-utils.cpp
src/can-utils.hpp
src/can_decode_message.cpp
src/can_event_push.cpp
src/low-can-binding.cpp
src/low-can-binding.hpp [new file with mode: 0644]
src/obd2.cpp
src/obd2.hpp
src/openxc-utils.cpp [new file with mode: 0644]
src/openxc-utils.hpp [new file with mode: 0644]

index 84e8ecf..4f95cce 100644 (file)
@@ -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 ""
index b299693..c6a8ae9 100644 (file)
  * 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
index 2720513..b115263 100644 (file)
 
 #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
index 8d5f025..72f00aa 100644 (file)
@@ -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;
 
index db97b4b..0b0971d 100644 (file)
 
 #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
 
 #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.
  *
index 7e20f88..a28fa18 100644 (file)
 #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
index 3964f97..d3f4cbd 100644 (file)
@@ -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
index c5fadbe..23aaf90 100644 (file)
 #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 (file)
index 0000000..20dc5dc
--- /dev/null
@@ -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
index 96b6c08..25416cd 100644 (file)
@@ -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;
 }
index b5bd0f8..365c683 100644 (file)
@@ -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 (file)
index 0000000..b53a5eb
--- /dev/null
@@ -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 (file)
index 0000000..f078c6e
--- /dev/null
@@ -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