LCOV - code coverage report
Current view: top level - src - actuators.c (source / functions) Coverage Total Hit
Test: combined.info Lines: 95.2 % 42 40
Test Date: 2025-05-05 14:46:49 Functions: 100.0 % 3 3
Branches: 90.9 % 11 10
MC/DC: 87.5 % 8 7

             Branch data      MC/DC data    Line data    Source code
       1                 :              :             : /**
       2                 :              :             :  * @file controller.c
       3                 :              :             :  * @brief Controller module responsible for managing actuator logic through message queue handling.
       4                 :              :             :  * 
       5                 :              :             :  * This module handles the reception and processing of CAN messages related to actuators via POSIX
       6                 :              :             :  * message queues. It spawns a separate thread to continuously read incoming messages, update the 
       7                 :              :             :  * internal state of the actuators accordingly, and log each event for traceability and diagnostics.
       8                 :              :             :  */
       9                 :              :             : 
      10                 :              :             : #include <stdio.h>
      11                 :              :             : #include <stdlib.h>
      12                 :              :             : #include <unistd.h>
      13                 :              :             : #include <mqueue.h>
      14                 :              :             : #include <stdbool.h>
      15                 :              :             : #include <pthread.h>
      16                 :              :             : #include "mq_utils.h"
      17                 :              :             : #include "constants.h"
      18                 :              :             : #include "actuators.h"
      19                 :              :             : #include "dbc.h"
      20                 :              :             : #include "log_utils.h"
      21                 :              :             : 
      22                 :              :             : #define LOOP_EMPTY_ITERATIONS_MAX 11
      23                 :              :             : 
      24                 :              :             : void *actuatorsResponseLoop(void *arg);
      25                 :              :             : void actuatorsTranslateCanMsg(can_msg captured_frame);
      26                 :              :             : void updateInternalActuatorsState(can_msg captured_frame);
      27                 :              :             : 
      28                 :              :             : mqd_t actuators_mq;
      29                 :              :             : pthread_t actuators_id;
      30                 :              :             : 
      31                 :              :             : actuators_abstraction actuators_state = {
      32                 :              :             :     .belt_tightness = false,
      33                 :              :             :     .door_lock = true,
      34                 :              :             :     .should_activate_abs = false,
      35                 :              :             :     .alarm_led = false,
      36                 :              :             :     .alarm_buzzer = false};
      37                 :              :             : 
      38                 :              :             : can_msg captured_can_frame = {
      39                 :              :             :     .identifier = 0x0CFFB027,
      40                 :              :             :     .dataFrame = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
      41                 :              :             : 
      42                 :              :             : 
      43                 :              :             : //Workaround to avoid the main function in this file
      44                 :              :             : // Write just the main function in the test file
      45                 :              :             : //Put the #ifndef TEST_MODE in the test file, as bellow
      46                 :              :             : //After the last line of main, put #endif
      47                 :              :             : 
      48                 :              :             : //The next step is put the flag TEST_MODE in the Makefile
      49                 :              :             : //See the example:
      50                 :              :             : //      $(CC) $(CFLAGS) -DTEST_MODE test/test_actuators.c src/actuators.c test/unity.c -o test/test_actuators -Iinc -Itest -lpthread
      51                 :              :             : //Put the flag TEST_MODE in the Makefile: -DTEST_MODE
      52                 :              :             : #ifndef TEST_MODE 
      53                 :              :             : int main()
      54                 :              :             : {
      55                 :              :             :     actuators_mq = open_mq(ACTUATORS_MQ);
      56                 :              :             : 
      57                 :              :             :     int actuators_thread;
      58                 :              :             :     actuators_thread = pthread_create(&actuators_id, NULL, actuatorsResponseLoop, NULL);
      59                 :              :             :     if (actuators_thread != 0)
      60                 :              :             :     {
      61                 :              :             :         perror("Actuators: it wasn't possible to create the associated thread\n");
      62                 :              :             :         exit(54);
      63                 :              :             :     }
      64                 :              :             :     actuators_thread = pthread_join(actuators_id, NULL);
      65                 :              :             : 
      66                 :              :             :     return 0;
      67                 :              :             : }
      68                 :              :             : #endif 
      69                 :              :             : 
      70                 :              :             : 
      71                 :              :             : /**
      72                 :              :             :  * @brief Main loop for processing actuator messages.
      73                 :              :             :  *
      74                 :              :             :  * This function runs in a separate thread and continuously reads messages from the actuators message queue.
      75                 :              :             :  * It processes each message to update the internal state of the actuators and logs the event.
      76                 :              :             :  * If the message queue is empty for a specified number of iterations (`LOOP_EMPTY_ITERATIONS_MAX`), 
      77                 :              :             :  * the loop exits, signaling that no more messages are expected.
      78                 :              :             :  *
      79                 :              :             :  * @param arg Unused parameter (can be NULL).
      80                 :              :             :  * @return NULL
      81                 :              :             :  *
      82                 :              :             :  * @details
      83                 :              :             :  * - Reads messages from the `actuators_mq` message queue using `read_mq`.
      84                 :              :             :  * - If a message is successfully read, it resets the `empty_mq_counter` and processes the message using `actuatorsTranslateCanMsg`.
      85                 :              :             :  * - If the queue is empty, increments the `empty_mq_counter`.
      86                 :              :             :  * - Logs each processed message using `log_event`, including the current state of the actuators.
      87                 :              :             :  * - Waits for 200 milliseconds between iterations using `usleep`.
      88                 :              :             :  * - Exits the loop and prints a message when the `empty_mq_counter` reaches `LOOP_EMPTY_ITERATIONS_MAX`.
      89                 :              :             :  *
      90                 :              :             :  * Implements [SwR-4](@ref SwR-4)
      91                 :              :             :  * 
      92                 :              :             :  * \anchor actuatorsResponseLoop
      93                 :              :             :  */
      94                 :              :           1 : void *actuatorsResponseLoop(void *arg)
      95                 :              :             : {
      96                 :              :           1 :     int empty_mq_counter = 0;
      97         [ +  - ]:      [ T  f ]:           5 :     while (empty_mq_counter < LOOP_EMPTY_ITERATIONS_MAX)
      98                 :              :             :     {
      99         [ +  + ]:      [ T  F ]:           5 :         if (read_mq(actuators_mq, &captured_can_frame) != -1)
     100                 :              :             :         {
     101                 :              :           2 :             empty_mq_counter = 0;
     102                 :              :           2 :             actuatorsTranslateCanMsg(captured_can_frame);
     103                 :              :             :         }
     104                 :              :             :         else
     105                 :              :             :         {
     106                 :              :           3 :             empty_mq_counter++;
     107                 :              :             :         }
     108                 :              :             : 
     109                 :              :           5 :         uint32_t event_id = captured_can_frame.identifier; 
     110                 :              :             : 
     111                 :              :           5 :         log_event("AEB1", event_id, actuators_state); // [SwR-4]
     112                 :              :             : 
     113                 :              :             : 
     114                 :              :           5 :         usleep(200000); // Deprected, change for function other later
     115                 :              :             :     }
     116                 :              :             : 
     117                 :              :           0 :     printf("Actuators: empty_mq_counter reached the limit, exiting\n");
     118                 :              :           0 :     return NULL;
     119                 :              :             : }
     120                 :              :             : 
     121                 :              :             : /**
     122                 :              :             :  * @brief Translates a CAN message into actuator commands.
     123                 :              :             :  *
     124                 :              :             :  * This function processes a captured CAN message and determines the appropriate action
     125                 :              :             :  * based on the message's identifier. It updates the actuators' internal state or logs
     126                 :              :             :  * a warning if the message identifier is unknown.
     127                 :              :             :  *
     128                 :              :             :  * @param captured_frame The captured CAN message to be processed.
     129                 :              :             :  * 
     130                 :              :             :  * \anchor actuatorsTranslateCanMsg
     131                 :              :             :  *
     132                 :              :             :  * @details
     133                 :              :             :  * - If the identifier is `ID_AEB_S`, the function calls `updateInternalActuatorsState` to update
     134                 :              :             :  *   the actuators' internal state based on the message's data.
     135                 :              :             :  * - If the identifier is `ID_EMPTY`, the function does nothing, as it represents an empty message.
     136                 :              :             :  * - For any other identifier, the function logs a warning indicating that the identifier is unknown.
     137                 :              :             :  *
     138                 :              :             :  * @note This function is a key part of the actuators module, as it ensures that the actuators' state
     139                 :              :             :  * remains synchronized with the incoming CAN messages.
     140                 :              :             :  *
     141                 :              :             :  * @see updateInternalActuatorsState
     142                 :              :             :  */
     143                 :              :           7 : void actuatorsTranslateCanMsg(can_msg captured_frame)
     144                 :              :             : {
     145      [ +  +  + ]:              :           7 :     switch (captured_frame.identifier)
     146                 :              :             :     {
     147                 :              :           4 :     case ID_AEB_S:
     148                 :              :           4 :         updateInternalActuatorsState(captured_frame);
     149                 :              :           4 :         break;
     150                 :              :           2 :     case ID_EMPTY:
     151                 :              :             :         //printf("Actuators: Empty message received\n");
     152                 :              :           2 :         break;
     153                 :              :           1 :     default:
     154                 :              :           1 :         printf("Actuators: CAN Identifier unknown\n");
     155                 :              :           1 :         break;
     156                 :              :             :     }
     157                 :              :           7 : }
     158                 :              :             : 
     159                 :              :             : /**
     160                 :              :             :  * @brief Updates the internal state of the actuators based on a CAN message.
     161                 :              :             :  *
     162                 :              :             :  * This function processes the data frame of a captured CAN message and updates
     163                 :              :             :  * the internal state of the actuators accordingly. It determines the state of
     164                 :              :             :  * various actuators, such as belt tightness, door lock, ABS activation, alarm LED,
     165                 :              :             :  * and alarm buzzer, based on specific conditions in the message's data frame.
     166                 :              :             :  *
     167                 :              :             :  * @param captured_frame The captured CAN message containing the data to update the actuators' state.
     168                 :              :             :  *
     169                 :              :             :  * @details
     170                 :              :             :  * - If `dataFrame[1] == 0x01`, the function sets the actuators to an active state, enabling
     171                 :              :             :  *   features like belt tightness, ABS activation, and alarms.
     172                 :              :             :  * - If `dataFrame[0] == 0x01`, the function sets the actuators to a partially active state,
     173                 :              :             :  *   enabling some features while disabling others.
     174                 :              :             :  * - For any other values in the data frame, the function sets the actuators to a default
     175                 :              :             :  *   inactive state, disabling all features except the door lock.
     176                 :              :             :  *
     177                 :              :             :  * @note This function is critical for ensuring that the actuators' state reflects the
     178                 :              :             :  *       commands received via CAN messages. It is called by `actuatorsTranslateCanMsg`
     179                 :              :             :  *       when a valid message with the identifier `ID_AEB_S` is received.
     180                 :              :             :  * 
     181                 :              :             : * \anchor updateInternalActuatorsState
     182                 :              :             : 
     183                 :              :             :  *
     184                 :              :             :  * @see actuatorsTranslateCanMsg
     185                 :              :             :  */
     186                 :              :           6 : void updateInternalActuatorsState(can_msg captured_frame)
     187                 :              :             : {
     188         [ +  + ]:      [ T  F ]:           6 :     if (captured_frame.dataFrame[1] == 0x01)
     189                 :              :             :     {
     190                 :              :           4 :         actuators_state.belt_tightness = true;
     191                 :              :           4 :         actuators_state.door_lock = false;
     192                 :              :           4 :         actuators_state.should_activate_abs = true;
     193                 :              :           4 :         actuators_state.alarm_led = true;
     194                 :              :           4 :         actuators_state.alarm_buzzer = true;
     195                 :              :             :     }
     196         [ +  + ]:      [ T  F ]:           2 :     else if (captured_frame.dataFrame[0] == 0x01)
     197                 :              :             :     {
     198                 :              :           1 :         actuators_state.belt_tightness = false;
     199                 :              :           1 :         actuators_state.door_lock = true;
     200                 :              :           1 :         actuators_state.should_activate_abs = false;
     201                 :              :           1 :         actuators_state.alarm_led = true;
     202                 :              :           1 :         actuators_state.alarm_buzzer = true;
     203                 :              :             :     }
     204                 :              :             :     else
     205                 :              :             :     {
     206                 :              :           1 :         actuators_state.belt_tightness = false;
     207                 :              :           1 :         actuators_state.door_lock = true;
     208                 :              :           1 :         actuators_state.should_activate_abs = false;
     209                 :              :           1 :         actuators_state.alarm_led = false;
     210                 :              :           1 :         actuators_state.alarm_buzzer = false;
     211                 :              :             :     }
     212                 :              :           6 : }
        

Generated by: LCOV version 2.3.1-beta