This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

WMBus StackForce serial T2 collector stack receiving encrypted SND-NR frames

Part Number: WMBUS
Other Parts Discussed in Thread: CC1310

Hello all,

I am working on a product that needs to receive WMBus measurements. We have a working prototype using the two processor solution where the main processor talks with the CC1310 running the image supplied by TI Serial_CC13xx_Collector_T2 from https://www.ti.com/tool/WMBUS.

We got a version to work that can communicate with the StackForce SATP commands by adding a meter to the internal meter list with its address and encryption key. Now we want to look into receiving the encrypted frames and doing decryption ourselves to meet a customer requirement. In SATP there is the command SATP_APL_COL_ATTRIBUTE_SET_PROPERTY, with this command we enable Enhanced installation mode. In this mode we receive the indication SATP_APL_COL_INDICATION_NEW_METER. We are receiving the SATP_APL_COL_INDICATION_NEW_METER at the same frequency we were receiving the SATP_APL_COL_INDICATION_RX before when we were doing decryption in the SATP stack with the expected meter addresses.

So far so good, the problem now is that we don't get enough bytes in the SATP_APL_COL_INDICATION_NEW_METER indication to use AES on. When we parse the TPL header received it seems a valid WMBus frame TPL header with an control information field of `0x7A`, an encryption mode of 5 and 4 encrypted blocks. 4 encrypted blocks should mean that the payload is 64 bytes, the amount of payload left in the SATP frame is 59 bytes. We have this problem for both meters we are testing with. The code that parses the header and tries to decrypt has been tested with the OMS example (https://oms-group.org/fileadmin/files/download4all/specification/Vol2/4.3.3/OMS-Spec_Vol2_AnnexN_D103.pdf) so we're confident that we did IV construction correctly and are using AES in the correct mode.

We padded the frame with zero bytes to see if AES could decrypt the first blocks but that was also unsuccessful. For the type of message we are using should the first 2 bytes of the plaintext of the encrypted payload be 0x2F2F and that isn't the case with the payloads we do receive.

Another problem we see is that we are not just missing the 5 bytes to complete the payload. When using decryption on the CC1310 the payload of one of our meters is usually 96 bytes decrypted while the encrytped payload in the TPL header is 64 bytes and in the SATP frame is 59 bytes. This can indicate that we aren't receiving the SND-NR frames we are expecting to receive there but Control field byte isn't part of the header send with the frame in the SATP_APL_COL_INDICATION_NEW_METER indication while it is part of the frame for the SATP_APL_COL_INDICATION_RX indication.

Our end goal is to be able to decrypt SND-NR frames ourselves to get to the measurement data while using an WMBus Serial T2 Collector image. Our questions to get there are:

  • What are the bytes we are receiving in the payload of the SATP_APL_COL_INDICATION_NEW_METER indication after the ELL, AFL, TPL headers?
  • Can you know what the C field value was for a frame received via SATP_APL_COL_INDICATION_NEW_METER?
  • Can you receive all WMBus frames still encrypted using Enhanced installation mode, SATP_APL_COL_INDICATION_NEW_METER and the Serial Collector T2 image? And if not all can you receive the SND-NR frames? Can you do it by using another image?

I can supply more information or logic analyzer traces if the questions aren't clear.

