diff options
-rw-r--r-- | can-decoder.cpp | 93 | ||||
-rw-r--r-- | can-decoder.h | 146 | ||||
-rw-r--r-- | low-can-binding.cpp | 22 | ||||
-rw-r--r-- | timer.h | 18 |
4 files changed, 256 insertions, 23 deletions
diff --git a/can-decoder.cpp b/can-decoder.cpp new file mode 100644 index 00000000..000db2ac --- /dev/null +++ b/can-decoder.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015, 2016 "IoT.bzh" + * Author "Romain Forlot" <romain.forlot@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +Decoder::Decoder +{ + decoded_value = { .has_type = false, + .has_numeric_value = false, + .has_boolean_value = false, + .has_string_value = false }; +} + +float Decoder::parseSignalBitfield(CanSignal* signal, const CanMessage* message) +{ + return bitfield_parse_float(message->data, CAN_MESSAGE_SIZE, + signal->bitPosition, signal->bitSize, signal->factor, + signal->offset); +} + +openxc_DynamicField Decoder::noopDecoder(CanSignal* signal, + CanSignal* signals, int signalCount, float value, bool* send) +{ + decoded_value = { .has_type = true, + .type = openxc_DynamicField_Type_NUM, + .has_numeric_value = true, + .numeric_value = value }; + return decoded_value; +} + +openxc_DynamicField Decoder::booleanDecoder(CanSignal* signal, + CanSignal* signals, int signalCount, float value, bool* send) +{ + decoded_value = { .has_type = true, + .type = openxc_DynamicField_Type_BOOL, + .has_boolean_value = true, + .numeric_value = value == 0.0 ? false : true }; + return decoded_value; +} + +openxc_DynamicField Decoder::ignoreDecoder(CanSignal* signal, + CanSignal* signals, int signalCount, float value, bool* send) +{ + *send = false; + openxc_DynamicField decoded_value = {0}; + return decoded_value; +} + +openxc_DynamicField Decoder::stateDecoder(CanSignal* signal, + CanSignal* signals, int signalCount, float value, bool* send) +{ + openxc_DynamicField decoded_value = {0}; + decoded_value.has_type = true; + decoded_value.type = openxc_DynamicField_Type_STRING; + decoded_value.has_string_value = true; + + const CanSignalState* signalState = lookupSignalState(value, signal); + if(signalState != NULL) { + strcpy(decoded_value.string_value, signalState->name); + } else { + *send = false; + } + return decoded_value; +} + +openxc_DynamicField Decoder::decodeSignal(CanSignal* signal, + float value, CanSignal* signals, int signalCount, bool* send) +{ + SignalDecoder decoder = signal->decoder == NULL ? + noopDecoder : signal->decoder; + openxc_DynamicField decoded_value = decoder(signal, signals, + signalCount, value, send); + return decoded_value; +} + +openxc_DynamicField Decoder::decodeSignal(CanSignal* signal, + const CanMessage* message, CanSignal* signals, int signalCount, + bool* send) { + float value = parseSignalBitfield(signal, message); + return decodeSignal(signal, value, signals, signalCount, send); +}
\ No newline at end of file diff --git a/can-decoder.h b/can-decoder.h new file mode 100644 index 00000000..249d5b00 --- /dev/null +++ b/can-decoder.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015, 2016 "IoT.bzh" + * Author "Romain Forlot" <romain.forlot@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + + +class Decoder_c +{ + private: + openxc_DynamicField decoded_value; + + public: + /* Public: Parse the signal's bitfield from the given data and return the raw + * value. + * + * signal - The signal to parse from the data. + * data - The data to parse the signal from. + * length - The length of the data array. + * + * Returns the raw value of the signal parsed as a bitfield from the given byte + * array. + */ + float parseSignalBitfield(CanSignal* signal, const CanMessage* message); + + /* Public: Find and return the corresponding string state for a CAN signal's + * raw integer value. + * + * This is an implementation of the SignalDecoder type signature, and can be + * used directly in the CanSignal.decoder field. + * + * signal - The details of the signal that contains the state mapping. + * signals - The list of all signals. + * signalCount - the length of the signals array. + * value - The numerical value that should map to a state. + * send - An output argument that will be set to false if the value should + * not be sent for any reason. + * + * Returns a DynamicField with a string value if a matching state is found in + * the signal. If an equivalent isn't found, send is sent to false and the + * return value is undefined. + */ + openxc_DynamicField stateDecoder(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send); + + /* Public: Coerces a numerical value to a boolean. + * + * This is an implementation of the SignalDecoder type signature, and can be + * used directly in the CanSignal.decoder field. + * + * signal - The details of the signal that contains the state mapping. + * signals - The list of all signals + * signalCount - The length of the signals array + * value - The numerical value that will be converted to a boolean. + * send - An output argument that will be set to false if the value should + * not be sent for any reason. + * + * Returns a DynamicField with a boolean value of false if the raw signal value + * is 0.0, otherwise true. The 'send' argument will not be modified as this + * decoder always succeeds. + */ + openxc_DynamicField booleanDecoder(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send); + + /* Public: Update the metadata for a signal and the newly received value. + * + * This is an implementation of the SignalDecoder type signature, and can be + * used directly in the CanSignal.decoder field. + * + * This function always flips 'send' to false. + * + * signal - The details of the signal that contains the state mapping. + * signals - The list of all signals. + * signalCount - The length of the signals array. + * value - The numerical value that will be converted to a boolean. + * send - This output argument will always be set to false, so the caller will + * know not to publish this value to the pipeline. + * + * The return value is undefined. + */ + openxc_DynamicField ignoreDecoder(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send); + + /* Public: Wrap a raw CAN signal value in a DynamicField without modification. + * + * This is an implementation of the SignalDecoder type signature, and can be + * used directly in the CanSignal.decoder field. + * + * signal - The details of the signal that contains the state mapping. + * signals - The list of all signals + * signalCount - The length of the signals array + * value - The numerical value that will be wrapped in a DynamicField. + * send - An output argument that will be set to false if the value should + * not be sent for any reason. + * + * Returns a DynamicField with the original, unmodified raw CAN signal value as + * its numeric value. The 'send' argument will not be modified as this decoder + * always succeeds. + */ + openxc_DynamicField noopDecoder(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send); + + /* Public: Parse a signal from a CAN message and apply any required + * transforations to get a human readable value. + * + * If the CanSignal has a non-NULL 'decoder' field, the raw CAN signal value + * will be passed to the decoder before returning. + * + * signal - The details of the signal to decode and forward. + * message - The CAN message that contains the signal. + * signals - an array of all active signals. + * signalCount - The length of the signals array. + * send - An output parameter that will be flipped to false if the value could + * not be decoded. + * + * The decoder returns an openxc_DynamicField, which may contain a number, + * string or boolean. If 'send' is false, the return value is undefined. + */ + openxc_DynamicField decodeSignal(CanSignal* signal, + const CanMessage* message, CanSignal* signals, int signalCount, + bool* send); + + /* Public: Decode a transformed, human readable value from an raw CAN signal + * already parsed from a CAN message. + * + * This is the same as decodeSignal(CanSignal*, CanMessage*, CanSignal*, int, + * bool*) but you must parse the bitfield value of the signal from the CAN + * message yourself. This is useful if you need that raw value for something + * else. + */ + openxc_DynamicField decodeSignal(CanSignal* signal, float value, + CanSignal* signals, int signalCount, bool* send); +}
\ No newline at end of file diff --git a/low-can-binding.cpp b/low-can-binding.cpp index b523e9d1..bb219be2 100644 --- a/low-can-binding.cpp +++ b/low-can-binding.cpp @@ -7,7 +7,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -44,7 +44,7 @@ #include "obd2.h" /* - * Interface between the daemon and the binding + * Interface between the daemon and the binding */ static const struct afb_binding_interface *interface; @@ -84,11 +84,12 @@ static int on_event(sd_event_source *s, int fd, uint32_t revents, void *userdata } /* + * USELESS SINCE THREADS SEPARATION + * * Get the event loop running. * Will trigger on_event function on EPOLLIN event on socket * * Return 0 or positive value on success. Else negative value for failure. - */ static int connect_to_event_loop(CanBus &CanBus_handler) { sd_event *event_loop; @@ -113,6 +114,7 @@ static int connect_to_event_loop(CanBus &CanBus_handler) return rc; } + */ /******************************************************************************** * @@ -156,7 +158,7 @@ static int subscribe_unsubscribe_name(struct afb_req request, int subscribe, con if (0 == strcmp(name, "*")) return subscribe_unsubscribe_all(request, subscribe); - sig = getsig(name); + sig = getSignal(name); if (sig == NULL) { return 0; } @@ -204,8 +206,8 @@ static void unsubscribe(struct afb_req request) } static const struct afb_verb_desc_v1 verbs[]= { - { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." }, - { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." }, + { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info= "subscribe to notification of CAN bus messages." }, + { .name= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info= "unsubscribe a previous subscription." }, {NULL} }; @@ -230,9 +232,7 @@ int afbBindingV1ServiceInit(struct afb_service service) /* Open JSON conf file */ /* Open CAN socket */ - CanBus_t CanBus_handler; + CanBus_c CanBus_handler(interface); CanBus_handler.open(); - CanBus_handler.start_threads(); - - return connect_to_event_loop(CanBus_handler); -}
\ No newline at end of file + CanBus_handler.start_threads(); +} @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,17 +23,11 @@ * * frequency - the clock frequency in Hz. * last_time - the last time (in milliseconds since startup) that the clock - * ticked. + * ticked. * time_function - a function returning current time in ms -typedef struct { - float frequency; - unsigned long lastTick; - TimeFunction timeFunction; -} FrequencyClock; */ - -class FrequencyClock_c { - private: +typedef struct { float frequency; - unsigned long last_tick; -}
\ No newline at end of file + unsigned long lastTick; + TimeFunction timeFunction; +} FrequencyClock; |