summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevron Rees <tripzero.kev@gmail.com>2015-04-06 08:33:33 -0700
committerKevron Rees <tripzero.kev@gmail.com>2015-04-06 08:33:33 -0700
commit4279804ec1986e918af017c8110dd5caf64e4887 (patch)
treec6897aa13d102f53e380c07aa096658b0452530d
parent9e370e5052ec254aa80306f6741dbc12bfb6bd5c (diff)
parent947be368482abf6f5d38a79213d9ba9d1c5debd4 (diff)
downloadautomotive-message-broker-4279804ec1986e918af017c8110dd5caf64e4887.tar.gz
Merge pull request #48 from CogentEmbedded/master
Fixes and improvements in CAN support
-rw-r--r--TODO2
-rw-r--r--ambd/CMakeLists.txt13
-rw-r--r--ambd/ambd.in50
-rw-r--r--ambd/core.cpp12
-rw-r--r--lib/asyncqueue.hpp9
-rw-r--r--lib/superptr.hpp2
-rw-r--r--lib/timestamp.cpp16
-rw-r--r--lib/timestamp.h5
-rw-r--r--plugins/cangenplugin/cangenplugin.cpp8
-rw-r--r--plugins/cangenplugin/cangenplugin.h6
-rw-r--r--plugins/cansimplugin/cansimplugin.cpp10
-rw-r--r--plugins/cansimplugin/cansimplugin.h6
-rw-r--r--plugins/common/CMakeLists.txt8
-rw-r--r--plugins/common/canadapter.h18
-rw-r--r--plugins/common/canbus.h97
-rw-r--r--plugins/common/canbusimpl.cpp70
-rw-r--r--plugins/common/canbusimpl.h26
-rw-r--r--plugins/common/canframeinfo.h72
-rw-r--r--plugins/common/canobserver.h10
-rw-r--r--plugins/common/cansocket.cpp119
-rw-r--r--plugins/common/cansocket.h68
-rw-r--r--plugins/common/cansocketadapter.cpp23
-rw-r--r--plugins/common/cansocketadapter.h16
-rw-r--r--plugins/common/cansocketbcm.cpp279
-rw-r--r--plugins/common/cansocketbcm.h122
-rw-r--r--plugins/common/cansocketraw.cpp199
-rw-r--r--plugins/common/cansocketraw.h103
-rw-r--r--plugins/common/cansocketreader.cpp90
-rw-r--r--plugins/common/cansocketreader.h7
-rw-r--r--plugins/common/thread.cpp151
-rw-r--r--plugins/common/thread.h9
-rw-r--r--plugins/dbus/dbusinterfacemanager.cpp2
-rw-r--r--tools/AmbSignalMapper/Makefile.PL11
-rw-r--r--tools/AmbSignalMapper/README29
-rw-r--r--tools/AmbSignalMapper/TODO2
-rwxr-xr-xtools/AmbSignalMapper/bin/dbc2amb295
-rwxr-xr-xtools/AmbSignalMapper/bin/dbc2json2
-rwxr-xr-xtools/AmbSignalMapper/bin/json2amb13
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm58
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar97
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/MsgGrammar129
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt31
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl.in.json7
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp12
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h28
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp30
-rw-r--r--tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h20
-rw-r--r--tools/AmbSignalMapper/t/syntax.msg45
48 files changed, 2005 insertions, 432 deletions
diff --git a/TODO b/TODO
index 31fb46be..a9ee8d70 100644
--- a/TODO
+++ b/TODO
@@ -4,4 +4,6 @@
- Refactor obd2 plugin with AsyncQueue. Use thread-safe updateProperty.
- source export from database plugin does not reflect the source in the database
- grep all the TODOs in the code and do them
+- implement no-value for AbstractPropertyType
+- add timestamp processing for CAN data
diff --git a/ambd/CMakeLists.txt b/ambd/CMakeLists.txt
index 4c66e05e..c17222a0 100644
--- a/ambd/CMakeLists.txt
+++ b/ambd/CMakeLists.txt
@@ -36,7 +36,12 @@ add_executable(ambd ${ambd_sources})
include_directories(${include_dirs} )
target_link_libraries(ambd ${link_libraries} dl amb ${gio_LIBRARIES})
-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.in.json ${CMAKE_CURRENT_BINARY_DIR}/config @ONLY)
-
-install (TARGETS ambd RUNTIME DESTINATION bin)
-install (FILES ${CMAKE_CURRENT_BINARY_DIR}/config DESTINATION /etc/ambd)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.in.json ${CMAKE_CURRENT_BINARY_DIR}/config @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ambd.in ${CMAKE_CURRENT_BINARY_DIR}/init.d/ambd @ONLY)
+
+install(TARGETS ambd RUNTIME DESTINATION bin)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config DESTINATION /etc/ambd)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/init.d/ambd
+ DESTINATION /etc/init.d/
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)
diff --git a/ambd/ambd.in b/ambd/ambd.in
new file mode 100644
index 00000000..95a2a5b7
--- /dev/null
+++ b/ambd/ambd.in
@@ -0,0 +1,50 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: ambd
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Automotive Message Broker daemon
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+[ -f /etc/default/ambd ] && . /etc/default/ambd
+
+case "$1" in
+ start)
+ echo -n "Starting Automotive Message Broker daemon: "
+ start-stop-daemon -S -x @CMAKE_INSTALL_PREFIX@/bin/ambd -- -D
+ if [ $? = 0 ]; then
+ echo "ambd."
+ else
+ echo "(failed.)"
+ fi
+ ;;
+ stop)
+ echo -n "Stopping Automotive Message Broker daemon: "
+ start-stop-daemon -K -x @CMAKE_INSTALL_PREFIX@/bin/ambd
+ echo "apmd."
+ ;;
+ status)
+ status @CMAKE_INSTALL_PREFIX@/bin/ambd;
+ exit $?
+ ;;
+ restart|force-reload)
+ $0 stop
+ $0 start
+ exit
+ ;;
+ *)
+ echo "Usage: /etc/init.d/ambd {start|stop|status|restart|force-reload}"
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/ambd/core.cpp b/ambd/core.cpp
index 02e4a08e..419c078e 100644
--- a/ambd/core.cpp
+++ b/ambd/core.cpp
@@ -166,26 +166,14 @@ void Core::updateProperty(AbstractPropertyType *value, const string & uuid)
updateProperty(value);
else if(value->priority == AbstractPropertyType::High)
{
- value->destroyed.push_back([this](AbstractPropertyType* v)
- {
- updatePropertyQueueHigh.remove(v);
- });
updatePropertyQueueHigh.append(value);
}
else if(value->priority == AbstractPropertyType::Normal)
{
- value->destroyed.push_back([this](AbstractPropertyType* v)
- {
- updatePropertyQueue.remove(v);
- });
updatePropertyQueue.append(value);
}
else if(value->priority == AbstractPropertyType::Low)
{
- value->destroyed.push_back([this](AbstractPropertyType* v)
- {
- updatePropertyQueueLow.remove(v);
- });
updatePropertyQueueLow.append(value);
}
}
diff --git a/lib/asyncqueue.hpp b/lib/asyncqueue.hpp
index 61ff412e..0e4da9af 100644
--- a/lib/asyncqueue.hpp
+++ b/lib/asyncqueue.hpp
@@ -82,10 +82,15 @@ public:
{
std::lock_guard<std::mutex> lock(mutex);
- if(contains(mQueue, item))
+ auto i = mQueue.begin();
+ while(true)
{
- mQueue.erase(std::find(mQueue.begin(), mQueue.end(), item));
+ i = find(i, mQueue.end(), item);
+ if (i == mQueue.end())
+ break;
+ i = mQueue.erase(i);
}
+
mQueue.push_back(item);
}
diff --git a/lib/superptr.hpp b/lib/superptr.hpp
index afe09836..98fc6ec4 100644
--- a/lib/superptr.hpp
+++ b/lib/superptr.hpp
@@ -93,7 +93,7 @@ template<typename T> ::std::shared_ptr<T> make_shared(T* t)
template<typename T> gobject_ptr<T> make_gobject(T* t)
{
- return gobject_ptr<T>(t, [](auto ptr) { if(ptr) g_object_unref(ptr);});
+ return gobject_ptr<T>(t, [](T *ptr) { if(ptr) g_object_unref(ptr);});
}
}
diff --git a/lib/timestamp.cpp b/lib/timestamp.cpp
index 33e01823..7b1f5931 100644
--- a/lib/timestamp.cpp
+++ b/lib/timestamp.cpp
@@ -1,5 +1,6 @@
#include "timestamp.h"
+#include <math.h>
#include <time.h>
#include <iostream>
#include <chrono>
@@ -36,6 +37,11 @@ double amb::Timestamp::epochTime(double time)
return startTimeEpoch + time;
}
+double amb::Timestamp::currentTime(double time)
+{
+ return time - startTimeEpoch;
+}
+
double amb::Timestamp::epochTime()
{
auto tm = std::chrono::system_clock::now();
@@ -52,3 +58,13 @@ amb::Timestamp* amb::Timestamp::instance()
return mInstance;
}
+
+double amb::Timestamp::fromTimeval(const struct ::timeval &tv)
+{
+ return tv.tv_sec*1.0 + tv.tv_usec*1e-6;
+}
+
+struct ::timeval amb::Timestamp::toTimeval(const double time)
+{
+ return { (__time_t) time, (__suseconds_t)fmod(time*1e6, 1e6) };
+}
diff --git a/lib/timestamp.h b/lib/timestamp.h
index 7d553b1d..0e7d1b6e 100644
--- a/lib/timestamp.h
+++ b/lib/timestamp.h
@@ -1,6 +1,7 @@
#ifndef _TIMESTAMP_H___
#define _TIMESTAMP_H___
+#include <time.h>
namespace amb {
@@ -25,6 +26,7 @@ public:
* \return current monotonic (steady) time in seconds.
*/
double currentTime();
+ double currentTime(double time);
/*!
* \brief epochTime
@@ -39,6 +41,9 @@ public:
*/
double epochTime();
+ static double fromTimeval(const struct ::timeval& tv);
+ static struct ::timeval toTimeval(const double time);
+
public:
/*!
* \brief instance
diff --git a/plugins/cangenplugin/cangenplugin.cpp b/plugins/cangenplugin/cangenplugin.cpp
index 73d32538..93d2e718 100644
--- a/plugins/cangenplugin/cangenplugin.cpp
+++ b/plugins/cangenplugin/cangenplugin.cpp
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <logger.h>
#include <ambplugin.h>
+#include <canbusimpl.h>
#include "cangenplugin.h"
@@ -203,7 +204,7 @@ bool CANGenPlugin::sendValue(const std::string& interface, AbstractPropertyType*
auto& canBus = interfaces[interface];
if(!canBus){
- canBus = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ canBus = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
bool started(canBus->start(interface.c_str()));
if(!started)
return false;
@@ -464,3 +465,8 @@ void CANGenPlugin::dataReceived(libwebsocket* socket, const char* data, size_t l
}
}
}
+
+void CANGenPlugin::timeoutDetected(const can_frame& frame)
+{
+ // do nothing
+}
diff --git a/plugins/cangenplugin/cangenplugin.h b/plugins/cangenplugin/cangenplugin.h
index 09e9c4e5..163cde0e 100644
--- a/plugins/cangenplugin/cangenplugin.h
+++ b/plugins/cangenplugin/cangenplugin.h
@@ -137,6 +137,12 @@ public:
* \param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame);
/*!
* Second phase of the plugin initialization.
diff --git a/plugins/cansimplugin/cansimplugin.cpp b/plugins/cansimplugin/cansimplugin.cpp
index b609b3f9..c8b99216 100644
--- a/plugins/cansimplugin/cansimplugin.cpp
+++ b/plugins/cansimplugin/cansimplugin.cpp
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <ambplugin.h>
#include <logger.h>
+#include <canbusimpl.h>
#include "cansimplugin.h"
@@ -86,7 +87,7 @@ CANSimPlugin::CANSimPlugin(AbstractRoutingEngine* re, const map<string, string>&
json_object* obj = (json_object*)array_list_get_idx(ifacelist,i);
const char* str = obj ? json_object_get_string(obj) : nullptr;
if(str){
- interfaces[str] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ interfaces[str] = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
}
}
}
@@ -94,7 +95,7 @@ CANSimPlugin::CANSimPlugin(AbstractRoutingEngine* re, const map<string, string>&
}
// Default interface if none has been configured.
if(interfaces.empty()){
- interfaces[DEFAULT_CAN_IF_NAME] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ interfaces[DEFAULT_CAN_IF_NAME] = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
}
addPropertySupport(
@@ -386,4 +387,7 @@ void CANSimPlugin::printFrame(const can_frame& frame) const
LOG_INFO( "CANSimPlugin::printFrame can data" << ss.str() << endl );
}
-
+void CANSimPlugin::timeoutDetected(const can_frame& frame)
+{
+ // do nothing
+}
diff --git a/plugins/cansimplugin/cansimplugin.h b/plugins/cansimplugin/cansimplugin.h
index 40b55d51..43b1f79e 100644
--- a/plugins/cansimplugin/cansimplugin.h
+++ b/plugins/cansimplugin/cansimplugin.h
@@ -126,6 +126,12 @@ public:
* \param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame);
/*!
* Second phase of the plugin initialization.
diff --git a/plugins/common/CMakeLists.txt b/plugins/common/CMakeLists.txt
index 052c2c56..407b281e 100644
--- a/plugins/common/CMakeLists.txt
+++ b/plugins/common/CMakeLists.txt
@@ -1,9 +1,9 @@
set(plugins_common_sources abstractio.hpp serialport.hpp bluetoothadapterproxy.c bluetooth.hpp bluetoothmanagerproxy.c bluetoothserialproxy.c bluetooth5.cpp
- canadapter.cpp cansocket.cpp cansocketreader.cpp canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp thread.cpp dbusexport.cpp dbusplugin.cpp
- abstractdbusinterface.cpp dbussignaller.cpp varianttype.cpp)
+ canadapter.cpp cansocket.cpp cansocketraw.cpp cansocketbcm.cpp cansocketreader.cpp canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp
+ thread.cpp dbusexport.cpp dbusplugin.cpp abstractdbusinterface.cpp dbussignaller.cpp varianttype.cpp)
set(plugins_common_headers_install abstractio.hpp serialport.hpp bluetooth.hpp bluetoothadapterproxy.h bluetoothmanagerproxy.h bluetoothserialproxy.h
- bluetooth5.h canbus.h canadapter.h cansocket.h cansocketreader.h canbusimpl.h cansocketadapter.h canobserver.h logger.h mutex.h thread.h
- dbusexport.h dbusplugin.h abstractdbusinterface.h dbussignaller.h varianttype.h)
+ bluetooth5.h canframeinfo.h canbus.h canadapter.h cansocket.h cansocketraw.h cansocketbcm.h cansocketreader.h canbusimpl.h cansocketadapter.h
+ canobserver.h logger.h mutex.h thread.h dbusexport.h dbusplugin.h abstractdbusinterface.h dbussignaller.h varianttype.h)
add_library(amb-plugins-common SHARED ${plugins_common_sources})
diff --git a/plugins/common/canadapter.h b/plugins/common/canadapter.h
index fa78c102..2efffa03 100644
--- a/plugins/common/canadapter.h
+++ b/plugins/common/canadapter.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -68,6 +70,22 @@ public:
* @return True if frame was sent
*/
virtual bool sendFrame(const can_frame& frame) = 0;
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime) = 0;
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId) = 0;
protected:
/**
diff --git a/plugins/common/canbus.h b/plugins/common/canbus.h
index 319c856a..4d9d856c 100644
--- a/plugins/common/canbus.h
+++ b/plugins/common/canbus.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,6 +18,8 @@ License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* Refactored to an abstract interface. See http://stackoverflow.com/a/825365 */
+
#ifndef CANBUS_H
#define CANBUS_H
@@ -35,47 +39,60 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
class CANBus
{
public:
- /**
- * @param observer Object derived from #CANObserver that will receive CAN bus frames
- */
- CANBus(CANObserver& observer);
- virtual ~CANBus();
-
- /**
- * Starts the CAN bus instance on the specified interface
- * @fn start
- * @param name Name of the CAN bus network interface
- * @return True if no error occurs.
- */
- virtual bool start(const char* name);
- /**
- * Stops the CAN bus instance
- * @fn stop
- */
- virtual void stop();
- /**
- * Sends standard(11bit) CAN frame over the bus
- * @fn sendStandardFrame
- * @param frame CAN frame to be sent
- * @return True if frame was sent
- */
- virtual bool sendStandardFrame(const can_frame& frame);
- /**
- * Sends extended(29bit) CAN frame over the bus
- * @fn sendExtendedFrame
- * @param frame CAN frame to be sent
- * @return True if frame was sent
- */
- virtual bool sendExtendedFrame(const can_frame& frame);
+ virtual ~CANBus(){} /*LCOV_EXCL_LINE*/
- class Impl;
-protected:
- /**
- * CANBus class private implementation
- * @property d
- * @protected
- */
- Impl* d;
+ /**
+ * Starts the CAN bus instance on the specified interface
+ * @fn start
+ * @param name Name of the CAN bus network interface
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* name) = 0;
+ /**
+ * Stops the CAN bus instance
+ * @fn stop
+ */
+ virtual void stop() = 0;
+ /**
+ * Sends standard(11bit) CAN frame over the bus
+ * @fn sendStandardFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendStandardFrame(const can_frame& frame) = 0;
+ /**
+ * Sends extended(29bit) CAN frame over the bus
+ * @fn sendExtendedFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendExtendedFrame(const can_frame& frame) = 0;
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime) = 0;
+ /**
+ * Registers CAN ID of a message for receiving with no timeout. Perfect for sporadic messages.
+ * @fn registerMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerMessageForReceive(int canId)
+ {
+ return registerCyclicMessageForReceive(canId, 0, 0);
+ }
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId) = 0;
};
#endif // CANBUS_H
diff --git a/plugins/common/canbusimpl.cpp b/plugins/common/canbusimpl.cpp
index 993e4a0f..b0a0fa7d 100644
--- a/plugins/common/canbusimpl.cpp
+++ b/plugins/common/canbusimpl.cpp
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -21,25 +23,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "canadapter.h"
#include "logger.h"
-//----------------------------------------------------------------------------
-// CANBusImpl
-//----------------------------------------------------------------------------
-
-CANBus::Impl::Impl(CANObserver& observer) :
+CANBusImpl::CANBusImpl(CANObserver& observer) :
mObserver(observer),
mAdapter(NULL)
{
LOG_TRACE("");
}
-CANBus::Impl::~Impl()
+CANBusImpl::~CANBusImpl()
{
LOG_TRACE("");
stop();
}
-bool CANBus::Impl::start(const char* name)
+bool CANBusImpl::start(const char* name)
{
LOG_TRACE("");
@@ -49,7 +47,7 @@ bool CANBus::Impl::start(const char* name)
return mAdapter ? mAdapter->start(name) : false;
}
-void CANBus::Impl::stop()
+void CANBusImpl::stop()
{
LOG_TRACE("");
@@ -60,7 +58,7 @@ void CANBus::Impl::stop()
}
}
-bool CANBus::Impl::sendStandardFrame(const can_frame& frame)
+bool CANBusImpl::sendStandardFrame(const can_frame& frame)
{
LOG_TRACE("");
@@ -72,7 +70,7 @@ bool CANBus::Impl::sendStandardFrame(const can_frame& frame)
return false;
}
-bool CANBus::Impl::sendExtendedFrame(const can_frame& frame)
+bool CANBusImpl::sendExtendedFrame(const can_frame& frame)
{
LOG_TRACE("");
@@ -85,56 +83,24 @@ bool CANBus::Impl::sendExtendedFrame(const can_frame& frame)
return false;
}
-void CANBus::Impl::init()
+void CANBusImpl::init()
{
mAdapter = CANAdapter::createCANAdapter(mObserver);
}
-//----------------------------------------------------------------------------
-// CANBus
-//----------------------------------------------------------------------------
-
-CANBus::CANBus(CANObserver& observer) :
- d(new CANBus::Impl(observer))
-{
- LOG_TRACE("");
-}
-
-CANBus::~CANBus()
+bool CANBusImpl::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
{
- LOG_TRACE("");
-
- if(d) {
- delete d;
- d = 0;
+ if(mAdapter) {
+ return mAdapter->registerCyclicMessageForReceive(canId, minCycleTime, maxCycleTime);
}
+ return false;
}
-bool CANBus::start(const char* name)
-{
- LOG_TRACE("");
-
- return d ? d->start(name) : false;
-}
-
-void CANBus::stop()
-{
- LOG_TRACE("");
-
- if(d)
- d->stop();
-}
-
-bool CANBus::sendStandardFrame(const can_frame& frame)
+bool CANBusImpl::unregisterMessageForReceive(int canId)
{
- LOG_TRACE("");
-
- return d ? d->sendStandardFrame(frame) : false;
+ if(mAdapter) {
+ return mAdapter->unregisterMessageForReceive(canId);
+ }
+ return false;
}
-bool CANBus::sendExtendedFrame(const can_frame& frame)
-{
- LOG_TRACE("");
-
- return d ? d->sendExtendedFrame(frame) : false;
-}
diff --git a/plugins/common/canbusimpl.h b/plugins/common/canbusimpl.h
index e2ccdd9c..c7698b80 100644
--- a/plugins/common/canbusimpl.h
+++ b/plugins/common/canbusimpl.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -35,14 +37,14 @@ class CANAdapter;
* @class CANBus::Impl
*/
-class CANBus::Impl
+class CANBusImpl : public CANBus
{
public:
/**
- * @param observer \link #CANObserver Observer \endlink that will receives CAN bus frames
+ * @param observer \link #CANObserver Observer \endlink that will receive CAN bus frames
*/
- Impl(CANObserver& observer);
- virtual ~Impl();
+ CANBusImpl(CANObserver& observer);
+ virtual ~CANBusImpl();
/**
* Starts the CAN bus instance on the specified interface
@@ -70,6 +72,22 @@ public:
* @return True if frame was sent
*/
bool sendExtendedFrame(const can_frame& frame);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
protected:
/**
diff --git a/plugins/common/canframeinfo.h b/plugins/common/canframeinfo.h
new file mode 100644
index 00000000..6469a679
--- /dev/null
+++ b/plugins/common/canframeinfo.h
@@ -0,0 +1,72 @@
+/*
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANFRAMEINFO_H
+#define CANFRAMEINFO_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <stdlib.h>
+#include <linux/can.h>
+
+#include "timestamp.h"
+
+/**
+ * CAN frame with additional information
+ */
+struct CANFrameInfo
+{
+ CANFrameInfo(const can_frame &frame)
+ {
+ this->status = CANFrameInfo::CANMessageStatus::GOOD;
+ this->frame = frame;
+ this->timestamp = amb::currentTime();
+ }
+
+ CANFrameInfo() { }
+
+ enum CANMessageStatus {
+ TIMEOUT = -2,
+ EMPTY = 0,
+ GOOD = 1,
+ };
+
+ /**
+ * The actual frame written or read from socket
+ */
+ struct can_frame frame;
+
+ /**
+ * Status of the message.
+ */
+ CANFrameInfo::CANMessageStatus status;
+
+ /**
+ * Timestamp of sending or receiving action
+ */
+ double timestamp;
+};
+
+#endif // CANFRAMEINFO_H
+
+/** @} */
+
diff --git a/plugins/common/canobserver.h b/plugins/common/canobserver.h
index 0518bd49..549f0700 100644
--- a/plugins/common/canobserver.h
+++ b/plugins/common/canobserver.h
@@ -24,8 +24,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @{
*/
+#include <stdlib.h>
#include <linux/can.h>
+#include "canframeinfo.h"
+
/**
* \brief Interface. Receives notifications about the CAN bus traffic and errors.
*
@@ -76,7 +79,12 @@ public:
* @param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame) = 0; /* remote transmission request (SFF/EFF is still present)*/
-
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame) = 0; /* timeout */
};
#endif // CANOBSERVER_H
diff --git a/plugins/common/cansocket.cpp b/plugins/common/cansocket.cpp
index b59c6bd5..0b5ca9c0 100644
--- a/plugins/common/cansocket.cpp
+++ b/plugins/common/cansocket.cpp
@@ -24,135 +24,54 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "logger.h"
#include "cansocket.h"
-
-CANSocket::CANSocket() :
- mSocket(-1)
+CANSocket::CANSocket()
{
+ // default implementation doesn't do anything
LOG_TRACE("");
}
CANSocket::~CANSocket()
{
+ // default implementation doesn't do anything
LOG_TRACE("");
stop();
}
-bool CANSocket::start(const char* ifName)
-{
- LOG_TRACE("");
-
- if(mSocket < 0) {
- if(!createSocket()) {
- LOG_ERROR("Socket error");
- } else {
- can_err_mask_t errorMask = 0xFFFFFFFF;
- if(!enableCANErrors(errorMask)) {
- LOG_ERROR("Socket error");
- } else {
- mPoll.fd = mSocket;
- mPoll.events = POLLIN | POLLPRI;
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ifName);
- if(!locateInterfaceIndex(ifr)) {
- LOG_ERROR("Socket error");
- stop();
- } else {
- struct sockaddr_can addr;
- memset(&addr, 0, sizeof(addr));
- addr.can_family = AF_CAN;
- addr.can_ifindex = ifr.ifr_ifindex;
- if(!bindSocket(addr)) {
- LOG_ERROR("Socket error");
- stop();
- } else {
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
void CANSocket::stop()
{
- LOG_TRACE("");
-
- if(mSocket >= 0) {
- closeSocket();
- mSocket = -1;
- }
+ // default implementation doesn't do anything
}
-bool CANSocket::write(const struct can_frame &frame, int &bytesWritten)
+bool CANSocket::write(const struct CANFrameInfo &message)
{
+ // default implementation doesn't do anything
LOG_TRACE("");
- bytesWritten = (int)writeFrame(frame);
- return bytesWritten == sizeof(struct can_frame);
-}
-
-CANSocket::CANSocketReadSuccess CANSocket::read(
- struct can_frame& frame, int &bytesRead, unsigned int timeout)
-{
- LOG_TRACE("timeout: " << timeout);
-
- CANSocket::CANSocketReadSuccess success;
-
- switch(waitData(timeout)) {
- case -1:
- LOG_ERROR("reading error");
- success = CANSocket::READING_FAILED;
- break;
- case 0:
- bytesRead = 0;
- success = CANSocket::READING_TIMED_OUT;
- break;
- default:
- bytesRead = (int)readFrame(frame);
- success = bytesRead >= 0 ?CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
- }
- return success;
-}
-
-bool CANSocket::createSocket()
-{
- return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
+ return false;
}
-bool CANSocket::enableCANErrors(can_err_mask_t errorMask)
-{
- return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
-}
-bool CANSocket::locateInterfaceIndex(struct ifreq& ifr)
+CANSocket::CANSocketReadSuccess CANSocket::read(struct CANFrameInfo& message, unsigned int timeout)
{
- return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-bool CANSocket::bindSocket(struct sockaddr_can& addr)
-{
- return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+ return CANSocketReadSuccess::READING_FAILED;
}
-bool CANSocket::closeSocket()
+bool CANSocket::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
{
- return (::close(mSocket) == 0);
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-int CANSocket::waitData(unsigned int timeout)
-{
- return ::poll(&mPoll, 1, timeout);
+ return false;
}
-ssize_t CANSocket::writeFrame(const can_frame& frame)
+bool CANSocket::unregisterMessageForReceive(int canId)
{
- return ::write(mSocket, &frame, sizeof(struct can_frame));
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-ssize_t CANSocket::readFrame(can_frame& frame)
-{
- return ::recv(mSocket, &frame, sizeof(struct can_frame), 0);
+ return false;
}
diff --git a/plugins/common/cansocket.h b/plugins/common/cansocket.h
index f6eaa50a..a201e5a4 100644
--- a/plugins/common/cansocket.h
+++ b/plugins/common/cansocket.h
@@ -24,13 +24,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @{
*/
-#include <net/if.h>
-#include <sys/poll.h>
-#include <string>
-#include <linux/can/raw.h>
+#include <linux/can.h>
+
+#include "canbus.h"
/**
-* \brief CAN Socket wrapper.
+* \brief Wrapper around different implementations of SocketCAN.
* @class CANSocket
*/
class CANSocket
@@ -45,7 +44,7 @@ public:
enum CANSocketReadSuccess {
READING_FAILED = -1,
READING_TIMED_OUT,
- READING_SUCCEEDED
+ READING_SUCCEEDED,
};
public:
@@ -53,62 +52,49 @@ public:
virtual ~CANSocket();
/**
- * Opens and initialize CAN socket
+ * Opens and initializes CAN socket
* @fn start
* @param ifName Name of the CAN bus network interface.
* @return True if no error occurs.
*/
- virtual bool start(const char* ifName);
+ virtual bool start(const char* ifName) = 0;
/**
- * Closes socket
+ * Closes the socket
* @fn stop
*/
virtual void stop();
/**
* Writes CAN frame using the socket
* @fn write
- * @param frame CAN frame buffer
+ * @param message CAN frame with additional information
* @param bytesWritten Number of written bytes.
* @return True if no error occurs.
*/
- virtual bool write(const struct can_frame &frame, int &bytesWritten);
-
+ virtual bool write(const struct CANFrameInfo &message);
/**
* Try to read CAN frame
* @fn read
- * @param frame CAN frame buffer
- * @param bytesRead Number of read bytes.
- * @param timeout Timeout for reading.
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
* @return Reading operation status code.
*/
- virtual CANSocket::CANSocketReadSuccess read( struct can_frame& frame, int &bytesRead, unsigned int timeout = 1000);
-
-private:
- /**
- * @internal
- */
- virtual bool createSocket();
- virtual bool enableCANErrors(can_err_mask_t errorMask);
- virtual bool locateInterfaceIndex(struct ifreq& ifr);
- virtual bool bindSocket(struct sockaddr_can &addr);
- virtual bool closeSocket();
- virtual int waitData(unsigned int timeout);
- virtual ssize_t writeFrame(const struct can_frame &frame);
- virtual ssize_t readFrame(struct can_frame& frame);
-
-private:
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
/**
- * Socket file descriptor.
- * @property mSocket
- * @private
- */
- int mSocket;
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
/**
- * Data structure describing a polling request.
- * @property mPoll
- * @private
- */
- struct pollfd mPoll;
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
};
#endif // CANSOCKET_H
diff --git a/plugins/common/cansocketadapter.cpp b/plugins/common/cansocketadapter.cpp
index c2e660b7..3395038b 100644
--- a/plugins/common/cansocketadapter.cpp
+++ b/plugins/common/cansocketadapter.cpp
@@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "canobserver.h"
#include "cansocketreader.h"
#include "logger.h"
+#include "cansocketbcm.h"
+#include "cansocketraw.h"
// TODO: handle socket errors
@@ -76,8 +78,8 @@ bool CANSocketAdapter::sendFrame(const can_frame& frame)
LOG_TRACE("");
if(mSocket) {
- int bytesWritten(0);
- return mSocket->write(frame, bytesWritten);
+ CANFrameInfo message(frame);
+ return mSocket->write(message);
}
return false;
}
@@ -85,8 +87,23 @@ bool CANSocketAdapter::sendFrame(const can_frame& frame)
void CANSocketAdapter::init()
{
if(!mSocket)
- mSocket = new CANSocket();
+ mSocket = new CANSocketBCM();
if(!mReader)
mReader = new CANSocketReader(mObserver, *mSocket);
}
+bool CANSocketAdapter::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
+{
+ if(mSocket)
+ return mSocket->registerCyclicMessageForReceive(canId, minCycleTime, maxCycleTime);
+ else
+ return false;
+}
+
+bool CANSocketAdapter::unregisterMessageForReceive(int canId)
+{
+ if(mSocket)
+ return mSocket->unregisterMessageForReceive(canId);
+ else
+ return false;
+}
diff --git a/plugins/common/cansocketadapter.h b/plugins/common/cansocketadapter.h
index 350563ce..811d26a7 100644
--- a/plugins/common/cansocketadapter.h
+++ b/plugins/common/cansocketadapter.h
@@ -63,6 +63,22 @@ public:
* @return True if frame was sent
*/
virtual bool sendFrame(const can_frame& frame);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
protected:
/**
diff --git a/plugins/common/cansocketbcm.cpp b/plugins/common/cansocketbcm.cpp
new file mode 100644
index 00000000..d923ce3e
--- /dev/null
+++ b/plugins/common/cansocketbcm.cpp
@@ -0,0 +1,279 @@
+/*
+Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <timestamp.h>
+#include "logger.h"
+#include "cansocketbcm.h"
+#include "timestamp.h"
+
+CANSocketBCM::CANSocketBCM() :
+ mSocket(-1)
+{
+ LOG_TRACE("");
+}
+
+bool CANSocketBCM::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0)
+ return false;
+
+ if(!createSocket())
+ {
+ LOG_ERROR("Socket error");
+ return false;
+ }
+
+ // can_err_mask_t errorMask = 0xFFFFFFFF;
+ // if(!enableCANErrors(errorMask)) {
+ // LOG_ERROR("Socket error");
+ // return false;
+ // }
+
+ mPoll.fd = mSocket;
+ mPoll.events = POLLIN | POLLPRI;
+
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ifName);
+ if(!locateInterfaceIndex(ifr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ return false;
+ }
+
+ struct sockaddr_can addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+ if(!connectSocket(addr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ return false;
+ }
+
+ return true;
+}
+
+void CANSocketBCM::stop()
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0) {
+ closeSocket();
+ mSocket = -1;
+ }
+}
+
+bool CANSocketBCM::write(const struct CANFrameInfo &message)
+{
+ LOG_TRACE("");
+
+ return writeFrameOneTime(message.frame);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketBCM::read(struct CANFrameInfo& message, unsigned int timeout)
+{
+ LOG_TRACE("timeout: " << timeout);
+
+ CANSocket::CANSocketReadSuccess success;
+ memset(&message, 0, sizeof(message));
+
+ switch(waitData(timeout)) {
+ case -1:
+ LOG_ERROR("reading error");
+ success = CANSocket::READING_FAILED;
+ break;
+ case 0:
+ success = CANSocket::READING_TIMED_OUT;
+ break;
+ default:
+ success = readMessage(message);
+ break;
+ }
+
+ return success;
+}
+
+bool CANSocketBCM::createSocket()
+{
+ return ((mSocket = ::socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) >= 0);
+}
+
+bool CANSocketBCM::locateInterfaceIndex(struct ifreq& ifr)
+{
+ return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
+}
+
+bool CANSocketBCM::connectSocket(struct sockaddr_can& addr)
+{
+ return (::connect(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+}
+
+bool CANSocketBCM::closeSocket()
+{
+ return (::close(mSocket) == 0);
+}
+
+int CANSocketBCM::waitData(unsigned int timeout)
+{
+ return ::poll(&mPoll, 1, timeout);
+}
+
+/**
+ * BCM header with one message.
+ * @note hdr.nframes must always be 0 or 1.
+ */
+struct __attribute__ ((__packed__)) bcm_msg_one{
+ struct bcm_msg_head hdr;
+ struct can_frame frames[1];
+};
+
+bool CANSocketBCM::writeFrameOneTime(const can_frame& frame)
+{
+ struct bcm_msg_one bcms;
+
+ // fill in the header
+ memset(&bcms.hdr, 0, sizeof(bcms.hdr));
+ bcms.hdr.opcode = TX_SEND;
+ bcms.hdr.nframes = 1;
+ bcms.hdr.can_id = frame.can_id;
+
+ // copy the frame
+ memcpy(&bcms.frames[0], &frame, sizeof(frame));
+
+ // and write everything
+ ssize_t nbytes = ::write(mSocket, &bcms, sizeof(bcms));
+ return nbytes == sizeof(bcms);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketBCM::readMessage(CANFrameInfo& message)
+{
+ struct bcm_msg_one bcms;
+
+ // clear the destination
+ memset(&message, 0, sizeof(message));
+
+ // get data from socket
+ size_t nbytes = ::recv(mSocket, &bcms, sizeof(bcms), 0);
+ if ( nbytes < sizeof(bcms.hdr))
+ {
+ LOG_ERROR("Socket error");
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+ //TODO: implement better timestamps
+ message.timestamp = amb::currentTime();
+
+ switch (bcms.hdr.opcode)
+ {
+ case RX_CHANGED:
+ if (bcms.hdr.nframes >= 1 && nbytes == sizeof(bcms))
+ {
+ if (bcms.hdr.nframes > 1)
+ {
+ LOG_WARNING("Dropped " << bcms.hdr.nframes - 1 << " updates from CAN bus.");
+ }
+
+ // copy the first frame
+ memcpy(&message.frame, &bcms.frames[0], sizeof(bcms.frames[0]));
+ message.status = CANFrameInfo::CANMessageStatus::GOOD;
+ return CANSocket::CANSocketReadSuccess::READING_SUCCEEDED;
+ }
+ else
+ {
+ LOG_ERROR("Unexpected data from the socket"
+ << " " << bcms.hdr.opcode
+ << " " << bcms.hdr.nframes
+ << " " << nbytes);
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+ case RX_TIMEOUT:
+ memcpy(&message.frame, &bcms.frames[0], sizeof(bcms.frames[0]));
+ message.frame.can_id = bcms.hdr.can_id; //doubtful. Do we need to override this?
+ message.status = CANFrameInfo::CANMessageStatus::TIMEOUT;
+ return CANSocket::CANSocketReadSuccess::READING_SUCCEEDED;
+
+ case TX_EXPIRED:
+ // do nothing
+ return CANSocket::CANSocketReadSuccess::READING_TIMED_OUT;
+
+ default:
+ LOG_ERROR("Unexpected opcode " << bcms.hdr.opcode);
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+}
+
+/*
+ 4.2.5 Broadcast Manager receive filter timers
+
+ The timer values ival1 or ival2 may be set to non-zero values at RX_SETUP.
+ When the SET_TIMER flag is set the timers are enabled:
+
+ ival1: Send RX_TIMEOUT when a received message is not received again within
+ the given time. When START_TIMER is set at RX_SETUP the timeout detection
+ is activated directly - even without a former CAN frame reception.
+
+ ival2: Throttle the received message rate down to the value of ival2. This
+ is useful to reduce messages for the application when the signal inside the
+ CAN frame is stateless as state changes within the ival2 periode may get
+ lost.
+*/
+
+bool CANSocketBCM::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
+{
+ struct bcm_msg_head hdr;
+
+ // fill in the header
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.opcode = RX_SETUP;
+ // set RX_FILTER_ID | RX_CHECK_DLC because we don't differentiate messages by dlc or content yet. Only by id
+ // setting RX_ANNOUNCE_RESUME may lead to duplicates in data which should be filtered by amb core.
+ // However, we won't miss any data.
+ hdr.flags = RX_FILTER_ID | RX_CHECK_DLC | SETTIMER | STARTTIMER | RX_ANNOUNCE_RESUME;
+ hdr.nframes = 0;
+ hdr.can_id = canId;
+ hdr.ival1 = amb::Timestamp::toTimeval(maxCycleTime);
+ hdr.ival2 = amb::Timestamp::toTimeval(minCycleTime);
+
+ // and write
+ ssize_t nbytes = ::write(mSocket, &hdr, sizeof(hdr));
+ return nbytes == sizeof(hdr);
+}
+
+bool CANSocketBCM::unregisterMessageForReceive(int canId)
+{
+ struct bcm_msg_head hdr;
+
+ // fill in the header
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.opcode = RX_DELETE;
+ hdr.can_id = canId;
+
+ // and write
+ ssize_t nbytes = ::write(mSocket, &hdr, sizeof(hdr));
+ return nbytes == sizeof(hdr);
+}
+
diff --git a/plugins/common/cansocketbcm.h b/plugins/common/cansocketbcm.h
new file mode 100644
index 00000000..f5403bfc
--- /dev/null
+++ b/plugins/common/cansocketbcm.h
@@ -0,0 +1,122 @@
+/*
+Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKETBCM_H
+#define CANSOCKETBCM_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <net/if.h>
+#include <sys/poll.h>
+#include <string>
+#include <stdlib.h>
+#include <linux/can/bcm.h>
+#include <linux/can/raw.h>
+
+#include "cansocket.h"
+
+/**
+* \brief CAN Socket wrapper.
+* @class CANSocket
+*/
+class CANSocketBCM : public CANSocket
+{
+public:
+ CANSocketBCM();
+ virtual ~CANSocketBCM(){} /*LCOV_EXCL_LINE*/
+
+ /**
+ * Opens and initialize CAN socket
+ * @fn start
+ * @param ifName Name of the CAN bus network interface.
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Writes CAN frame using the socket
+ * @fn write
+ * @param message CAN frame with additional information
+ * @param bytesWritten Number of written bytes.
+ * @return True if no error occurs.
+ */
+ virtual bool write(const struct CANFrameInfo &message);
+ /**
+ * Try to read CAN frame
+ * @fn read
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
+ * @return Reading operation status code.
+ */
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Unregisters CAN ID for receiving
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
+
+private:
+ /**
+ * @internal
+ */
+ bool createSocket();
+ bool locateInterfaceIndex(struct ifreq& ifr);
+ bool connectSocket(struct sockaddr_can& addr);
+ bool closeSocket();
+ int waitData(unsigned int timeout);
+ bool writeFrameOneTime(const can_frame& frame);
+ CANSocket::CANSocketReadSuccess readMessage(CANFrameInfo& message);
+
+private:
+ /**
+ * Socket file descriptor.
+ * @property mSocket
+ * @private
+ */
+ int mSocket;
+ /**
+ * Data structure describing a polling request.
+ * @property mPoll
+ * @private
+ */
+ struct pollfd mPoll;
+};
+
+#endif // CANSOCKETBCM_H
+
+/** @} */
diff --git a/plugins/common/cansocketraw.cpp b/plugins/common/cansocketraw.cpp
new file mode 100644
index 00000000..2ab5d4f7
--- /dev/null
+++ b/plugins/common/cansocketraw.cpp
@@ -0,0 +1,199 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "logger.h"
+#include "cansocket.h"
+#include "cansocketraw.h"
+#include "timestamp.h"
+
+CANSocketRaw::CANSocketRaw() :
+ mSocket(-1)
+{
+ LOG_TRACE("");
+}
+
+bool CANSocketRaw::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(mSocket < 0) {
+ if(!createSocket()) {
+ LOG_ERROR("Socket error");
+ } else {
+ can_err_mask_t errorMask = 0xFFFFFFFF;
+ if(!enableCANErrors(errorMask)) {
+ LOG_ERROR("Socket error");
+ } else
+ if(!enableTimestamps()) {
+ LOG_ERROR("Socket error");
+ } else {
+ mPoll.fd = mSocket;
+ mPoll.events = POLLIN | POLLPRI;
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ifName);
+ if(!locateInterfaceIndex(ifr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ struct sockaddr_can addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+ if(!bindSocket(addr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void CANSocketRaw::stop()
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0) {
+ closeSocket();
+ mSocket = -1;
+ }
+}
+
+bool CANSocketRaw::write(const struct CANFrameInfo &message)
+{
+ LOG_TRACE("");
+
+ return writeFrame(message.frame);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketRaw::read(struct CANFrameInfo& message, unsigned int timeout)
+{
+ LOG_TRACE("timeout: " << timeout);
+
+ CANSocket::CANSocketReadSuccess success;
+ memset(&message, 0, sizeof(message));
+
+ switch(waitData(timeout)) {
+ case -1:
+ LOG_ERROR("reading error");
+ success = CANSocket::READING_FAILED;
+ break;
+ case 0:
+ success = CANSocket::READING_TIMED_OUT;
+ break;
+ default:
+ ssize_t nbytes = (int)readFrame(message.frame, message.timestamp);
+ message.status = CANFrameInfo::CANMessageStatus::GOOD;
+ success = nbytes > 0 ? CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
+ }
+
+ return success;
+}
+
+bool CANSocketRaw::createSocket()
+{
+ return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
+}
+
+bool CANSocketRaw::enableTimestamps()
+{
+ const int timestamp = 1;
+
+ return (setsockopt(mSocket, SOL_SOCKET, SO_TIMESTAMP, &timestamp, sizeof(timestamp)) == 0);
+}
+
+bool CANSocketRaw::enableCANErrors(can_err_mask_t errorMask)
+{
+ return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
+}
+
+bool CANSocketRaw::locateInterfaceIndex(struct ifreq& ifr)
+{
+ return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
+}
+
+bool CANSocketRaw::bindSocket(struct sockaddr_can& addr)
+{
+ return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+}
+
+bool CANSocketRaw::closeSocket()
+{
+ return (::close(mSocket) == 0);
+}
+
+int CANSocketRaw::waitData(unsigned int timeout)
+{
+ return ::poll(&mPoll, 1, timeout);
+}
+
+bool CANSocketRaw::writeFrame(const can_frame& frame)
+{
+ return ::write(mSocket, &frame, sizeof(frame)) == sizeof(frame);
+}
+
+ssize_t CANSocketRaw::readFrame(can_frame& frame, double &timestamp)
+{
+ struct iovec io;
+ struct msghdr msgh;
+ struct cmsghdr *cmsg;
+
+ // prepare buffers
+ memset(&msgh, 0, sizeof(msgh));
+ io.iov_base=&frame;
+ io.iov_len=sizeof(can_frame);
+ msgh.msg_iov=&io;
+ msgh.msg_iovlen=1;
+ char buffer[1024];
+ msgh.msg_control=&buffer;
+ msgh.msg_controllen=sizeof(buffer);
+
+ // receive data
+ ssize_t nbytes = ::recvmsg(mSocket, &msgh, 0);
+
+ if (nbytes > 0 )
+ {
+ /* Receive auxiliary data in msgh */
+ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+ if (cmsg->cmsg_type == SO_TIMESTAMP) {
+ struct ::timeval *tv = (struct timeval*) CMSG_DATA(cmsg);
+
+ // convert the timestamp
+ timestamp = amb::Timestamp::fromTimeval(*tv);
+
+ break;
+ }
+ }
+ if (cmsg == NULL) {
+ /* No timestamp is provided by the socket. Use our own. */
+ timestamp = amb::Timestamp::instance()->epochTime();
+ }
+ }
+
+ return nbytes;
+}
diff --git a/plugins/common/cansocketraw.h b/plugins/common/cansocketraw.h
new file mode 100644
index 00000000..aca053df
--- /dev/null
+++ b/plugins/common/cansocketraw.h
@@ -0,0 +1,103 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKETRAW_H
+#define CANSOCKETRAW_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <net/if.h>
+#include <sys/poll.h>
+#include <string>
+#include <linux/can/raw.h>
+
+#include "cansocket.h"
+
+/**
+* \brief CAN Socket wrapper.
+* @class CANSocket
+*/
+class CANSocketRaw : public CANSocket
+{
+public:
+ CANSocketRaw();
+ virtual ~CANSocketRaw(){} /*LCOV_EXCL_LINE*/
+
+ /**
+ * Opens and initializes CAN socket
+ * @fn start
+ * @param ifName Name of the CAN bus network interface.
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Writes CAN frame using the socket
+ * @fn write
+ * @param message CAN frame with additional information
+ * @return True if no error occurs.
+ */
+ virtual bool write(const struct CANFrameInfo &message);
+ /**
+ * Try to read CAN frame
+ * @fn read
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
+ * @return Reading operation status code.
+ */
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
+
+private:
+ /**
+ * @internal
+ */
+ bool createSocket();
+ bool enableCANErrors(can_err_mask_t errorMask);
+ bool enableTimestamps();
+ bool locateInterfaceIndex(struct ifreq& ifr);
+ bool bindSocket(struct sockaddr_can &addr);
+ bool closeSocket();
+ int waitData(unsigned int timeout);
+ bool writeFrame(const struct can_frame &frame);
+ ssize_t readFrame(can_frame& frame, double &timestamp);
+
+private:
+ /**
+ * Socket file descriptor.
+ * @property mSocket
+ * @private
+ */
+ int mSocket;
+ /**
+ * Data structure describing a polling request.
+ * @property mPoll
+ * @private
+ */
+ struct pollfd mPoll;
+};
+
+#endif // CANSOCKETRAW_H
+
+/** @} */
diff --git a/plugins/common/cansocketreader.cpp b/plugins/common/cansocketreader.cpp
index a9663e7f..e5bb42e8 100644
--- a/plugins/common/cansocketreader.cpp
+++ b/plugins/common/cansocketreader.cpp
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -38,7 +40,11 @@ bool CANSocketReader::start()
{
LOG_TRACE("");
- return CUtil::Thread::start();
+ bool res = CUtil::Thread::start();
+
+ // try to set higher priority
+ if (res) res = setPriority(4);
+ return res;
}
void CANSocketReader::stop()
@@ -55,41 +61,71 @@ void CANSocketReader::run()
while(isRunnable()) {
- struct can_frame frame;
- int bytesRead;
+ CANFrameInfo message;
+ CANSocket::CANSocketReadSuccess success = mSocket.read(message);
+
+ switch(success)
+ {
+ case CANSocket::READING_SUCCEEDED:
+ dispatchMessage(message);
+ break;
- CANSocket::CANSocketReadSuccess success = mSocket.read(frame, bytesRead);
+ case CANSocket::READING_TIMED_OUT:
+ // read again
+ break;
- switch(success) {
case CANSocket::READING_FAILED:
+ default:
LOG_ERROR("reading failed");
mObserver.errorOccured(CANObserver::GENERAL_ERROR);
- return;
- case CANSocket::READING_TIMED_OUT:
- // read again
break;
- default: //CANSocketWrapper::READING_SUCCEEDED
- if(frame.can_id & CAN_ERR_FLAG) {
- frame.can_id &= (CAN_ERR_FLAG|CAN_ERR_MASK);
- mObserver.errorFrameReceived(frame);
- }
- else if(frame.can_id & CAN_RTR_FLAG){
- if(!(frame.can_id & CAN_EFF_FLAG)){
- frame.can_id &= CAN_SFF_MASK;
- }
- else{
- frame.can_id &= (~CAN_RTR_FLAG);
- }
- mObserver.remoteTransmissionRequest(frame);
- }
- else if(frame.can_id & CAN_EFF_FLAG){
- frame.can_id &= CAN_EFF_MASK;
- mObserver.extendedFrameReceived(frame);
+ }
+ }
+}
+
+void CANSocketReader::dispatchMessage(const CANFrameInfo &message)
+{
+ struct can_frame frame = message.frame;
+
+ switch (message.status)
+ {
+ case CANFrameInfo::CANMessageStatus::GOOD:
+ if(frame.can_id & CAN_ERR_FLAG) {
+ frame.can_id &= (CAN_ERR_FLAG|CAN_ERR_MASK);
+ mObserver.errorFrameReceived(frame);
+ }
+ else if( frame.can_id & CAN_RTR_FLAG){
+ if(!( frame.can_id & CAN_EFF_FLAG)){
+ frame.can_id &= CAN_SFF_MASK;
}
else{
- frame.can_id &= CAN_SFF_MASK;
- mObserver.standardFrameReceived(frame);
+ frame.can_id &= (~CAN_RTR_FLAG);
}
+ mObserver.remoteTransmissionRequest(frame);
}
+ else if(frame.can_id & CAN_EFF_FLAG){
+ frame.can_id &= CAN_EFF_MASK;
+ mObserver.extendedFrameReceived(frame);
+ }
+ else{
+ frame.can_id &= CAN_SFF_MASK;
+ mObserver.standardFrameReceived(frame);
+ }
+ break;
+
+ case CANFrameInfo::CANMessageStatus::TIMEOUT:
+ if(frame.can_id & CAN_EFF_FLAG)
+ frame.can_id &= CAN_EFF_MASK;
+ else
+ frame.can_id &= CAN_SFF_MASK;
+
+ mObserver.timeoutDetected(frame);
+ break;
+
+ default:
+ LOG_ERROR("Unexpected CAN message status " << message.status);
+ mObserver.errorOccured(CANObserver::GENERAL_ERROR);
+ break;
}
}
+
diff --git a/plugins/common/cansocketreader.h b/plugins/common/cansocketreader.h
index 623430ae..62d7ead7 100644
--- a/plugins/common/cansocketreader.h
+++ b/plugins/common/cansocketreader.h
@@ -66,6 +66,13 @@ private:
*/
virtual void run();
+ /**
+ * Proceseses CAN message received from SocketCAN and notifies mObserver.
+ * @fn dispatchMessage
+ * @param message CAN message to be processed. Unchanged.
+ */
+ virtual void dispatchMessage(const CANFrameInfo &message);
+
private:
/**
* #CANObserver instance reference
diff --git a/plugins/common/thread.cpp b/plugins/common/thread.cpp
index d9d9c999..504feb38 100644
--- a/plugins/common/thread.cpp
+++ b/plugins/common/thread.cpp
@@ -52,9 +52,9 @@ static void *PosixThreadProc(void *param)
thread->run();
gMutex.lock();
- --gActiveThreadCount;
- LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
- gMutex.unlock();
+ --gActiveThreadCount;
+ LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
+ gMutex.unlock();
return 0;
}
@@ -64,59 +64,84 @@ namespace CUtil{
////////////////////////////////////////////////
Thread::Thread() :
- thread(0),
- runnableFlag(false)
+ thread(0),
+ runnableFlag(false)
{
- pthread_cond_init( &cond, NULL );
- pthread_mutex_init( &mutex, NULL );
+ pthread_cond_init( &cond, NULL );
+ pthread_mutex_init( &mutex, NULL );
}
bool Thread::start()
{
- pthread_mutex_lock(&mutex);
- if (runnableFlag) {// already running
- pthread_mutex_unlock(&mutex);
- return false;
- }
- // try to run
- if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
+ pthread_mutex_lock(&mutex);
+ if (runnableFlag) {// already running
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+ // try to run
+ if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
//pthread_attr_destroy(&thread_attr);
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
return false;
}
//pthread_attr_destroy(&thread_attr);
- runnableFlag = true;
- pthread_mutex_unlock(&mutex);
+ runnableFlag = true;
+ pthread_mutex_unlock(&mutex);
+ return true;
+}
+
+
+bool Thread::setPriority(int priority)
+{
+ pthread_mutex_lock(&mutex);
+ if (!runnableFlag) {// not running yet or terminated already
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+
+ priority = priority < 1 ? 1 : priority;
+ priority = priority < 99 ? priority : 99;
+
+ // set priority
+ struct sched_param pr;
+ pr.__sched_priority = priority;
+ if (pthread_setschedparam(thread, SCHED_FIFO, &pr) < 0)
+ {
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+
+ pthread_mutex_unlock(&mutex);
return true;
}
Thread::~Thread()
{
stop();
- pthread_cond_destroy( &cond );
- pthread_mutex_destroy( &mutex );
- thread = 0;
+ pthread_cond_destroy( &cond );
+ pthread_mutex_destroy( &mutex );
+ thread = 0;
}
void Thread::stop()
{
if (setRunnableFlag(false) == true) {
- if( thread != 0 ){
- if (thread == pthread_self()){
- int s = pthread_detach(thread);
- ((void)s);// prevent compiler warning in RELEASE build
- LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
- }
- else{
- int s = pthread_join(thread, NULL);
- if (s != 0){
- LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
- }
- else{
- LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
- }
- }
- thread = 0;
+ if( thread != 0 ){
+ if (thread == pthread_self()){
+ int s = pthread_detach(thread);
+ ((void)s);// prevent compiler warning in RELEASE build
+ LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
+ }
+ else{
+ int s = pthread_join(thread, NULL);
+ if (s != 0){
+ LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ else{
+ LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ }
+ thread = 0;
}
}
return;
@@ -124,44 +149,44 @@ void Thread::stop()
bool Thread::setRunnableFlag(bool flag)
{
- pthread_mutex_lock(&mutex);
- bool retval(runnableFlag);
- runnableFlag = flag;
-
- if(!runnableFlag)
- pthread_cond_signal(&cond);
- pthread_mutex_unlock(&mutex);
- return retval;
+ pthread_mutex_lock(&mutex);
+ bool retval(runnableFlag);
+ runnableFlag = flag;
+
+ if(!runnableFlag)
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&mutex);
+ return retval;
}
bool Thread::isRunnable(long miliseconds)
{
- bool runnable(false);
+ bool runnable(false);
- pthread_mutex_lock(&mutex);
- if (miliseconds != 0){
- wait(miliseconds);
- }
- runnable = runnableFlag;
+ pthread_mutex_lock(&mutex);
+ if (miliseconds != 0){
+ wait(miliseconds);
+ }
+ runnable = runnableFlag;
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
return runnable;
}
bool Thread::wait( long miliseconds )
{
- struct timespec abstime;
- clock_gettime(CLOCK_REALTIME, &abstime);
- abstime.tv_sec += ( miliseconds / 1000 );
- miliseconds %= 1000;
- abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
- if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
- abstime.tv_sec += 1; // +1s
- abstime.tv_nsec -= 1000000000L; // -1s
- }
-
- int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
- return ( status == ETIMEDOUT );
+ struct timespec abstime;
+ clock_gettime(CLOCK_REALTIME, &abstime);
+ abstime.tv_sec += ( miliseconds / 1000 );
+ miliseconds %= 1000;
+ abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
+ if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
+ abstime.tv_sec += 1; // +1s
+ abstime.tv_nsec -= 1000000000L; // -1s
+ }
+
+ int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
+ return ( status == ETIMEDOUT );
}
}
diff --git a/plugins/common/thread.h b/plugins/common/thread.h
index 8879b5b4..7bc26f21 100644
--- a/plugins/common/thread.h
+++ b/plugins/common/thread.h
@@ -127,6 +127,15 @@ public:
virtual bool start();
/**
+ * Sets the priority of the thread for FIFO scheduling.
+ * @fn set_priority
+ * @param priority Integer ranging from 1 (lowest) to 99 (highest).
+ * @return True if the operation was successful.
+ * @public
+ */
+ bool setPriority(int priority);
+
+ /**
* Stops the thread
* @fn stop
* @public
diff --git a/plugins/dbus/dbusinterfacemanager.cpp b/plugins/dbus/dbusinterfacemanager.cpp
index 4006d50a..b556fd14 100644
--- a/plugins/dbus/dbusinterfacemanager.cpp
+++ b/plugins/dbus/dbusinterfacemanager.cpp
@@ -51,7 +51,7 @@ on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_d
{
DBusInterfaceManager* iface = static_cast<DBusInterfaceManager*>(user_data);
- iface->connection = std::shared_ptr<GDBusConnection>(connection, [=](auto conn){
+ iface->connection = std::shared_ptr<GDBusConnection>(connection, [=](GDBusConnection* conn){
amb::traits<GDBusConnection>::delete_functor functor;
functor(conn);
});
diff --git a/tools/AmbSignalMapper/Makefile.PL b/tools/AmbSignalMapper/Makefile.PL
index bae450ee..b2b5952f 100644
--- a/tools/AmbSignalMapper/Makefile.PL
+++ b/tools/AmbSignalMapper/Makefile.PL
@@ -33,7 +33,7 @@ WriteMakefile(
'Digest::SHA1'=>0,
#'Config::General'=>0,
},
- EXE_FILES => [ 'bin/dbc2json','bin/json2amb'],
+ EXE_FILES => [ 'bin/dbc2json','bin/json2amb', 'bin/dbc2amb' ],
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
clean => { FILES => 'AmbSignalMapper-*' },
);
@@ -54,10 +54,11 @@ sub MY::postamble {
# Compile the RecDescent grammar during make;
sub compile_DbcGrammar {
push(@EXCLUSIONS,'blib/lib/Intel/IviPoc/DbcGrammar');
+ push(@EXCLUSIONS,'blib/lib/Intel/IviPoc/MsgGrammar');
$MORE_MAKERULES .= <<'MakeGrammar';
# Precompile the (Recursive Descent) DbcGrammar
-pure_all :: $(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm
+pure_all :: $(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm $(INST_LIBDIR)/Intel/IviPoc/MsgGrammar.pm
$(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm: lib/Intel/IviPoc/DbcGrammar
$(PERLRUN) -MParse::RecDescent - lib/Intel/IviPoc/DbcGrammar Intel::IviPoc::DbcGrammar
@@ -66,6 +67,12 @@ $(INST_LIBDIR)/Intel/IviPoc/DbcGrammar.pm: lib/Intel/IviPoc/DbcGrammar
$(CHMOD) $(PERM_RWX) bin/dbc2json
$(CHMOD) $(PERM_RWX) bin/json2amb
+$(INST_LIBDIR)/Intel/IviPoc/MsgGrammar.pm: lib/Intel/IviPoc/MsgGrammar
+ $(PERLRUN) -MParse::RecDescent - lib/Intel/IviPoc/MsgGrammar Intel::IviPoc::MsgGrammar
+ $(NOECHO) $(MKPATH) $(INST_LIBDIR)/Intel/IviPoc
+ $(MV) -f MsgGrammar.pm blib/lib/Intel/IviPoc/MsgGrammar.pm
+ $(CHMOD) $(PERM_RWX) bin/dbc2amb
+
MakeGrammar
}
diff --git a/tools/AmbSignalMapper/README b/tools/AmbSignalMapper/README
index 42907f5c..af5de91f 100644
--- a/tools/AmbSignalMapper/README
+++ b/tools/AmbSignalMapper/README
@@ -1,8 +1,14 @@
AmbSignalMapper
+===============
ABSTRACT:
The AmbSignalMapper tool serves basic utilities for AMB signal mapping process.
+Two workflows exist: a classic workflow with an intermediate file and a "direct"
+workflow with an *.msg file.
+
+Classic Workflow
+----------------
It should take place in three steps:
1. Vector CANdb++ conversion into intermediate file (First phase)
@@ -13,6 +19,27 @@ The First phase is achieved by software utolity called dbc2json.
The second phase needs to be done by humans manually.
The third phase is again covered by software utolity called json2amb.
+Direct Workflow
+---------------
+This workflow is designed for generation of production code. It consists of three steps:
+1. Obtain a *.dbc file
+2. Prepare a special *.msg message definition file
+3. Generate AMB plugin by running
+ dbc2amb I<dbc file> I<msg file> I<outdir> I<plugin name>
+
+*.msg file contains message definitions marked by the keyword B<RECEIVE>. Messages can be
+selected by name "Message1" or by id with b<@> prefix "@141". An asterisk can be specified
+instead of the list of signals to select all signals.
+
+ RECEIVE Message1 {
+ Signal1
+ }
+
+ RECEIVE Message2.Signal2;
+
+ RECEIVE @141.*;
+
+
PREREQUISITES:
Perl version 5.006 or higher.
@@ -56,6 +83,8 @@ perldoc command.
perldoc json2amb
+ perldoc dbc2amb
+
LICENSE AND COPYRIGHT
Copyright (C) 2014 Intel Corporation
diff --git a/tools/AmbSignalMapper/TODO b/tools/AmbSignalMapper/TODO
new file mode 100644
index 00000000..3504b81b
--- /dev/null
+++ b/tools/AmbSignalMapper/TODO
@@ -0,0 +1,2 @@
+- get CycleTime for the message from *.dbc file
+
diff --git a/tools/AmbSignalMapper/bin/dbc2amb b/tools/AmbSignalMapper/bin/dbc2amb
new file mode 100755
index 00000000..a6b0bbca
--- /dev/null
+++ b/tools/AmbSignalMapper/bin/dbc2amb
@@ -0,0 +1,295 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2014 Intel Corporation
+# Copyright (c) 2015 Cogent Embedded Inc.
+# Copyright (C) 2015 Renesas Electronics Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+use strict;
+use warnings;
+
+use warnings FATAL => 'all';
+
+use Intel::IviPoc::DbcGrammar;
+use Intel::IviPoc::MsgGrammar;
+use Intel::IviPoc::AmbCommon;
+use Intel::IviPoc::AmbPluginGenerator qw(processPlugin);
+use File::Basename;
+use File::Spec;
+use Cwd;
+use Data::Dumper;
+
+=head1 NAME
+
+dbc2amb - Vector CANdb++ to Automotive Message Broker plugin generator.
+
+=head1 SYNOPSIS
+
+B<dbc2amb> I<dbc file> I<msg file> [ I<outdir> [I<plugin name>] ]
+
+=head1 DESCRIPTION
+
+Part of Automotive Message Broker Signal Mapper tool.
+
+B<dbc2amb> converts file in Vector CANdb++ format to Automotive Message Broker plugin.
+
+=head1 OPTIONS
+
+=over 4
+
+=item I<dbc file>
+
+Input I<dbc file> file in Vector CANdb++ (*.dbc) format.
+
+"-" (without quotes) can be specified instead of I<dbc file> to omit *.dbc file.
+
+=item I<msg file>
+
+Input I<msg file> file with message definitions.
+
+=item [ I<outdir> ]
+
+This parameter is optional. Target directory where the plugin is generated to.
+Otherwise current directory.
+
+=item [ I<plugin name> ]
+
+Machine- and user- readable name of the plugin. Plugin code will be exported to
+B<I<outdir>>/BI<plugin name>_plugin> directory
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=back
+
+=head1 REQUIRES
+
+Perl 5.006, Intel::IviPoc::DbcGrammar, Intel::IviPoc::MsgGrammar, Intel::IviPoc::AmbPluginGenerator, Intel::IviPoc::AmbCommon, File::Basename, File::Spec, Cwd
+
+=head1 SEE ALSO
+
+perl(1), amb2json(1), json2amb(1)
+
+=cut
+
+local $/;
+
+# get total arg passed to this script
+my $total = $#ARGV + 1;
+
+if ( $total < 2 or $total > 4) {
+ # get script name and print usage
+ my $scriptname = $0;
+ &printUsage($scriptname);
+ exit;
+}
+
+# First parameter is input dbc filename
+my $dbc_inputfilename = $ARGV[0];
+my $dbc_text;
+if ($dbc_inputfilename eq '-') {
+ # use dummy *.dbc file if '-' is specified on command line
+ $dbc_text = "VERSION \"\" \n\n\nNS_ : \n\n\nEMPTY \nBS_: \nBU_: \n ";
+}
+else {
+ $dbc_text = &readFileContent($dbc_inputfilename);
+}
+
+# Second parameter is input msg filename
+my $msg_inputfilename = $ARGV[1];
+my $msg_text = &readFileContent($msg_inputfilename);
+
+# Third optional parameter is output file
+my $targetDir = ();
+if ( $total <= 2 ) {
+ $targetDir = getcwd;
+} else {
+ $targetDir = Cwd::abs_path($ARGV[2]);
+}
+
+# Fourth optional parameter is plugin name
+my $pluginname;
+if ( $total <= 2 ) {
+ my ($infilename, $indirectories, $insuffix) = fileparse($dbc_inputfilename, qr/\.[^.]*/);
+ $pluginname = $infilename;
+} else {
+ $pluginname = $ARGV[3];
+}
+
+# We add one space to dbc file if there is something like ""ReceiverId to get "" ReceiverId
+$dbc_text =~ s/"(.*)"(\w*)/"$1" $2/g;
+
+#Create parsers
+my $dbc_parser = new Intel::IviPoc::DbcGrammar;
+my $msg_parser = new Intel::IviPoc::MsgGrammar;
+
+# Print wait info for user
+&printWait($dbc_inputfilename, $msg_inputfilename, $targetDir);
+
+# Parse input files
+my $dbc_result;
+$dbc_result = $dbc_parser->DbcOutput($dbc_text);
+my $msg_result;
+$msg_result = $msg_parser->MsgOutput($msg_text);
+# print Dumper $msg_result; #TODO: Remove debug print
+
+# Generate the plugin
+my $selected_signals = selectSignals($dbc_result, $msg_result, "CAN");
+$selected_signals->{'pluginName'} = $pluginname;
+#print Dumper $selected_signals; #TODO: remove this after debugging is complete
+my $hashingAllowed = 'D';
+
+processPlugin ( $hashingAllowed, $selected_signals, $targetDir );
+
+print "Plugin is generated in '$targetDir'.\n";
+
+# Finnish
+exit;
+
+
+=head2 selectSignals
+
+Select signals for implementing in an AMB plugin.
+
+=cut
+
+sub selectSignals {
+ my %dbc_root = %{$_[0]};
+ my %msg_root = %{$_[1]};
+ my $plugin_name = $_[2];
+
+ my @electronicControlUnits = ();
+ keys $msg_root{'receive'};
+ while( my($msg_id, $signals) = each $msg_root{'receive'}) {
+ for my $ecu (@{$dbc_root{'electronicControlUnits'}}) {
+ my %add_ecu = ();
+
+ for my $message (@{$ecu->{'messages'}}) {
+ if ((lc $msg_id eq lc $message->{'canName'}) or ($msg_id eq $message->{'canId'})) {
+ # selected valid message, add its common properties
+ my %msg_copy = %{$message};
+
+ if (!(exists $signals->{'*'})) {
+ delete $msg_copy{'signals'};
+
+ for my $signal (@{$message->{'signals'}}) {
+ if (exists $signals->{$signal->{'canId'}}) {
+ push(@{$msg_copy{'signals'}}, $signal);
+ }
+ }
+ }
+
+ # select 'cycle' property
+ if (exists $msg_root{'cycle'}->{$msg_id}) {
+ $msg_copy{'cycle'} = $msg_root{'cycle'}->{$msg_id};
+ }
+ else {
+ $msg_copy{'cycle'} = 0;
+ }
+
+ # add message only if not empty
+ if (exists $msg_copy{'signals'}) {
+ push(@{$add_ecu{'messages'}}, \%msg_copy);
+ }
+ }
+ }
+
+ # add signals to the reference
+ if (%add_ecu){
+ push(@electronicControlUnits, \%add_ecu);
+ }
+ }
+ }
+
+ my %jsonroot = ();
+ $jsonroot{'pluginName'} = "pluginName";
+ $jsonroot{'electronicControlUnits'} = \@electronicControlUnits;
+
+ return \%jsonroot;
+}
+
+=head2 printWait
+
+Prints out wait information
+
+=cut
+
+sub printWait {
+ print STDERR ("\n");
+ print STDERR ("Processing input dbc file:\n");
+ print STDERR (" $_[0]\n");
+ print STDERR ("Processing input msg file:\n");
+ print STDERR (" $_[1]\n");
+ print STDERR ("Generating output files is in:\n");
+ print STDERR (" $_[2]\n");
+ print STDERR ("\n");
+ print STDERR ("This operation may take some while. Please wait...\n");
+}
+
+=head2 printUsage
+
+Prints out basic usage help
+
+=cut
+
+sub printUsage {
+ my $scriptname=$_[0];
+ print STDERR ("$scriptname\n");
+ print STDERR ("Usage: dbc2amb in_dbc_file in_msg_file [outdir [plugin_name]]\n");
+ print STDERR (" in_dbc_file Input dbc file. Specify '-' to skip.\n");
+ print STDERR (" in_msg_file Input msg file\n");
+ print STDERR (" outdir Target plugin directory (optional) generated to,\n");
+ print STDERR (" otherwise current directory.\n");
+ print STDERR (" plugin_name Machine-readable name of the plugin\n");
+ print STDERR ("\n");
+}
+
+=head1 AUTHOR
+
+IntelIVIPoc, C<< <ivipoc at intel.com> >>
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc dbc2amb
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 LICENSE AND COPYRIGHT
+
+Copyright (C) 2014 Intel Corporation
+
+Copyright (C) 2015 Cogent Embedded, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+=cut
diff --git a/tools/AmbSignalMapper/bin/dbc2json b/tools/AmbSignalMapper/bin/dbc2json
index e96f8679..453bdf26 100755
--- a/tools/AmbSignalMapper/bin/dbc2json
+++ b/tools/AmbSignalMapper/bin/dbc2json
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
# Copyright (C) 2014 Intel Corporation
#
diff --git a/tools/AmbSignalMapper/bin/json2amb b/tools/AmbSignalMapper/bin/json2amb
index 7e39e988..b785f2ee 100755
--- a/tools/AmbSignalMapper/bin/json2amb
+++ b/tools/AmbSignalMapper/bin/json2amb
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
# Copyright (C) 2014 Intel Corporation
#
@@ -107,8 +107,17 @@ if ($total == 2) {
$targetDir = Cwd::abs_path($ARGV[2]);
}
+# Load the json
+my $json_text = &readFileContent( $ARGV[1] );
+
+my $json = JSON->new;
+$json = $json->utf8;
+
+my $dbcjson = $json->decode( $json_text );
+
+
# Generate the plaugin
-processPlugin ( $hashingAllowed, $ARGV[1], $targetDir );
+processPlugin ( $hashingAllowed, $dbcjson, $targetDir );
# Finnish
exit;
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm
index 4c603099..d4e33d34 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/AmbPluginGenerator.pm
@@ -80,20 +80,13 @@ based on information comming from input JSON file.
=cut
-my $hashingAllowed = 'E'; # Enabled by default
+my $hashingAllowed = 'E'; # Enabled by default
sub processPlugin {
$hashingAllowed = $_[0];
- my $jsonfile = $_[1];
+ my $dbcjson = $_[1];
my $targetDir = $_[2];
-
- # Load the json
- my $json_text = &readFileContent( $jsonfile );
-
- my $json = JSON->new;
- $json = $json->utf8;
-
- my $dbcjson = $json->decode( $json_text );
+
if ($hashingAllowed eq 'E' ) {
&encryptAmbPropertyNames( $dbcjson );
}
@@ -113,6 +106,7 @@ sub processPlugin {
, "ambtmpl_plugin.cpp"
, "ambtmpl_cansignals.h"
, "ambtmpl_plugin.idl"
+ , "ambtmpl.in.json"
);
my @pluginFiles = ( "CMakeLists.txt"
@@ -122,6 +116,7 @@ sub processPlugin {
, lc ($pluginName) . "_plugin.cpp"
, lc ($pluginName) . "_cansignals.h"
, lc ($pluginName) . "_plugin.idl"
+ , lc ($pluginName) . ".in.json"
);
my @generationSubs = ( undef
@@ -131,11 +126,12 @@ sub processPlugin {
, \&generateCppImplTypes
, \&generateSignalsTypes
, \&generateIdlTypes
+ , undef
);
my $templateFile = '';
my $pluginFile = '';
- my ($volume, $directory) = File::Spec->splitpath( $INC{'Intel/IviPoc/AmbPluginGenerator.pm'} );
+ my ($volume, $directory) = File::Spec->splitpath(__FILE__);
for my $i (0..scalar(@pluginFiles)-1) {
# First join templates folder and filename
$templateFile = File::Spec->catfile( ($templatesDir), $templatesFiles[$i] );
@@ -267,7 +263,7 @@ sub generateCppImplTypes {
my @messages = @{$engineControlUnits[$ecui]{'messages'}};
for my $msgi (0..scalar(@messages)-1) {
$hexValue = '0x' . uc ( sprintf( "%x", $messages[$msgi]{'canId'} ) );
- $registerMessageText .= " registerMessage($hexValue, $messages[$msgi]{'canDlc'}";
+ $registerMessageText .= " registerMessage($hexValue, $messages[$msgi]{'canDlc'}, $messages[$msgi]{'cycle'}";
my @signals = @{$messages[$msgi]{'signals'}};
foreach my $signal ( @signals ) {
@@ -275,7 +271,7 @@ sub generateCppImplTypes {
$registerMessageText .= &generateCppProperty( $signal, $type);
}
- $registerMessageText .= "\n );\n";
+ $registerMessageText .= "\n );\n";
}
}
}
@@ -303,9 +299,9 @@ sub generateCppProperty {
# TODO CANSignal needs to take zone as argument
#my $zone = 'Zone::None';
#if ($zonesInUse) {
- # $zone = &calculateZone( $ambPropertyName );
+ # $zone = &calculateZone( $ambPropertyName );
#}
- $generatedText .= "\n , new ${ambPropertyName}Type()";
+ $generatedText .= "\n , new ${ambPropertyName}Type()";
}
return $generatedText;
}
@@ -382,7 +378,7 @@ sub generateEnumOrValues {
# Generate enum values
for my $vali (0..scalar(@values) -1 ) {
$hexValue = '0x' . uc ( sprintf( "%x", $values[$vali]->{'value'} ) );
- $generatedText .= " $values[$vali]->{'name'} = $hexValue";
+ $generatedText .= " $values[$vali]->{'name'} = $hexValue";
if ($vali != scalar(@values)-1 ) {
$generatedText .= ",";
}
@@ -427,16 +423,16 @@ sub generatePropertyClasses {
$ambPropertyName = $signal->{'AMBPropertyName'};
}
- my $byteOrdering = "Endian::Intel"; # LittleEndian by default
+ my $byteOrdering = "Endian::Intel"; # LittleEndian by default
if ( exists( $signal->{'byteOrdering'} ) and $signal->{'byteOrdering'} eq '0') {
- $byteOrdering = "Endian::Motorola"; # BigEndian
+ $byteOrdering = "Endian::Motorola"; # BigEndian
}
my $signedness;
if ($signal->{'signedness'} eq '+') {
- $signedness = "Signedness::Unsigned"; # Unsigned
+ $signedness = "Signedness::Unsigned"; # Unsigned
} else {
- $signedness = "Signedness::Signed"; # Signed
+ $signedness = "Signedness::Signed"; # Signed
}
my $convertFromFunction = "nullptr";
@@ -479,7 +475,7 @@ sub generatePropertyClasses {
} else {
$cppType = "int";
}
- } else { # (u)int16, (u)int64
+ } else { # (u)int16, (u)int64
$cppType = "$type";
}
@@ -552,15 +548,15 @@ sub generateIdlProperty {
for my $vali (0..scalar(@values) -1 ) {
# TODO const unsigned short migth be not enough, guess type based on values
$hexValue = '0x' . uc (sprintf( "%x", $values[$vali]->{'value'} ) );
- $generatedText .= " const unsigned short " . uc($values[$vali]->{'name'}) . " = $hexValue;\n";
+ $generatedText .= " const unsigned short " . uc($values[$vali]->{'name'}) . " = $hexValue;\n";
}
}
}
$generatedText .= "\n";
- $generatedText .= " /** ${ambPropertyName}\n";
- $generatedText .= " * \\brief Returns ${ambPropertyName}\n";
- $generatedText .= " **/\n";
+ $generatedText .= " /** ${ambPropertyName}\n";
+ $generatedText .= " * \\brief Returns ${ambPropertyName}\n";
+ $generatedText .= " **/\n";
my $unsigned = '';
if ( $type =~ m/uint/ ) {
@@ -569,17 +565,17 @@ sub generateIdlProperty {
if ( $type =~ m/enum/ ) {
# TODO const unsigned short migth be not enough, guess type based on values
- $generatedText .= " readonly attribute octet ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute octet ${ambPropertyName};\n";
} elsif ( $type =~ m/bool/ ) {
- $generatedText .= " readonly attribute boolean ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute boolean ${ambPropertyName};\n";
} elsif ( $type =~ m/int8/ ) {
- $generatedText .= " readonly attribute ${unsigned}octet ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute ${unsigned}octet ${ambPropertyName};\n";
} elsif ( $type =~ m/int16/ ) {
- $generatedText .= " readonly attribute ${unsigned}short ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute ${unsigned}short ${ambPropertyName};\n";
} elsif ( $type =~ m/int32/ ) {
- $generatedText .= " readonly attribute ${unsigned}long ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute ${unsigned}long ${ambPropertyName};\n";
} else {
- $generatedText .= " readonly attribute double ${ambPropertyName};\n";
+ $generatedText .= " readonly attribute double ${ambPropertyName};\n";
}
$generatedText .= "};\n\n";
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar
index 80e6164e..1f977c5c 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/DbcGrammar
@@ -1,4 +1,5 @@
#Copyright (C) 2014 Intel Corporation
+#Copyright (c) 2015 Cogent Embedded Inc.
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
@@ -19,6 +20,12 @@
my @ecuList = ();
my %ecuMessages = ();
my %ecuValues = ();
+ my %enumValues = ();
+ my %messageSenders = ();
+ my $fileComment = '';
+ my %ecuComments = ();
+ my %messageComments = ();
+ my %signalComments = ();
}
DbcOutput: Line(s?) eofile
@@ -75,32 +82,90 @@ Line: CommentPrefix /.*\n/
# Not needed to output anything yet
| 'VERSION' DoubleQuotedId
# Not needed to output anything yet
+ # Version can be empty like this ""
| 'NS_' ':' NSList(s?) ...'BS_'
+ # this tag holds a list of "new symbols" for the file
+ # Not needed to output anything
+ | 'BS_' ':'
+ # This tag holds definition of bit timings, obsolete
+ # Not need to output anything
+ | 'BU_' ':' <skip:'[ \t]*'> Identifier(s?)
{
- # We just read the list of NSs
- @networks = @{$item[3]};
+ # This tag holds the list of ECUs in one line
+ @ecuList = @{$item[4]};
}
- | 'BS_' /.*\n/
- # Not needed to output anything yet
- | 'BU_' ':' EcuList(s?) ...'BO_'
- {
- @ecuList = @{$item[3]};
- }
- | 'BO_' Number Identifier ':' Identifier Identifier Signal(s?)
+ | 'BO_' Integer Identifier ':' Identifier Identifier Signal(s?)
{
my %msg = ();
$msg{'canId'} = $item[2];
$msg{'canName'} = $item[3];
$msg{'canDlc'} = $item[5];
- $msg{'canMessageId'} = $item[6];
+ $msg{'canEcuId'} = $item[6];
$msg{'signals'} = $item[7];
push ( @{$ecuMessages{$item[6]}}, \%msg );
}
| 'VAL_' Number Identifier ValuePair(s?) ';'
{
+ # This tag holds enums defined for specific messages
${$ecuValues{$item[2]}->{$item[3]}} = $item[4];
}
+ | 'VAL_TABLE_' Identifier ValuePair(s?) ';'
+ {
+ # This tag holds predefined enumerations
+ ${$enumValues{$item[2]}} = $item[3];
+ }
+ | 'BO_TX_BU_' Number ':' Receiver(s /,/) ';'
+ {
+ # This tag defines message senders
+ @{$messageSenders{$item[2]}} = $item[4];
+ }
+ | 'CM_' DoubleQuotedId ';'
+ {
+ # This tag is a comment for the whole file
+ $fileComment = $item[2];
+ }
+ | 'CM_' 'BU_' Identifier DoubleQuotedId ';'
+ {
+ # This tag is a comment for an ECU
+ ${$ecuComments{$item[3]}} = $item[4];
+ }
+ | 'CM_' 'BO_' Identifier DoubleQuotedId ';'
+ {
+ # This tag is a comment for a message
+ ${$messageComments{$item[3]}} = $item[4];
+ }
+ | 'CM_' 'SG_' Number Identifier DoubleQuotedId ';'
+ {
+ # This tag is a comment for a signal
+ ${$signalComments{$item[3]}->{$item[4]}} = $item[5];
+ }
+ | 'BA_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_DEF_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_DEF_DEF_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_REL_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_DEF_REL_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_DEF_DEF_REL_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_SGTYPE_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'BA_DEF_SGTYPE_' /.*;/
+ # This tag is an attribute definition
+ # Not needed to output anything yet
+ | 'SIG_GROUP_' Number Identifier Number ':' Identifier(s) ';'
+ # This tag is a signal group definition
| <error: Invalid dbc format at $thisline!>
Signal: 'SG_' Identifier ':' DataPlacement FactorOffset Range DoubleQuotedId Receiver(s /,/)
@@ -109,7 +174,7 @@ Signal: 'SG_' Identifier ':' DataPlacement FactorOffset Range DoubleQuotedId Rec
$signal{'canId'} = $item[2];
my %placement = %{$item[4]};
- $signal{'startbit'} = $placement{'startbit'};
+ $signal{'startBit'} = $placement{'startbit'};
$signal{'length'} = $placement{'length'};
$signal{'byteOrdering'} = $placement{'byteOrdering'};
$signal{'signedness'} = $placement{'signedness'};
@@ -133,11 +198,6 @@ Signal: 'SG_' Identifier ':' DataPlacement FactorOffset Range DoubleQuotedId Rec
$return=\%signal;
}
-EcuList: ...!'BO_' Identifier
- {
- $return = $item[2];
- }
-
NSList: ...!'BS_' Identifier
{
$return = $item[2];
@@ -209,10 +269,13 @@ Identifier: /[A-Za-z0-9_\-]+/
$return = $item[1];
}
-Number: /[-+]?[0-9]*/
+Number: Integer | RealNumber | Sign
+
+Integer: /[-+]?[0-9]*/
RealNumber: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
Sign: /^[-+]?/
CommentPrefix: /^\/\//
DoubleQuotation: "\""
+
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/MsgGrammar b/tools/AmbSignalMapper/lib/Intel/IviPoc/MsgGrammar
new file mode 100644
index 00000000..eaf30511
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/MsgGrammar
@@ -0,0 +1,129 @@
+#Copyright (c) 2015 Cogent Embedded Inc.
+#Copyright (C) 2015 Renesas Electronics Corporation
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+{
+ my @receive = ();
+ my @send = ();
+}
+
+MsgOutput: Line(s?) eofile
+ {
+ my %rcv_msg = ();
+ my %cycle_msg = ();
+ my %send_msg = ();
+
+ for my $msg (@receive) {
+ my %m = %{$msg};
+
+ for my $signal (@{$m{'signals'}}) {
+ $rcv_msg{$m{'id'}}->{$signal} += 1;
+ }
+
+ if (exists $m{'cycle'}) {
+ $cycle_msg{$m{'id'}} = $m{'cycle'} / 1000.0;
+ }
+
+ }
+
+ my %picked = ();
+ $picked{'receive'} = \%rcv_msg;
+ $picked{'cycle'} = \%cycle_msg;
+ $picked{'send'} = \%send_msg;
+
+ return \%picked;
+ }
+
+eofile: /^\Z/
+
+Line: CommentPrefix /.*\n/
+ # Not needed to output anything yet
+ | 'RECEIVE' MessageSpec
+ {
+ # select the message for receiving
+ push(@receive, $item[2]);
+ }
+ | 'SEND' MessageSpec
+ {
+ # select the message for sending
+ push(@send, $item[2]);
+ }
+ | <error: Invalid msg format at $thisline!>
+
+MessageSpec: MessageId '.' SignalId MessageProperties ';'
+ {
+ my %msg;
+ $msg{'id'} = $item[1];
+ @{$msg{'signals'}} = $item[3];
+ for my $p (@{$item[4]}) {
+ $msg{lc($p->{'name'})} = $p->{'value'};
+ }
+ $return = \%msg;
+ }
+ | MessageId MessageProperties '{' SignalId(s? /,/) '}'
+ {
+ my %msg;
+ $msg{'id'} = $item[1];
+ $msg{'signals'} = $item[4];
+ for my $p (@{$item[2]}) {
+ $msg{lc($p->{'name'})} = $p->{'value'};
+ }
+ $return = \%msg;
+ }
+
+MessageId: Identifier
+ {
+ # Message is selected by name
+ $return = $item[1];
+ }
+ | '@' Integer
+ {
+ # Message is selected by id
+ $return = $item[2];
+ }
+
+MessageProperties: MessageProperty(s?)
+
+MessageProperty: Identifier '=' Value
+ {
+ # property of the message
+ my %prop;
+ $prop{'name'} = $item[1];
+ $prop{'value'} = $item[3];
+ $return = \%prop;
+ }
+
+SignalId: Identifier|'*'
+
+Identifier: /[A-Za-z0-9_\-]+/
+ {
+ $return = $item[1];
+ }
+
+Value: Number | String
+
+Number: Integer | RealNumber | Sign
+
+Integer: /[-+]?[0-9]*/
+RealNumber: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/
+Sign: /^[-+]?/
+
+CommentPrefix: '#'
+
+DoubleQuotation: "\""
+
+String: /\"[^\"]*\"/
+
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt
index 6d392eed..f5bfee92 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/CMakeLists.txt
@@ -1,19 +1,27 @@
cmake_minimum_required(VERSION 2.8)
-set( CMAKE_VERBOSE_MAKEFILE on )
+set(CMAKE_VERBOSE_MAKEFILE on )
+set(PLUGIN_SEGMENT_INSTALL_PATH "/etc/ambd/plugins.d")
+set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/${CMAKE_LIBRARY_ARCHITECTURE}" )
+set(PLUGIN_INSTALL_PATH "${LIB_INSTALL_DIR}/automotive-message-broker")
# to install plugin into /usr instead of /usr/local
set (CMAKE_INSTALL_PREFIX /usr)
-IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
+# check that CAN interface is specified and use vcan0 by default
+if(NOT DEFINED ${DEFAULT_CAN_INTERFACE})
+ set(DEFAULT_CAN_INTERFACE "vcan0")
+endif(NOT DEFINED ${DEFAULT_CAN_INTERFACE})
+
+if(CMAKE_BUILD_TYPE MATCHES DEBUG)
message("debug mode")
+else(CMAKE_BUILD_TYPE MATCHES DEBUG)
+ # default is RELEASE mode
+ message("release mode, no logger")
+ add_definitions(-D_LOGGER_NO_LOG)
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
-IF(CMAKE_BUILD_TYPE MATCHES RELEASE)
- message("release mode")
- add_definitions(-D_LOGGER_NO_LOG)
-ENDIF(CMAKE_BUILD_TYPE MATCHES RELEASE)
-
include(FindPkgConfig)
find_package(Boost REQUIRED)
@@ -21,7 +29,7 @@ find_package(Boost REQUIRED)
pkg_check_modules(glib REQUIRED glib-2.0)
pkg_check_modules(json REQUIRED json)
-add_definitions(-std=gnu++0x -fPIC -fPIE)
+add_definitions(-std=gnu++0x)
pkg_check_modules( amb REQUIRED automotive-message-broker )
pkg_check_modules( amb-plugins-common REQUIRED amb-plugins-common )
@@ -31,6 +39,8 @@ include_directories(${include_dirs} ${amb-plugins-common_INCLUDE_DIRS} ${amb_INC
set(ambtmpl_plugin_headers ambtmpl_plugin.h ambtmpl_cansignals.h ambtmpl_cansignal.h)
set(ambtmpl_plugin_sources ambtmpl_plugin.cpp ambtmpl_cansignal.cpp)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ambtmpl.in.json ${CMAKE_CURRENT_BINARY_DIR}/ambtmpl @ONLY)
+
if(ivipoc_tests)
#########################################
# ivipoc_tests START
@@ -63,6 +73,7 @@ add_library(ambtmpl_plugin MODULE ${ambtmpl_plugin_sources} ${ambtmpl_plugin_hea
set_target_properties(ambtmpl_plugin PROPERTIES PREFIX "")
target_link_libraries(ambtmpl_plugin ${link_libraries} ${libamb_LIBRARY} ${amb_LIBRARIES} ${amb-plugins-common_LIBRARIES})
-install(TARGETS ambtmpl_plugin LIBRARY DESTINATION lib/automotive-message-broker)
+install(TARGETS ambtmpl_plugin LIBRARY DESTINATION "lib/automotive-message-broker")
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ambtmpl DESTINATION ${PLUGIN_SEGMENT_INSTALL_PATH})
+
-############################################################################################################################################
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl.in.json b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl.in.json
new file mode 100644
index 00000000..15cdea99
--- /dev/null
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl.in.json
@@ -0,0 +1,7 @@
+{
+ "name" : "AmbTmpl",
+ "path" : "@PLUGIN_INSTALL_PATH@/ambtmpl_plugin.so",
+ "frequency" : "10",
+ "enabled" : true,
+ "interface" : "@DEFAULT_CAN_INTERFACE@"
+}
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
index b44f36ef..cd4b6d34 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.cpp
@@ -84,6 +84,18 @@ void CANSignal::onMessage(const can_frame& frame, std::function<void (AbstractPr
}
}
+void CANSignal::onTimeout(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
+{
+ //TODO: implement <no-value> handling
+/* if (ambProperty->toString() != "none") {
+ ambProperty->setValue("none");
+ if(changeCallback)
+ changeCallback(ambProperty.get());
+ }
+*/
+}
+
+
void CANSignal::setAmbProperty(std::shared_ptr<AbstractPropertyType> ambProperty)
{
this->ambProperty = ambProperty;
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
index 2ea563fd..1201c3fb 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_cansignal.h
@@ -97,6 +97,7 @@ public:
virtual GVariant *processSignal( const can_frame& frame ) = 0;
virtual void onMessage( const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback );
+ virtual void onTimeout( const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback );
virtual bool updateFrame( can_frame* frame );
@@ -145,9 +146,10 @@ class CANMessage
public:
CANMessage() = delete;
- CANMessage(canid_t canId, __u8 canDlc) :
+ CANMessage(canid_t canId, __u8 canDlc, double CycleTime) :
canId(canId),
- canDlc(canDlc)
+ canDlc(canDlc),
+ CycleTime(CycleTime)
{
}
@@ -159,6 +161,7 @@ public:
void onMessage(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
{
+ // sanity check
if(frame.can_dlc != canDlc || frame.can_id != canId)
return;
@@ -171,6 +174,21 @@ public:
}
}
+ void onTimeout(const can_frame& frame, std::function<void (AbstractPropertyType*)> changeCallback)
+ {
+ // sanity check
+ if(frame.can_id != canId)
+ return;
+
+ for ( auto it = canSignals.begin(); it != canSignals.end(); ++it ) {
+ std::shared_ptr<CANSignal> signal(it->second);
+
+ if ( signal ) {
+ signal->onTimeout(frame, changeCallback);
+ }
+ }
+ }
+
void setupFrame(can_frame* frame)
{
if(!frame)
@@ -185,9 +203,15 @@ public:
}
}
+ bool registerOnCANBus(CANBus& canBus)
+ {
+ return canBus.registerCyclicMessageForReceive(canId, 0, CycleTime);
+ }
+
private:
canid_t canId;
__u8 canDlc;
+ double CycleTime;
std::map< VehicleProperty::Property , std::shared_ptr<CANSignal> > canSignals;
};
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
index 6f412742..3353c705 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.cpp
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <logger.h>
+#include <canbusimpl.h>
#include "ambtmpl_plugin.h"
#include "ambtmpl_cansignals.h"
@@ -81,10 +82,10 @@ gboolean AmbTmplPlugin::timeoutCallback(gpointer data)
// AmbTmplPlugin
//----------------------------------------------------------------------------
-AmbTmplPlugin::AmbTmplPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSink& parent) :
+AmbTmplPlugin::AmbTmplPlugin(AbstractRoutingEngine* re, const map<string, string>& config, AbstractSource& parent) :
AmbPluginImpl(re, config, parent),
interface(DEFAULT_CAN_IF_NAME),
- canBus(new CANBus(*static_cast<CANObserver*>(this))),
+ canBus(new CANBusImpl(*static_cast<CANObserver*>(this))),
announcementIntervalTimer(1000),
announcementCount(20)
{
@@ -125,6 +126,11 @@ AmbTmplPlugin::~AmbTmplPlugin()
void AmbTmplPlugin::init()
{
canBus->start(interface.c_str());
+
+ for(auto iter = messages.begin(); iter != messages.end(); iter++) {
+ if (!iter->second.registerOnCANBus(*canBus))
+ LOG_ERROR("Cannot register a message with can_id=0x" << std::hex << iter->first);
+ }
}
AsyncPropertyReply *AmbTmplPlugin::setProperty(const AsyncSetPropertyRequest& request )
@@ -176,6 +182,18 @@ void AmbTmplPlugin::onMessage(const can_frame& frame)
message.onMessage( frame, [&re, &guid](AbstractPropertyType* value){re->updateProperty(value, guid);} );
}
+void AmbTmplPlugin::onTimeout(const can_frame& frame)
+{
+ auto messageIt = messages.find(frame.can_id);
+ if(messageIt == messages.end())
+ return;
+
+ CANMessage& message(messageIt->second);
+ const std::string guid = uuid();
+ AbstractRoutingEngine* re = routingEngine;
+ message.onTimeout( frame, [&re, &guid](AbstractPropertyType* value){re->updateProperty(value, guid);} );
+}
+
bool AmbTmplPlugin::sendValue(AbstractPropertyType* value)
{
if(!value)
@@ -214,6 +232,14 @@ void AmbTmplPlugin::extendedFrameReceived(const can_frame& frame)
onMessage(frame);
}
+void AmbTmplPlugin::timeoutDetected(const can_frame& frame)
+{
+ LOG_INFO("testPlugin::timeoutDetected()");
+ printFrame( frame );
+
+ onTimeout(frame);
+}
+
void AmbTmplPlugin::errorFrameReceived(const can_frame& frame)
{
LOG_INFO("AmbTmplPlugin::errorFrameReceived()");
diff --git a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h
index 9e22f554..2ce3b582 100644
--- a/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h
+++ b/tools/AmbSignalMapper/lib/Intel/IviPoc/templates/ambtmpl_plugin.h
@@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <canbus.h>
#include <canobserver.h>
+#include <ambplugin.h>
#include <ambpluginimpl.h>
#include "ambtmpl_cansignal.h"
@@ -42,7 +43,7 @@ class CANMessage;
class AmbTmplPlugin : public AmbPluginImpl, public CANObserver {
public:
- AmbTmplPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSink& parent);
+ AmbTmplPlugin(AbstractRoutingEngine* re, const std::map<std::string, std::string>& config, AbstractSource& parent);
virtual ~AmbTmplPlugin(); // has to be virtual because of unit tests
// from AbstractSink
@@ -116,6 +117,12 @@ public:
* \return True if frame was sent
*/
bool sendExtendedFrame(const can_frame& frame);
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame);
/*!
* Second phase of the plugin initialization.
@@ -134,15 +141,15 @@ public:
protected:
- void registerMessage(const canid_t& canId, const __u8& canDlc)
+ void registerMessage(const canid_t& canId, const __u8& canDlc, const double CycleTime)
{
LOG_MESSAGE("registered message: " << canId);
}
template<typename Signal, typename... Rest>
- void registerMessage(const canid_t& canId, const __u8& canDlc, Signal* canSignal, Rest... rest)
+ void registerMessage(const canid_t& canId, const __u8& canDlc, const double CycleTime, Signal* canSignal, Rest... rest)
{
- static_assert(std::is_base_of<CANSignal, Signal>::value, "CANSignal has to be a base of Signal");
+ static_assert(std::is_base_of<CANSignal, Signal>::value, "CANSignal has to be a base class of Signal");
if(!canSignal)
return;
@@ -152,20 +159,21 @@ protected:
canSignal->setAmbProperty(prop);
auto messageIt = messages.find(canId);
if(messageIt == messages.end()){
- messageIt = messages.insert(make_pair(canId, CANMessage(canId, canDlc))).first;
+ messageIt = messages.insert(make_pair(canId, CANMessage(canId, canDlc, CycleTime))).first;
}
auto& message = messageIt->second;
message.addSignal(prop->name, std::shared_ptr<CANSignal>(canSignal));
propertyToMessage[prop->name] = &message;
}
- registerMessage(canId, canDlc, rest...);
+ registerMessage(canId, canDlc, CycleTime, rest...);
}
private:
void printFrame(const can_frame& frame) const;
void onMessage(const can_frame& frame);
+ void onTimeout(const can_frame& frame);
bool sendValue(AbstractPropertyType* value);
void registerMessages();
diff --git a/tools/AmbSignalMapper/t/syntax.msg b/tools/AmbSignalMapper/t/syntax.msg
new file mode 100644
index 00000000..391b2171
--- /dev/null
+++ b/tools/AmbSignalMapper/t/syntax.msg
@@ -0,0 +1,45 @@
+# Test file for Msg grammar
+#
+#Copyright (c) 2015 Cogent Embedded Inc.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#Lesser General Public License for more details.
+#
+#You should have received a copy of the GNU Lesser General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+# Pick one signal from message
+RECEIVE @1.Signal1;
+
+# Pick all signals from another message
+RECEIVE @2.*;
+
+RECEIVE Message1.Signal1;
+
+# pick multiple signals
+RECEIVE Message1 {
+ Signal1
+}
+
+RECEIVE @4 {
+ Signal1
+}
+
+RECEIVE @3 {
+ Signal1,
+ Signal2
+}
+
+RECEIVE @2 {
+ Signal1,
+ Signal2
+}
+