write: Add feature to build messages and fix some functions
authorArthur Guyader <arthur.guyader@iot.bzh>
Thu, 7 Nov 2019 09:06:25 +0000 (10:06 +0100)
committerRomain Forlot <romain.forlot@iot.bzh>
Thu, 7 Nov 2019 09:06:25 +0000 (10:06 +0100)
Allows to build a message (J1939,BCM) with a signal and a value.

Bug-AGL: SPEC-2386

Signed-off-by: Arthur Guyader <arthur.guyader@iot.bzh>
Change-Id: Iadca13a927ff83f713f39da441c88356695a1285

low-can-binding/binding/low-can-cb.cpp
low-can-binding/binding/low-can-subscription.cpp
low-can-binding/can/can-encoder.cpp
low-can-binding/can/can-encoder.hpp
low-can-binding/can/message/can-message.hpp
low-can-binding/can/message/j1939-message.cpp
low-can-binding/can/message/j1939-message.hpp
low-can-binding/can/message/message.cpp
low-can-binding/utils/socketcan-isotp.hpp
low-can-binding/utils/socketcan.hpp

index 1c01738..6738681 100644 (file)
@@ -716,7 +716,9 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
 
        if(! send_message(message, sig->get_message()->get_bus_device_name(), flags, event_filter, sig) && send)
                afb_req_success(request, nullptr, "Message correctly sent");
+       }
        else
+       {
                afb_req_fail(request, "Error", "Sending the message. See the log for more details.");
 
        if(sig->get_message()->is_j1939())
@@ -867,7 +869,6 @@ void list(afb_req_t request)
                afb_req_success(request, ans, NULL);
        else
                afb_req_fail(request, "error", NULL);
-
 }
 
 /// @brief Initialize the binding.
index 8b5f302..8c314af 100644 (file)
@@ -738,7 +738,9 @@ int low_can_subscription_t::tx_send(low_can_subscription_t &subscription, messag
        }
 
        if(! subscription.socket_.get())
-               return -1;
+       {
+                       return -1;
+       }
 
        return 0;
 }
index 94db19b..627cec3 100644 (file)
@@ -204,6 +204,118 @@ message_t* encoder_t::build_message(const std::shared_ptr<signal_t>& signal, uin
        }
 }
 
+
+/**
+ * @brief Allows to build a single frame message with correct data to be send
+ *
+ * @param signal The CAN signal to write, including the bit position and bit size.
+ * @param value The encoded integer value to write in the CAN signal.
+ * @param message A single frame message to complete
+ * @return message_t*  The message that is generated
+ */
+message_t* encoder_t::build_one_frame_message(const std::shared_ptr<signal_t>& signal, uint64_t value, message_t *message)
+{
+       signal->set_last_value((float)value);
+       uint8_t data_tab[message->get_length()];
+       std::vector<uint8_t> data;
+
+       for(const auto& sig: signal->get_message()->get_signals())
+       {
+               float last_value = sig->get_last_value();
+               bitfield_encode_float(last_value,
+                                       sig->get_bit_position(),
+                                       sig->get_bit_size(),
+                                       sig->get_factor(),
+                                       sig->get_offset(),
+                                       data_tab,
+                                       (uint8_t)message->get_length());
+       }
+
+       for (size_t i = 0; i < (uint8_t) message->get_length(); i++)
+       {
+               data.push_back(data_tab[i]);
+       }
+
+       message->set_data(data);
+       return message;
+}
+
+/**
+ * @brief Allows to build a multi frame message with correct data to be send
+ *
+ * @param signal The CAN signal to write, including the bit position and bit size.
+ * @param value The encoded integer value to write in the CAN signal.
+ * @param message A multi frame message to complete
+ * @return message_t*  The message that is generated
+ */
+message_t* encoder_t::build_multi_frame_message(const std::shared_ptr<signal_t>& signal, uint64_t value, message_t *message)
+{
+       signal->set_last_value((float)value);
+       std::vector<uint8_t> data;
+
+       uint32_t msgs_len = signal->get_message()->get_length(); // multi frame - number of bytes
+       int number_of_frame = (int) msgs_len / 8;
+
+       uint8_t data_tab[number_of_frame][8] = {0};
+
+       for(const auto& sig: signal->get_message()->get_signals())
+       {
+
+               int frame_position = (int) sig->get_bit_position() / 64;
+               float last_value = sig->get_last_value();
+               uint8_t bit_position = sig->get_bit_position() - ((uint8_t)(64 * frame_position));
+
+               bitfield_encode_float(last_value,
+                                       bit_position,
+                                       sig->get_bit_size(),
+                                       sig->get_factor(),
+                                       sig->get_offset(),
+                                       data_tab[frame_position],
+                                       8);
+       }
+
+       for (size_t i = 0; i < number_of_frame; i++)
+       {
+               for(size_t j = 0; j < 8 ; j++)
+               {
+                       data.push_back(data_tab[i][j]);
+               }
+       }
+
+       message->set_data(data);
+       return message;
+}
+
+/**
+ * @brief Allows to build a message_t with correct data to be send
+ *
+ * @param signal The CAN signal to write, including the bit position and bit size.
+ * @param value The encoded integer value to write in the CAN signal.
+ * @return message_t* The message that is generated
+ */
+message_t* encoder_t::build_message(const std::shared_ptr<signal_t>& signal, uint64_t value)
+{
+       message_t *message;
+       std::vector<uint8_t> data;
+       if(signal->get_message()->is_fd())
+       {
+               message = new can_message_t(CANFD_MAX_DLEN,signal->get_message()->get_id(),CANFD_MAX_DLEN,signal->get_message()->get_format(),false,0,data,0);
+               return build_one_frame_message(signal,value,message);
+       }
+#ifdef USE_FEATURE_J1939
+       else if(signal->get_message()->is_j1939())
+       {
+               message = new j1939_message_t(J1939_MAX_DLEN,signal->get_message()->get_length(),signal->get_message()->get_format(),data,0,J1939_NO_NAME,signal->get_message()->get_id(),J1939_NO_ADDR);
+               return build_multi_frame_message(signal,value,message);
+       }
+#endif
+       else
+       {
+               message = new can_message_t(CAN_MAX_DLEN,signal->get_message()->get_id(),CAN_MAX_DLEN,signal->get_message()->get_format(),false,0,data,0);
+               return build_one_frame_message(signal,value,message);
+       }
+}
+
 /// @brief Encode a boolean into an integer, fit for a CAN signal bitfield.
 ///
 /// This is a shortcut for encodeDynamicField(CanSignal*, openxc_DynamicField*,
