+///******************************************************************************
+///
+/// low_can_subscription_t object
+///
+///*******************************************************************************/
+
+low_can_subscription_t::low_can_subscription_t()
+ : index_{-1},
+ event_filter_{event_filter_t()},
+ socket_{}
+{}
+
+low_can_subscription_t::low_can_subscription_t(struct event_filter_t event_filter)
+ : event_filter_{event_filter}
+{}
+
+low_can_subscription_t::low_can_subscription_t(struct event_filter_t event_filter, std::shared_ptr<diagnostic_message_t> diagnostic_message)
+ : event_filter_{event_filter}, diagnostic_message_{diagnostic_message}
+{}
+
+low_can_subscription_t::low_can_subscription_t( low_can_subscription_t&& s)
+ : index_{s.index_},
+ event_filter_{s.event_filter_},
+ socket_{std::move(s.socket_)}
+{}
+
+ low_can_subscription_t& low_can_subscription_t::operator=(const low_can_subscription_t& s)
+{
+ socket_ = std::move(s.socket_);
+ return *this;
+}
+
+low_can_subscription_t::operator bool() const
+{
+ return socket_.socket() != INVALID_SOCKET;
+}
+
+int low_can_subscription_t::get_index() const
+{
+ return index_;
+}
+
+const std::shared_ptr<can_signal_t> low_can_subscription_t::get_can_signal() const
+{
+ return can_signal_;
+}
+
+const std::string low_can_subscription_t::get_sig_name() const
+{
+ return can_signal_->get_name();
+}
+
+float low_can_subscription_t::get_frequency() const
+{
+ return event_filter_.frequency;
+}
+
+float low_can_subscription_t::get_min() const
+{
+ return event_filter_.min;
+}
+
+float low_can_subscription_t::get_max() const
+{
+ return event_filter_.max;
+}
+
+utils::socketcan_bcm_t& low_can_subscription_t::get_socket()
+{
+ return socket_;
+}
+
+void low_can_subscription_t::set_frequency(float freq)
+{
+ event_filter_.frequency = freq;
+}
+
+void low_can_subscription_t::set_min(float min)
+{
+ event_filter_.min = min;
+}
+
+void low_can_subscription_t::set_max(float max)
+{
+ event_filter_.max = max;
+}
+
+/// @brief Create a RX_SETUP receive job used by the BCM socket.
+///
+/// @return 0 if ok else -1
+int low_can_subscription_t::create_rx_filter(std::shared_ptr<can_signal_t> sig)
+{
+ can_signal_= sig;
+ return create_rx_filter();
+}
+
+/// @brief Create a RX_SETUP receive job used by the BCM socket.
+///
+/// @return 0 if ok else -1
+int low_can_subscription_t::create_rx_filter()
+{
+ if (can_signal_ == nullptr)
+ {return -1;}
+
+ // Make sure that socket has been opened.
+ if(! socket_)
+ {
+ socket_.open(can_signal_->get_message()->get_bus_device_name());
+ index_ = (int)socket_.socket();
+ }
+
+ struct utils::simple_bcm_msg bcm_msg;
+ struct can_frame cfd;
+
+ memset(&cfd, 0, sizeof(cfd));
+ memset(&bcm_msg.msg_head, 0, sizeof(bcm_msg.msg_head));
+ float val = (float)(1 << can_signal_->get_bit_size()) - 1;
+
+ struct timeval freq;
+ frequency_clock_t f = event_filter_.frequency > 0.0f ? frequency_clock_t(event_filter_.frequency) : can_signal_->get_frequency();
+ freq = f.get_timeval_from_period();
+
+ bcm_msg.msg_head.opcode = RX_SETUP;
+ bcm_msg.msg_head.can_id = can_signal_->get_message()->get_id();
+ bcm_msg.msg_head.flags = SETTIMER|RX_NO_AUTOTIMER;
+ bcm_msg.msg_head.ival2.tv_sec = freq.tv_sec ;
+ bcm_msg.msg_head.ival2.tv_usec = freq.tv_usec;
+ bcm_msg.msg_head.nframes = 1;
+ bitfield_encode_float(val,
+ can_signal_->get_bit_position(),
+ can_signal_->get_bit_size(),
+ can_signal_->get_factor(),
+ can_signal_->get_offset(),
+ cfd.data,
+ CAN_MAX_DLEN);
+
+ bcm_msg.frames = cfd;
+
+ if(socket_ << bcm_msg)
+ return 0;
+ return -1;
+}
+
+///******************************************************************************
+///
+/// SystemD event loop Callbacks
+///
+///*******************************************************************************/
+
+void on_no_clients(const std::string& message)