Kind regards,
Harmjan

  • Hi Harmjan,

    Thank you for proviing so much detail. However I don't understand the set-up. Culd you make a figure and name all the different devices in play?

  • Hey Marie,

    The systems looks as follows:

    The main processor is where I want to do the decryption. The Coprocessor is where the StackForce WMBus stack runs, the main processor configures the coprocessor over UART using the SATP protocol. The WMBus meters periodically send out SND-NR frames that are received by the coprocessor and forwarded to the main processor.

    I have also attached the logic analyzer and have received the following Serial MAC V2 frame (part of the SATP stack), what you can see in this frame is that the received telegram after the DLL header is only 59 bytes while it should be 64:

    0xA5 Serial MAC V2 Sync byte
    0x00 Serial MAC V2 length 0x59 = 89 bytes
    0x59
    0xFF Serial MAC V2 inverted length
    0xA6
    0x01 SATP Stack ID of WMBus stack
    0x09 SATP API ID of Collector API
    0x04 SATP Indication Id, these three bytes means it is an SATP_APL_COL_INDICATION_NEW_METER
    0x4C Meter Address
    0xAE
    0x21
    0x04
    0x96
    0x66
    0x68
    0x07
    0x00 RF Adapter address (All zeroes are expected here)
    0x00
    0x00
    0x00
    0x00
    0x00
    0x00
    0x00
    0x01 Wireless MBus mode (0x01 means Mode T)
    0x00 Frame format (0x00 means Frame type A)
    0x30 RSSI
    0x05 TPL Header length
    0x00 ELL Header length
    0x00 AFL Header length
    0x7A TPL Header Control information field of 0x7A
    0xF8 TPL Header Access number of 0xF8
    0x30 TPL Header WMBus status field
    0x40 TPL Header WMBus config field (four encrypted blocks (total frame size should be 4*16=64 bytes), Content of Message=0, Repeated access=0, Hop Counter=0)
    0x05 TPL Header WMBus config field (Encryption mode 5, Bidrectional Communication=0, accessibility=0, synchronous=0)
    0xF6 Received telegram after the DLL header (without CRCs) byte  0
    0x5F Received telegram after the DLL header (without CRCs) byte  1
    0x9C Received telegram after the DLL header (without CRCs) byte  2
    0xE5 Received telegram after the DLL header (without CRCs) byte  3
    0x1A Received telegram after the DLL header (without CRCs) byte  4
    0xC6 Received telegram after the DLL header (without CRCs) byte  5
    0xD7 Received telegram after the DLL header (without CRCs) byte  6
    0xBD Received telegram after the DLL header (without CRCs) byte  7
    0xB5 Received telegram after the DLL header (without CRCs) byte  8
    0x3A Received telegram after the DLL header (without CRCs) byte  9
    0xDB Received telegram after the DLL header (without CRCs) byte 10
    0x3E Received telegram after the DLL header (without CRCs) byte 11
    0x90 Received telegram after the DLL header (without CRCs) byte 12
    0xD6 Received telegram after the DLL header (without CRCs) byte 13
    0x1F Received telegram after the DLL header (without CRCs) byte 14
    0x7A Received telegram after the DLL header (without CRCs) byte 15
    0xD8 Received telegram after the DLL header (without CRCs) byte 16
    0x9E Received telegram after the DLL header (without CRCs) byte 17
    0x29 Received telegram after the DLL header (without CRCs) byte 18
    0xBF Received telegram after the DLL header (without CRCs) byte 19
    0xE0 Received telegram after the DLL header (without CRCs) byte 20
    0xFB Received telegram after the DLL header (without CRCs) byte 21
    0x48 Received telegram after the DLL header (without CRCs) byte 22
    0x07 Received telegram after the DLL header (without CRCs) byte 23
    0xF0 Received telegram after the DLL header (without CRCs) byte 24
    0x95 Received telegram after the DLL header (without CRCs) byte 25
    0x3B Received telegram after the DLL header (without CRCs) byte 26
    0xF2 Received telegram after the DLL header (without CRCs) byte 27
    0x8C Received telegram after the DLL header (without CRCs) byte 28
    0x0E Received telegram after the DLL header (without CRCs) byte 29
    0xE1 Received telegram after the DLL header (without CRCs) byte 30
    0xF8 Received telegram after the DLL header (without CRCs) byte 31
    0x68 Received telegram after the DLL header (without CRCs) byte 32
    0xC5 Received telegram after the DLL header (without CRCs) byte 33
    0x7E Received telegram after the DLL header (without CRCs) byte 34
    0xE3 Received telegram after the DLL header (without CRCs) byte 35
    0xAB Received telegram after the DLL header (without CRCs) byte 36
    0x54 Received telegram after the DLL header (without CRCs) byte 37
    0x0D Received telegram after the DLL header (without CRCs) byte 38
    0x99 Received telegram after the DLL header (without CRCs) byte 39
    0x6B Received telegram after the DLL header (without CRCs) byte 40
    0xF4 Received telegram after the DLL header (without CRCs) byte 41
    0xE4 Received telegram after the DLL header (without CRCs) byte 42
    0xB8 Received telegram after the DLL header (without CRCs) byte 43
    0x55 Received telegram after the DLL header (without CRCs) byte 44
    0x36 Received telegram after the DLL header (without CRCs) byte 45
    0x70 Received telegram after the DLL header (without CRCs) byte 46
    0x2A Received telegram after the DLL header (without CRCs) byte 47
    0x49 Received telegram after the DLL header (without CRCs) byte 48
    0x2B Received telegram after the DLL header (without CRCs) byte 49
    0x03 Received telegram after the DLL header (without CRCs) byte 50
    0x1E Received telegram after the DLL header (without CRCs) byte 51
    0x53 Received telegram after the DLL header (without CRCs) byte 52
    0xB4 Received telegram after the DLL header (without CRCs) byte 53
    0x91 Received telegram after the DLL header (without CRCs) byte 54
    0xF6 Received telegram after the DLL header (without CRCs) byte 55
    0x85 Received telegram after the DLL header (without CRCs) byte 56
    0xD0 Received telegram after the DLL header (without CRCs) byte 57
    0x4E Received telegram after the DLL header (without CRCs) byte 58
    0x16 Serial MAC V2 CRC
    0xB6

  • This question is probably related to the question https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/964134?tisearch=e2e-sitesearch&keymatch=wmbus.

    The answer by M-W implies that what I want to do should be possible:

    I got feedback from the developers that there should be no real risks turning of the address filtering in the stack. If you do this (compile configuration + serial command) then the stack will just forward the telegrams up to the host (as you expected). While most of the handling is left to the host in that case, the CRC of the packets are still being validated by the stack.

    What compile configuration and serial commands do the developers expect you to use to get it to work?

  • Hi,

    I am also very interested in the answer.

    Maybe I could help a bit. After the ELL, AFL and TPL headers the userdata/meterrecords (Application Layer - APL) follows. This is structured as described in DIN EN 13757-03 with a DIB, VIB and the data, as it is in "C:\ti\wmbus_cc13x0_rtos_2_0_0\wmbus-cc13xx-rtos-2.0.0\apps_rtos\apl\app_aplMeterRtos.c" in the "Example UserData" you can also set it with an SATP command "SATP_APL_MTR_SET_USER_DATA" when using the SATP. After AES encryption it should be possible to interpret the data like in the DIN EN 13757-03.

    I found something interesting after my post (you mentioned) was answered: meter limitation is a Forum Post where it says that the meter limitation can be changed in release.h

    Then the AES decryption can be done by theStack for (more or less unlimited?) meters, maybe this helps you.

    But anyway it would be nice to know why we did not get enough bytes with SATP_APL_COL_INDICATION_NEW_METER indication.

  • Hey SB Ger,

    > Maybe I could help a bit. After the ELL, AFL and TPL headers the userdata/meterrecords (Application Layer - APL) follows. This is structured as described in DIN EN 13757-03 with a DIB, VIB and the data, as it is in "C:\ti\wmbus_cc13x0_rtos_2_0_0\wmbus-cc13xx-rtos-2.0.0\apps_rtos\apl\app_aplMeterRtos.c" in the "Example UserData" you can also set it with an SATP command "SATP_APL_MTR_SET_USER_DATA" when using the SATP. After AES encryption it should be possible to interpret the data like in the DIN EN 13757-03.
    >I found something interesting after my post (you mentioned) was answered: meter limitation is a Forum Post where it says that the meter limitation can be changed in release.h
    > Then the AES decryption can be done by theStack for (more or less unlimited?) meters, maybe this helps you.

    SATP_APL_MTR_SET_USER_DATA is an command for the meter interface, for when the stack is configured as an WMBus meter instead of an collector. We have successfully used the stack to receive and decrypt meter data, I can decode the DIB, VIB and data information from the SATP_APL_COL_INDICATION_RX you receive when you configure the stack in that way. But to meet customer requirements we want to move decryption away from the coprocessor to the main processor and we ran into this problem there. In the way I read and understand the documentation should it be possible to do this since SATP_APL_COL_INDICATION_NEW_METER should return the entire frame after the DLL header with the DLL CRCs removed. This should leave us with a frame we can decrypt but now we're not even receiving the expected amount of bytes.

    > But anyway it would be nice to know why we did not get enough bytes with SATP_APL_COL_INDICATION_NEW_METER indication.

    Yes, that is at the core of the problem. Either the implementation or my understanding of the documentation is wrong and getting to the bottom of that should solve this problem.

  • Hi,

    Yes thank you for the illustration, it helps. 

    Sorry this is taking some time. I agree either the documentation is wrong or there is a misunderstanding. I will need to confirm with the software team. Please let me get back to you.

  • Hi,

    We did a test with version 2.1.6 of the CC1310 WMBUS stack, a simulation of having a test meter sending telegrams with 4 AES encrypted blocks. The result I have got is a SATP_APL_COL_INDICATION_NEW_METER indication with 64 bytes data which is complete 4 AES encrypted blocks. So in this case there is no bytes missing.

    For further investigation I recommend the following:

    - Can you double check that your meter is indeed sending 4 AES encrypted blocks data?

    - If you are using a lib version of the WMBUS stack; is there any change done in the application such as changing the telegram storage size?

  • Hey,

    I'm using a pre-compiled image zo I'm not using a lib version. How do you get version 2.1.6 of the WMBus stack? If I go to https://www.ti.com/tool/WMBUS I can only find version 2.0.0. If I use the command SATP_WMBUS_GET_VERSION_STRING I also get the string 2.0.0.

    I'm also pretty sure that the device is sending correct AES frames since the stack itself can decrypt it.

    Kind regards,

    Harmjan

  • Hi Harmjan,

    Sorry, yes 2.0.0 is the one we have on ti.com.

    Can you double check that you are actually using 4 AES encryption?

  • Hey Marie,

    > Can you double check that you are actually using 4 AES encryption?
    We are using commercial meters to test with, and again the stack was able to decrypt the frames when we added the meters to the meter list with the encryption key. It wouldn't be able to do that if the frame were malformed.

    > Sorry, yes 2.0.0 is the one we have on ti.com.
    So when you did a test an got 64 bytes back did you use the version available on TI.com or 2.1.6? When you did the test do you use the Serial version of the stack or the lib version? Can you provide the code you used to perform this test so I can replicate it over here?

    Your last response also implies that the version on ti.com lags behind a bit, is there a plan to update to 2.1.6 for the ti.com images?

    Kind regards,
    Harmjan

  • Hey all,

    I have tried to use the lib version of the stack and still have the same problem. I made minor changes to the file app_aplCollectorRtos.c to set the stack in enhanced installation mode and set a breakpoint in the indication handler to inspect memory. Below is a screenshot:

    The same problem happens. You can see in the Variables window that `s_meterAddr` is set to the same address as the SATP example I dissected above. The TPL Header length is still 5 and the length of the payload (set in `g_last_len`, visible in the Memory Browser window) is 0x40 = 64. The TPL header is the same except for the access number (0x7A, 0x52, 0x30, 0x40, 0x05). Then there are 59 bytes of payload left which you can't decrypt since it's not an multiple of 16.  Just copying the next 5 bytes in memory also didn't help me decrypt them. I also think I should be able to decrypt the first blocks if there were only some bytes missing at the end so there are bytes missing at the start, it's different data or my decryption attempts are wrong.

    I attached the version of app_aplCollectorRtos.c which normally resides in wmbus_cc13x0_rtos_2_0_0/wmbus-cc13xx-rtos-2.0.0/apps_rtos/apl/app_aplCollectorRtos.c. I set the active configuration to the APL T2 collector. In these changes during initialization it checks that the stack version is 2.0.0, sets the stack in Enhanced installation mode, erase NVM memory and synchronizes. An if was hardcoded to true to prevent the stack from going to sleep. In the new meter indication is the length and payload copied to global variables to make them easier to read in an debugger (I'm not that proficient with code composer). I also included UART driver headers at the start of the file which are a remnant of another experiment. I'm pretty sure I didn't edit any other files but haven't used git well for this experiment.

    /**
     * @code
     *  ___ _____ _   ___ _  _____ ___  ___  ___ ___
     * / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
     * \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
     * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
     * embedded.connectivity.solutions.==============
     * @endcode
     *
     * @file
     * @copyright  STACKFORCE GmbH, Heitersheim, Germany, www.stackforce.de
     * @author     Naksit Anantalapochai <naksit.anantalapochai@stackforce.de>
     * @author     Alexander Rohleder <alexander.rohleder@stackforce.de>
     * @author     Mario Behringer <mario.behringer@stackforce.de>
     *
     * @example    main_collector.c
     *
     *             # Collector Demo Application
     *
     *             The main task of this application is to demonstrate how to setup a
     *             static meterlist, how the collector device can receive WMBUS
     *             telegrams and how to start a bidirectional communication
     *             with a meter device.\n
     *             \n
     *             The collector device installs a (preconfigured) WMBUS meter device
     *             into the meterlist with the start attributes of the device. After
     *             initialization, the collector is ready to receive WMBUS telegrams
     *             from the meter devices which are in its meterlist.
     *             After the collector has received a specified number
     *             (@ref NUMBER_OF_TELEGRAMS_BEFORE_SND_UD, default is 5) of telegrams from the
     *             WMBUS meter device, it initiates a bidirectional communication.\n
     *             \n
     *             The following diagram shows the communication sequence when running
     *             this collector demo application with the compatible meter.
     *
     *             <b><pre>
     *             +-------+                                    +-----------+
     *             | Meter |                                    | Collector |
     *             +-------+                                    +-----------+
     *                 |                   SND-NR                     |
     *                 |--------------------------------------------->|--+
     *                 |                                              |  | rxSndNrCounter++
     *                 |                                              |<-+
     *                 |                   SND-NR                     |
     *                 |--------------------------------------------->|--+
     *                 |                                              |  | rxSndNrCounter++
     *                 |                                              |<-+
     *                 |    |          rxSndNrCounter == 5       |    |
     *                 |    | Starts Bidirectional Communication |    |
     *                 |                                              |
     *                 |                   SND-UD                     |
     *                 |<---------------------------------------------|
     *                 |                    ACK                       |
     *                 |--------------------------------------------->|
     *                 |                   SND-NKE                    |
     *                 |<---------------------------------------------|--+
     *                 |                                              |  | rxSndNrCounter = 0 (reset)
     *                 |                                              |<-+
     *                 |                   SND-NR                     |
     *                 |--------------------------------------------->|
     *                 |                                              |
     *                 |        | Until rxSndNrCounter == 5 |         |
     *                 |                                              |
     *             </pre></b>
     *
     *             This application is compatible with the following WMBUS meter
     *             demonstration application(s):
     *             - app_aplMeterRtos.c
     *
     *             ## Source Code
     */
    
    /*==============================================================================
                                INCLUDE FILES
    ==============================================================================*/
    /* Standard libraries */
    #include <stdint.h>
    #include <stdbool.h>
    
    /* XDCtools Header files */
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/drivers/Power.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    #include "ti_rtos_src/sf_mcu_timerRtos.h"
    #include "ti_rtos_src/sf_mcu_rtcRtos.h"
    
    #include "inc/pub/utils/wmbus_timer_api.h"
    /* Include common HAL API. */
    #include "inc/pub/hal/wmbus_hal.h"
    /* Include HAL BSP API */
    #include "inc/pub/hal/wmbus_hal_bsp.h"
    /* Support low power modes */
    #include "inc/pub/hal/wmbus_hal_mcu_sleep.h"
    /* Sandman module to support sleep modes. */
    #include "src/utils/sandman/src/sf_sandman_api.h"
    /* Include common APL API */
    #include "inc/pub/apl/wmbus_apl_api.h"
    #include "inc/pub/apl/wmbus_apl_indication_api.h"
    #include "inc/pub/apl/wmbus_apl_attributes_api.h"
    /* Include meter device specific APL API functions */
    #include "inc/pub/apl/wmbus_apl_col_api.h"
    #include "inc/pub/apl/wmbus_apl_col_attributes_api.h"
    #include "inc/pub/apl/wmbus_apl_col_indication_api.h"
    
    #include "wmbus_task.h"
    #include "wmbus_semaphore.h"
    
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTCC26XX.h>
    
    /*==============================================================================
                                DEFINES
    ==============================================================================*/
    #ifndef WMBUS_CFG_DEVICE
      #error Please define the device configuration to a COLLECTOR device!
    #elif WMBUS_CFG_DEVICE != WMBUS_CFG_DEVICE_COLLECTOR
      #error Please define the device configuration to a COLLECTOR device!
    #endif /* WMBUS_CFG_DEVICE */
    
    /*! Number of received telegrams from meter device until the collector starts
        bidirectional communication by first sending SND-UD to meter. */
    #define NUMBER_OF_TELEGRAMS_BEFORE_SND_UD    5
    
    #ifndef CUSTOMER_FREQ_OFFSET
      /*! Customer specific frequency offset. */
      #define CUSTOMER_FREQ_OFFSET 0x00
    #endif /* CUSTOMER_FREQ_OFFSET */
    
    /* Check if a specific manufacturer id should be used */
    #ifndef MANUFACTURER_ID
      /*! Default manufacturer ID (STACKFORCE) MSB */
      #define MANUFACTURER_ID_H      0xCEU
      /*! Default manufacturer ID (STACKFORCE) LSB */
      #define MANUFACTURER_ID_L      0x86U
      #warning MANUFACTURER_ID is not defined. Default manufacturer ID 0xCE86 (STF) is used
    #else
      /* Set the ID of the manufacturer */
      #define MANUFACTURER_ID_H      (uint8_t)((MANUFACTURER_ID & 0xFF00U)>>8)
      #define MANUFACTURER_ID_L      (uint8_t)(MANUFACTURER_ID & 0x00FFU)
    #endif /* MANUFACTURER_ID */
    
    /*! Max length of the payload:
        MAX_PAYLOAD_LEN = 255-9(Dll-Header->L field not counted)-1(CI-Field) */
    #define MAX_PAYLOAD_LEN (uint8_t)245U
    
    /*==============================================================================
                                VARIABLES
    ==============================================================================*/
    /*! Counts the received SND-NR messages. */
    uint8_t gc_rxSndNrCounter = 0;
    
    /*! Memory to store received telegrams. */
    uint8_t gac_telegramStorage[MAX_PAYLOAD_LEN];
    
    /*! Example collector address */
    s_wmbus_addr_t gs_collector = {{MANUFACTURER_ID_H, MANUFACTURER_ID_L},
                        {0x80,0x00,0x00,0x02},    /* ident number            */
                         0x23,                    /* version                 */
                        WMBUS_DEV_TYPE_OTHER};    /* type, here other        */
    
    /*! Example meter entry for the meterlist of the collector. */
    s_apl_meterEntry_t gs_meterEntry = {
                    /* WMBus meter address */
                    {{MANUFACTURER_ID_H, MANUFACTURER_ID_L},{0x80,0x00,0x00,0x01},0x23,WMBUS_DEV_TYPE_WATER},
                    /* WMBus mode of the meter */
                    E_WMBUS_MODE_UNKNOWN,
                    /* WMBus RF adapter address of the meter (unused) */
                    {{0x0,0x0},{0x0,0x0,0x0,0x0},0x0,0x0},
                    /* WMBus meter key */
                    {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
                     0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}};
    
    /*! Example meterlist */
    s_apl_meterList_t gs_meterList = {0x0001U, &gs_meterEntry};
    
    /*! Start attribute for the collector device.  */
    s_apl_colInitAttr_t gs_collectorInitAttr =
    {
      {
        /* Frequency offset for the carrier. */
        CUSTOMER_FREQ_OFFSET,
        /* Device address */
        &gs_collector,
        /* Telegram storage */
        gac_telegramStorage,
        /* Size of the telegram storage */
        MAX_PAYLOAD_LEN
      },
      /* Static meters to install at startup. If no static meters are available,
         set the parameter to NULL. Only for collector devices. */
      &gs_meterList
    };
    
    /* Flag that indicates that the stack is active (needs to run) or not */
    static bool gb_stackActive = true;
    /* Variable to store the sleep mode that sandman indicates */
    static E_SANDMAN_t ge_sleepMode;
    
    /*==============================================================================
                                FUNCTION PROTOTYPES
    ==============================================================================*/
    /*! Sleep function to be registered to sandman module. */
    static void loc_stackSleep(E_SANDMAN_t e_sleep);
    /*! Wake up function to be registered to sandman module. */
    static void loc_stackWakeUp(void);
    
    /*! Task to handle the wmbus stack */
    static void loc_collectorTask(UArg arg0, UArg arg1);
    
    /*==============================================================================
                                LOCAL FUNCTIONS
    ==============================================================================*/
    /*----------------------------------------------------------------------------*/
    /*
     * @brief Sleep function to be registered to sandman module.
     *
     * @param e_sleep This parameter specifies the deepest sleep mode which is
                      currently possible.
     */
    /*----------------------------------------------------------------------------*/
    static void loc_stackSleep(E_SANDMAN_t e_sleep)
    {
      gb_stackActive = false;
      ge_sleepMode = e_sleep;
    } /* loc_stackSleep() */
    
    /*----------------------------------------------------------------------------*/
    /*!
     * @brief Wake up function to be registered to sandman module.
     */
    /*----------------------------------------------------------------------------*/
    static void loc_stackWakeUp(void)
    {
      gb_stackActive = true;
    } /* loc_stackWakeUp() */
    
    uint8_t g_version_string[50];
    
    /*----------------------------------------------------------------------------*/
    /*!
     * @brief Task to handle the wmbus stack.
     */
    /*----------------------------------------------------------------------------*/
    static void loc_collectorTask(UArg arg0, UArg arg1)
    {
      /* Initialises the hal. */
      if(wmbus_hal_init() == E_HAL_STATUS_SUCCESS)
      {
        /* Initialize the sandman module. */
        sf_sandman_init(&loc_stackSleep, &loc_stackWakeUp);
    
        /* Disable sleep mode for collector devices to ensure a faster reaction during
         * bidirectional communication */
        Power_disablePolicy();
    
        /* Initialize APL */
        if(E_WMBUS_STATUS_SUCCESS == wmbus_apl_col_init(&gs_collectorInitAttr))
        {
          #if WMBUS_CHECK_MODE_or(WMBUS_MODE_N1 | WMBUS_MODE_N2)
            /* Set the channel which should be used (for mode N-Devices only) */
            wmbus_apl_setChannelN(E_WMBUS_N_CHANNEL_169_1A);
          #endif /* WMBUS_CHECK_MODE_or(WMBUS_MODE_N1 | WMBUS_MODE_N2) */
    
          if (!wmbus_getVersionString(g_version_string, 50)) {
              while(true){}
          }
          if (g_version_string[0] != '2' ||
              g_version_string[1] != '.' ||
              g_version_string[2] != '0' ||
              g_version_string[3] != '.' ||
              g_version_string[4] != '0' ||
              g_version_string[5] != '\0'
             ) {
              while(true){}
          }
    
          if(E_WMBUS_STATUS_SUCCESS != wmbus_apl_col_setProperty(E_APL_COL_PROPERTY_ENHANCED_INSTALLATION, true)) {
              while(true){}
          }
    
          if (E_WMBUS_STATUS_SUCCESS != wmbus_memoryErase()) {
              while(true){}
          }
          if (E_WMBUS_STATUS_SUCCESS != wmbus_memorySynchronization()) {
              while(true){}
          }
    
          while(true)
          {
            // Don't go to sleep
            if(gb_stackActive || true)
            {
              sf_mcu_rtc_run();
    
              /*
                 Run the application layer.
                 In general, the function wmbus_apl_col_run must be called as often as
                 possible, since it is responsible to handle all operations of the
                 WMBUS Stack.
              */
              wmbus_apl_col_run();
    
              /* handel target events */
              wmbus_hal_bsp_handleEvent();
            }
            else
            {
              /* It is possible to let the device go to sleep. */
              wmbus_hal_mcu_sleep((E_HAL_MCU_SLEEP_MODE_t) ge_sleepMode);
            } /* if() .. else */
          }/* while */
        } /* if */
        else
        {
          /* Stack initialization failed. Add your error handling here. */
          while(1);
        }/* if...else */
      } /* if */
      else
      {
        /* HAL initialization failed. Add your error handling here. */
        while(1);
      }/* if() .. else */
    }/* loc_collectorTask() */
    
    /*==============================================================================
                                FUNCTIONS
    ==============================================================================*/
    /*============================================================================*/
    /*!
     * @brief Main program.
     */
    /*============================================================================*/
    int main(void)
    {
      Error_Block eb;
    
      /* Call board init functions */
      Board_initGeneral();
    
      /* Initialize error parameters */
      Error_init(&eb);
    
      wmbus_task_init(loc_collectorTask, &eb);
      wmbus_semaphore_init(&eb);
      /* Initialize the periodical clock source of the wmbus stack */
      sf_mcu_timerRtos_init(TMR_TICKS_PER_SECOND, &eb);
      sf_mcu_rtc_init();
    
      /* Start BIOS */
      BIOS_start();
      return (0);
    } /* main() */
    
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_indication() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_indication(E_APL_INDICATION_t e_indication)
    {
      switch(e_indication)
      {
        case E_APL_INDICATION_TX:
          break;
        case E_APL_INDICATION_TX_ERROR:
          break;
        case E_APL_INDICATION_REQUEST_TIMEOUT:
          break;
        case E_APL_INDICATION_RX_BUFFER_OVERFLOW:
          break;
        case E_APL_INDICATION_RX_NO_TELEGRAM_STORAGE:
          break;
        case E_APL_INDICATION_RX_TELEGRAM_STORAGE_OVERFLOW:
          break;
        default:
          break;
      }
    }/* wmbus_apl_indication() */
    
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_col_indication() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_col_indication(E_APL_COL_INDICATION_t e_indication,
                                  uint16_t i_meterId)
    {
      switch(e_indication)
      {
        case E_APL_COL_ALARM_AVAILABLE:
          break;
        case E_APL_COL_RX_DECRYPTION_FAILED:
          break;
        case E_APL_COL_RX_UNKNOWN_ENCRYPTION:
          break;
        default:
          break;
      }
    }/* wmbus_apl_col_indication() */
    
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_col_indication_rx() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_col_indication_rx(uint16_t i_meterId,
                                     E_APL_MESSAGE_TYPE_t e_controlField,
                                     uint8_t c_rssi, E_WMBUS_FRAME_t e_frameFormat,
                                     E_WMBUS_MODE_t e_mode,
                                     s_wmbus_layerHeaderLength_t *ps_headerLen,
                                     uint8_t *pc_payload, uint16_t i_length)
    {
      /* SND-UD payload. */
      uint8_t ac_cmdPayload[] = { 0x0F,  /* Record 1: DIB: Manufacturer specific data structure */
                                  0x7F,  /* Record 1: VIB: Manufacturer specific */
                                  0x00,  /* Record 1: Dummy data */
                                  0x01,  /* Record 1: Dummy data */
                                  0x02,  /* Record 1: Dummy data */
                                  0x03,  /* Record 1: Dummy data */
                                  0x04}; /* Record 1: Dummy data */
    
      if(e_controlField == E_APL_MESSAGE_TYPE_SND_NR)
      {
        /* SND-NR telegram received. Increase the counter. */
        ++gc_rxSndNrCounter;
    
        if(gc_rxSndNrCounter == NUMBER_OF_TELEGRAMS_BEFORE_SND_UD)
        {
          /* Threshold reached. Initiate transmission of a SND-UD telegram. */
          wmbus_apl_col_sendUserData(E_APL_MESSAGE_TYPE_SND_UD,
                                     APL_FIELD_CI_CMD_TO_DEVICE_LONG, i_meterId,
                                     true, 0xFFFFU, ac_cmdPayload, sizeof(ac_cmdPayload));
          /* Reset the counter. */
          gc_rxSndNrCounter = 0U;
        }
      }
      else if(e_controlField == E_APL_MESSAGE_TYPE_ACK)
      {
        /* ACK telegram from the meter received. Send SND-NKE. */
        wmbus_apl_col_send(E_APL_MESSAGE_TYPE_SND_NKE,
                           APL_FIELD_CI_LINK_TO_DEVICE_LONG,
                           i_meterId, true);
      }
    }/* wmbus_apl_col_indication_rx() */
    
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_col_indication_tlgPrependedToQueue() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_col_indication_tlgPrependedToQueue(uint16_t i_meterId,
                                                      E_APL_MESSAGE_TYPE_t e_controlField)
    {
      /*
       * A telegram from the given telegram type has been automatically
       * created by the Wireless M-Bus stack and added to the telegram queue.
       */
    }/* wmbus_apl_col_indication_tlgPrependedToQueue() */
    
    uint16_t g_last_len;
    uint8_t g_payload[256];
    
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_col_indication_newMeter() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_col_indication_newMeter(s_wmbus_addr_t * ps_address,
                                           s_wmbus_addr_t * ps_rfAdapter,
                                           E_WMBUS_MODE_t e_mode,
                                           E_WMBUS_FRAME_t e_frameFormat,
                                           uint8_t c_rssi,
                                           s_wmbus_layerHeaderLength_t * ps_headerLen,
                                           uint8_t * pc_payload, uint16_t i_len)
    {
    
      if (E_WMBUS_MODE_T == e_mode) {
          for (size_t i=0; i<256; ++i) {
              g_payload[i] = 0;
          }
          g_last_len = i_len;
          for (size_t i=0; i<i_len; ++i) {
              g_payload[i] = pc_payload[i];
          }
    
          g_payload[255] = 0;
      }
    
    }/* wmbus_apl_col_indication_newMeter() */
    
    #if OMS_V4_ENABLED
    #if INVALID_MSG_CTR_EVENT_ENABLED
    /*----------------------------------------------------------------------------*/
    /* wmbus_apl_col_indication_invalidMsgCtrReceived() */
    /*----------------------------------------------------------------------------*/
    void wmbus_apl_col_indication_invalidMsgCtrReceived(uint16_t i_meterId,
                                                        uint32_t l_invalidMsgCtr)
    {
      /* The event is triggered to inform the upper layer that an OMSv.4 telegram
         is received with invalid message counter. */
      return;
    } /* wmbus_apl_col_indication_invalidMsgCtrReceived() */
    #endif /* INVALID_MSG_CTR_EVENT_ENABLED */
    #endif /* OMS_V4_ENABLED */
    

    I hope this helps TI reproduce the problem locally. The sample I've mentioned before below (if I put a link in here now it seems to truncate the rest of the post) shows that the AES blocks should start after the TPL header.

    https://oms-group.org/fileadmin/files/download4all/specification/Vol2/4.3.3/OMS-Spec_Vol2_AnnexN_D103.pdf

  • Hi,

    Thank you for reporting this bug. I am working to see whether we can fix it and release a new version on ti.com. Sadly I don't know how long this may take.