index d4505f0..9989d0c 100644 (file)
@@ -30,10 +30,13 @@ class encoder_t
 public:
        static message_t* build_message(const std::shared_ptr<signal_t>& signal, uint64_t value, bool factor=true, bool offset=true);
        static message_t* build_frame(const std::shared_ptr<signal_t>& signal, uint64_t value, message_t *message, bool factor=true, bool offset=true);
+       static message_t* build_message(const std::shared_ptr<signal_t>& signal, uint64_t value);
+       static message_t* build_one_frame_message(const std::shared_ptr<signal_t>& signal, uint64_t value, message_t *message);
+       static message_t* build_multi_frame_message(const std::shared_ptr<signal_t>& signal, uint64_t value, message_t *message);
        static uint64_t encode_state(const signal_t& signal, const std::string& value, bool* send);
        static uint64_t encode_boolean(const signal_t& signal, bool value, bool* send);
        static uint64_t encode_number(const signal_t& signal, float value, bool* send);
        static void encode_data(std::shared_ptr<signal_t> sig, std::vector<uint8_t> &data, bool filter=false, bool factor=true, bool offset=true);
 
        static uint64_t encode_DynamicField(signal_t& signal, const openxc_DynamicField& field, bool* send);
-};
\ No newline at end of file
+};
index acc3bfc..8bc9aab 100644 (file)
@@ -53,10 +53,6 @@ class can_message_t : public message_t {
                static std::shared_ptr<can_message_t> convert_from_frame(const canfd_frame& frame, size_t nbytes, uint64_t timestamp);
                struct canfd_frame convert_to_canfd_frame();
                struct std::vector<canfd_frame> convert_to_canfd_frame_vector();
-               struct can_frame convert_to_can_frame();
-
-               bool is_correct_to_send();
-               bool is_set();
                struct bcm_msg& get_bcm_msg();
                void set_bcm_msg(struct bcm_msg bcm_msg);
 
index 432a139..31e08fc 100644 (file)
@@ -83,6 +83,23 @@ uint8_t j1939_message_t::get_addr() const{
        return addr_;
 }
 
+/**
+ * @brief Convert hex data to string
+ *
+ * @param data An array of data
+ * @param length The length of the data
+ * @return std::string The string data
+ */
+std::string to_hex( uint8_t data[], const size_t length)
+{
+    std::stringstream stream;
+    stream << std::hex << std::setfill('0');
+    for(int i = 0; i < length; i++)
+    {
+        stream << std::hex << ((int) data[i]);
+    }
+    return stream.str();
+}
 
 /// @brief Take a sockaddr_can struct and array of data to initialize class members
 ///
@@ -223,4 +240,4 @@ void j1939_message_t::set_sockname(pgn_t pgn, name_t name, uint8_t addr)
        {
                sockname_.can_addr.j1939.pgn = pgn;
        }
-}
\ No newline at end of file
+}
index a513e94..850455c 100644 (file)
@@ -79,4 +79,4 @@ class j1939_message_t : public message_t
                struct sockaddr_can get_sockname();
                void set_sockname(struct sockaddr_can sockname);
                void set_sockname(pgn_t pgn, name_t name, uint8_t addr);
-};
\ No newline at end of file
+};
index 2496b67..ef468c6 100644 (file)
@@ -188,4 +188,4 @@ void message_t::set_maxdlen(uint32_t maxdlen)
 void message_t::set_length(uint32_t length)
 {
        length_ = length;
-}
\ No newline at end of file
+}
index 86ed9fa..dfaf008 100644 (file)
@@ -36,4 +36,4 @@ namespace utils
                virtual int write_message(message_t& obj);
                int define_tx_address(std::string device_name, canid_t rx_id, canid_t tx_id);
        };
-}
\ No newline at end of file
+}
index 7b2501a..b08eeff 100644 (file)
 #define INVALID_SOCKET -1
 #define NO_CAN_ID 0xFFFFFFFFU
 
+/**
+ * @enum socket_type
+ * @brief The type of socket
+ */
+enum class socket_type {
+       BCM, ///< BCM - Socket BCM
+       J1939_ADDR_CLAIM, ///< J1939 - Socket J1939
+       J1939, ///< J1939 - Socket J1939
+       INVALID
+};
+
 namespace utils
 {