LoRa on Multitech with Semtech mote

Dependencies:   LoRaWAN-lib SX1272Lib lib_gps lib_mma8451q lib_mpl3115a2 mbed

Fork of LoRaWAN-NAMote72-Application-Demo_Multitech by Nagaraj Krishnamurthy

Committer:
nagarajkmurthy
Date:
Wed Nov 09 06:55:47 2016 +0000
Revision:
16:85cfe4bb33e8
Parent:
15:39a23f5affd1
Child:
18:168062d45093
some debug messsage;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ubhat 0:69f2e28d12c1 1 /*
ubhat 0:69f2e28d12c1 2 / _____) _ | |
ubhat 0:69f2e28d12c1 3 ( (____ _____ ____ _| |_ _____ ____| |__
ubhat 0:69f2e28d12c1 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
ubhat 0:69f2e28d12c1 5 _____) ) ____| | | || |_| ____( (___| | | |
ubhat 0:69f2e28d12c1 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
ubhat 0:69f2e28d12c1 7 (C)2015 Semtech
ubhat 0:69f2e28d12c1 8
ubhat 0:69f2e28d12c1 9 Description: Define events during Join, Tx & Rx
ubhat 0:69f2e28d12c1 10 Prepare TX packet by appending with appropriate application data
ubhat 0:69f2e28d12c1 11
ubhat 0:69f2e28d12c1 12 License: Revised BSD License, see LICENSE.TXT file include in the project
ubhat 0:69f2e28d12c1 13
ubhat 0:69f2e28d12c1 14 Maintainer: Uttam Bhat
ubhat 0:69f2e28d12c1 15 */
ubhat 0:69f2e28d12c1 16
ubhat 0:69f2e28d12c1 17 #include "LoRaEventProc.h"
ubhat 0:69f2e28d12c1 18
ubhat 5:6ffeac53b7cb 19 /*!
ubhat 5:6ffeac53b7cb 20 * Defines the application data transmission duty cycle
ubhat 5:6ffeac53b7cb 21 */
ubhat 5:6ffeac53b7cb 22 uint32_t TxDutyCycleTime = APP_TX_DUTYCYCLE;
ubhat 5:6ffeac53b7cb 23
ubhat 0:69f2e28d12c1 24 bool AppLed = 0;
ubhat 0:69f2e28d12c1 25
ubhat 0:69f2e28d12c1 26 /*!
ubhat 0:69f2e28d12c1 27 * \brief Prepares the payload of the frame based on application port
ubhat 0:69f2e28d12c1 28 */
ubhat 0:69f2e28d12c1 29 void PrepareLoRaFrame( uint8_t port )
ubhat 0:69f2e28d12c1 30 {
ubhat 0:69f2e28d12c1 31
nagarajkmurthy 16:85cfe4bb33e8 32 printf( "###### ===== PrepareLoRaFrame %d ==== ######\r\n", port );
nagarajkmurthy 16:85cfe4bb33e8 33
ubhat 0:69f2e28d12c1 34 switch( port )
ubhat 0:69f2e28d12c1 35 {
ubhat 0:69f2e28d12c1 36 case 5:
ubhat 0:69f2e28d12c1 37 {
ubhat 0:69f2e28d12c1 38 uint8_t tmp;
ubhat 0:69f2e28d12c1 39 uint8_t tmpLength;
ubhat 0:69f2e28d12c1 40 uint8_t ptrIndex = 0;
ubhat 0:69f2e28d12c1 41
ubhat 0:69f2e28d12c1 42 // Point the pointer to position index of Tx Buffer
ubhat 0:69f2e28d12c1 43 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 0:69f2e28d12c1 44
ubhat 0:69f2e28d12c1 45 tmp = ( AppLed != 0 ) ? 0x0F : 0x00;
ubhat 0:69f2e28d12c1 46 tmpLength = 1;
ubhat 0:69f2e28d12c1 47
ubhat 0:69f2e28d12c1 48 LoRaApp.ApplicationAppendData( &tmp, tmpLength ); // Populate lower nibble of 0th Byte with LED state
ubhat 0:69f2e28d12c1 49
ubhat 0:69f2e28d12c1 50 /*!
ubhat 0:69f2e28d12c1 51 * Read Temperature
ubhat 0:69f2e28d12c1 52 * Appends 1 Byte to TX buffer
ubhat 0:69f2e28d12c1 53 */
ubhat 0:69f2e28d12c1 54 LoRaApp.ApplicationCall( AppTemp );
ubhat 0:69f2e28d12c1 55
ubhat 0:69f2e28d12c1 56 /*!
ubhat 0:69f2e28d12c1 57 * Read Battery
ubhat 0:69f2e28d12c1 58 * Appends 1 Byte to TX buffer
ubhat 0:69f2e28d12c1 59 */
ubhat 0:69f2e28d12c1 60 LoRaApp.ApplicationCall( AppBat );
ubhat 0:69f2e28d12c1 61
ubhat 0:69f2e28d12c1 62 /*!
ubhat 0:69f2e28d12c1 63 * Read GPS coordinates
ubhat 0:69f2e28d12c1 64 * Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer
ubhat 0:69f2e28d12c1 65 */
ubhat 0:69f2e28d12c1 66 LoRaApp.ApplicationCall( AppGps );
ubhat 0:69f2e28d12c1 67
ubhat 0:69f2e28d12c1 68 /*!
ubhat 0:69f2e28d12c1 69 * Read Accelerometer
ubhat 0:69f2e28d12c1 70 * Appends 2 Bytes to TX buffer
ubhat 0:69f2e28d12c1 71 * Value Orientation
ubhat 0:69f2e28d12c1 72 * 0x99 0x00 horizontal + faceup
ubhat 0:69f2e28d12c1 73 * 0x66 0x00 horizontal + facedown
ubhat 0:69f2e28d12c1 74 * 0x00 0x11 vertical
ubhat 0:69f2e28d12c1 75 */
ubhat 0:69f2e28d12c1 76 LoRaApp.ApplicationCall( AppAccl ); // Generate Accelerometer data bytes
ubhat 0:69f2e28d12c1 77
ubhat 0:69f2e28d12c1 78 /*!
ubhat 0:69f2e28d12c1 79 * Generate Ramp data bytes
ubhat 0:69f2e28d12c1 80 * Appends incremental values of 1 Byte each to TX buffer until Full
ubhat 0:69f2e28d12c1 81 */
ubhat 0:69f2e28d12c1 82 LoRaApp.ApplicationCall( AppRamp );
nagarajkmurthy 16:85cfe4bb33e8 83
ubhat 0:69f2e28d12c1 84
ubhat 0:69f2e28d12c1 85 break;
ubhat 0:69f2e28d12c1 86 }
ubhat 0:69f2e28d12c1 87
ubhat 0:69f2e28d12c1 88 // Senet M2X ORIENTATION Demo
ubhat 0:69f2e28d12c1 89 // Set LORAWAN_APP_DATA_SIZE to 2
ubhat 0:69f2e28d12c1 90 case 6:
ubhat 0:69f2e28d12c1 91 {
ubhat 0:69f2e28d12c1 92 uint8_t ptrIndex = 1;
ubhat 0:69f2e28d12c1 93
ubhat 0:69f2e28d12c1 94 //Point the pointer to position index of Tx Buffer
ubhat 0:69f2e28d12c1 95 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 0:69f2e28d12c1 96
ubhat 0:69f2e28d12c1 97 LoRaApp.ApplicationCall( AppAcclSenet ); // Generate Accelerometer data bytes
ubhat 0:69f2e28d12c1 98
ubhat 0:69f2e28d12c1 99
ubhat 0:69f2e28d12c1 100
ubhat 0:69f2e28d12c1 101 break;
ubhat 0:69f2e28d12c1 102 }
ubhat 0:69f2e28d12c1 103
ubhat 0:69f2e28d12c1 104 /* Senet GPS Demo
ubhat 0:69f2e28d12c1 105 Data Format (in Hex):
ubhat 0:69f2e28d12c1 106 [01, 02, Lattitude (3 bytes), Longitude (3 Bytes), Elevation (2 bytes), Tx Power (1 byte)]
ubhat 0:69f2e28d12c1 107 */
ubhat 0:69f2e28d12c1 108 case 7:
ubhat 0:69f2e28d12c1 109 {
ubhat 0:69f2e28d12c1 110 uint8_t ptrIndex = 0;
ubhat 0:69f2e28d12c1 111 uint8_t tmp[] = {0x01, 0x02};
ubhat 0:69f2e28d12c1 112
ubhat 0:69f2e28d12c1 113 //Point the pointer to position index of Tx Buffer
ubhat 0:69f2e28d12c1 114 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 0:69f2e28d12c1 115
ubhat 0:69f2e28d12c1 116 LoRaApp.ApplicationAppendData( tmp, 2 );
ubhat 0:69f2e28d12c1 117
ubhat 0:69f2e28d12c1 118 LoRaApp.ApplicationCall( AppGps ); // Generate Accelerometer data bytes
ubhat 0:69f2e28d12c1 119
ubhat 0:69f2e28d12c1 120 uint8_t pow = 30 - 2*(( uint8_t ) LoRaMacUplinkStatus.TxPower);
ubhat 0:69f2e28d12c1 121 LoRaApp.ApplicationAppendData( &pow, 1 );
ubhat 0:69f2e28d12c1 122
ubhat 0:69f2e28d12c1 123 break;
ubhat 0:69f2e28d12c1 124 }
ubhat 6:f8194e691dd4 125
ubhat 6:f8194e691dd4 126 // Push-Button Demo
ubhat 6:f8194e691dd4 127 case 11:
ubhat 6:f8194e691dd4 128 {
ubhat 6:f8194e691dd4 129 uint8_t ptrIndex = 0;
ubhat 6:f8194e691dd4 130
ubhat 6:f8194e691dd4 131 //Point the pointer to position index of Tx Buffer
ubhat 6:f8194e691dd4 132 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 6:f8194e691dd4 133
ubhat 7:92f4f419f91f 134 LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter
ubhat 7:92f4f419f91f 135
ubhat 7:92f4f419f91f 136 break;
ubhat 7:92f4f419f91f 137 }
ubhat 7:92f4f419f91f 138
ubhat 7:92f4f419f91f 139 // Transmit on Vertical Orientation Demo
ubhat 7:92f4f419f91f 140 case 12:
ubhat 7:92f4f419f91f 141 {
ubhat 7:92f4f419f91f 142 uint8_t ptrIndex = 0;
ubhat 7:92f4f419f91f 143
ubhat 7:92f4f419f91f 144 //Point the pointer to position index of Tx Buffer
ubhat 7:92f4f419f91f 145 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 7:92f4f419f91f 146
ubhat 7:92f4f419f91f 147 LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter
ubhat 6:f8194e691dd4 148
ubhat 6:f8194e691dd4 149 break;
ubhat 6:f8194e691dd4 150 }
ubhat 13:6b6f4be13633 151
ubhat 13:6b6f4be13633 152
ubhat 13:6b6f4be13633 153 /* Senet myDevices Sensor Demo
ubhat 13:6b6f4be13633 154 Data Format (in Hex):
ubhat 13:6b6f4be13633 155 [Pressure (2 Bytes), Temperature (1 Byte), X-Axis (2 bytes), Y-Axis (2 bytes), Z-Axis (2 bytes), ]
ubhat 13:6b6f4be13633 156 */
ubhat 13:6b6f4be13633 157 case 13:
ubhat 13:6b6f4be13633 158 {
ubhat 13:6b6f4be13633 159 uint8_t ptrIndex = 0;
ubhat 15:39a23f5affd1 160 uint8_t tmp = 0;
ubhat 13:6b6f4be13633 161
ubhat 13:6b6f4be13633 162 //Point the pointer to position index of Tx Buffer
ubhat 13:6b6f4be13633 163 LoRaApp.ApplicationPtrPos( ptrIndex );
ubhat 13:6b6f4be13633 164
ubhat 13:6b6f4be13633 165 LoRaApp.ApplicationCall( AppPrsr);
ubhat 13:6b6f4be13633 166
ubhat 13:6b6f4be13633 167 LoRaApp.ApplicationCall( AppTemp );
ubhat 13:6b6f4be13633 168
ubhat 13:6b6f4be13633 169 LoRaApp.ApplicationCall( AppBat );
ubhat 13:6b6f4be13633 170
ubhat 13:6b6f4be13633 171 LoRaApp.ApplicationCall( AppAcclSensor ); // Generate Accelerometer data bytes
ubhat 15:39a23f5affd1 172
ubhat 15:39a23f5affd1 173 if( AppLed == 1 )
ubhat 15:39a23f5affd1 174 {
ubhat 15:39a23f5affd1 175 tmp = 0x01;
ubhat 15:39a23f5affd1 176 }
ubhat 15:39a23f5affd1 177 else
ubhat 15:39a23f5affd1 178 {
ubhat 15:39a23f5affd1 179 tmp = 0x00;
ubhat 15:39a23f5affd1 180 }
ubhat 15:39a23f5affd1 181
ubhat 15:39a23f5affd1 182 LoRaApp.ApplicationAppendData( &tmp, 1 );
ubhat 13:6b6f4be13633 183
ubhat 13:6b6f4be13633 184 break;
ubhat 13:6b6f4be13633 185 }
ubhat 0:69f2e28d12c1 186
ubhat 0:69f2e28d12c1 187 default:
ubhat 0:69f2e28d12c1 188 break;
ubhat 0:69f2e28d12c1 189 }
ubhat 0:69f2e28d12c1 190 }
ubhat 0:69f2e28d12c1 191
ubhat 5:6ffeac53b7cb 192
ubhat 5:6ffeac53b7cb 193 /*!
ubhat 5:6ffeac53b7cb 194 * \brief Sets Interrupt for next payload transmission
ubhat 5:6ffeac53b7cb 195 */
ubhat 5:6ffeac53b7cb 196 void InitNextTxInterrupt( uint8_t port )
ubhat 5:6ffeac53b7cb 197 {
ubhat 5:6ffeac53b7cb 198 switch( port )
ubhat 5:6ffeac53b7cb 199 {
ubhat 5:6ffeac53b7cb 200 /* GPS Application Demo
ubhat 5:6ffeac53b7cb 201 Set Timer interrupt for next uplink
ubhat 5:6ffeac53b7cb 202 */
ubhat 5:6ffeac53b7cb 203 case 5:
ubhat 5:6ffeac53b7cb 204 {
ubhat 5:6ffeac53b7cb 205 }
ubhat 5:6ffeac53b7cb 206
ubhat 5:6ffeac53b7cb 207 /* Senet + M2X demo
ubhat 5:6ffeac53b7cb 208 Set Timer interrupt for next uplink
ubhat 5:6ffeac53b7cb 209 */
ubhat 5:6ffeac53b7cb 210 case 6:
ubhat 5:6ffeac53b7cb 211 {
ubhat 5:6ffeac53b7cb 212
ubhat 5:6ffeac53b7cb 213 }
ubhat 5:6ffeac53b7cb 214
ubhat 5:6ffeac53b7cb 215 /* Senet GPS Demo
ubhat 5:6ffeac53b7cb 216 Set Timer interrupt for next uplink
ubhat 5:6ffeac53b7cb 217 */
ubhat 5:6ffeac53b7cb 218 case 7:
ubhat 5:6ffeac53b7cb 219 {
ubhat 5:6ffeac53b7cb 220 // Schedule next packet transmission
ubhat 5:6ffeac53b7cb 221 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
ubhat 5:6ffeac53b7cb 222 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
ubhat 5:6ffeac53b7cb 223 TimerStart( &TxNextPacketTimer );
ubhat 5:6ffeac53b7cb 224 break;
ubhat 5:6ffeac53b7cb 225 }
ubhat 5:6ffeac53b7cb 226
ubhat 5:6ffeac53b7cb 227 /* Push Button Demo
ubhat 6:f8194e691dd4 228 Send Packet Immedietly if PC0 = GND
ubhat 5:6ffeac53b7cb 229 */
ubhat 5:6ffeac53b7cb 230 case 11:
ubhat 5:6ffeac53b7cb 231 {
ubhat 6:f8194e691dd4 232 volatile bool PushButtonStatus;
ubhat 6:f8194e691dd4 233
ubhat 6:f8194e691dd4 234 PushButtonStatus = PC0;
ubhat 6:f8194e691dd4 235
ubhat 6:f8194e691dd4 236 if(PushButtonStatus == 0)
ubhat 6:f8194e691dd4 237 {
ubhat 6:f8194e691dd4 238 // Send Pkt immedietly if PC = GND
ubhat 6:f8194e691dd4 239 DeviceState = DEVICE_STATE_SEND;
ubhat 6:f8194e691dd4 240 NextTx = true;
ubhat 6:f8194e691dd4 241 }
ubhat 6:f8194e691dd4 242 else
ubhat 6:f8194e691dd4 243 {
ubhat 6:f8194e691dd4 244 // Keep polling
ubhat 6:f8194e691dd4 245 IsTxIntUpdate = true;
ubhat 6:f8194e691dd4 246 }
ubhat 5:6ffeac53b7cb 247 break;
ubhat 5:6ffeac53b7cb 248 }
ubhat 5:6ffeac53b7cb 249
ubhat 7:92f4f419f91f 250 /* Orientation Demo
ubhat 7:92f4f419f91f 251 Send Packet Immedietly if Mote is Vertical
ubhat 7:92f4f419f91f 252 */
ubhat 7:92f4f419f91f 253 case 12:
ubhat 7:92f4f419f91f 254 {
ubhat 8:14521932100a 255 CheckOrientation( );
ubhat 7:92f4f419f91f 256
ubhat 7:92f4f419f91f 257 if(VerticalStatus == true)
ubhat 7:92f4f419f91f 258 {
ubhat 7:92f4f419f91f 259 // Send Pkt immedietly if PC = GND
ubhat 7:92f4f419f91f 260 DeviceState = DEVICE_STATE_SEND;
ubhat 7:92f4f419f91f 261 NextTx = true;
ubhat 7:92f4f419f91f 262 }
ubhat 7:92f4f419f91f 263 else
ubhat 7:92f4f419f91f 264 {
ubhat 7:92f4f419f91f 265 // Keep polling
ubhat 7:92f4f419f91f 266 IsTxIntUpdate = true;
ubhat 7:92f4f419f91f 267 }
ubhat 7:92f4f419f91f 268 break;
ubhat 7:92f4f419f91f 269 }
ubhat 7:92f4f419f91f 270
ubhat 5:6ffeac53b7cb 271 /* Compliance Test
ubhat 5:6ffeac53b7cb 272 Set Timer interrupt for next uplink
ubhat 5:6ffeac53b7cb 273 */
ubhat 5:6ffeac53b7cb 274 case 224:
ubhat 5:6ffeac53b7cb 275 {
ubhat 5:6ffeac53b7cb 276 // Schedule next packet transmission
ubhat 5:6ffeac53b7cb 277 TimerSetValue( &TxNextPacketTimer, COMPLIANCE_TX_DUTYCYCLE );
ubhat 5:6ffeac53b7cb 278 TimerStart( &TxNextPacketTimer );
ubhat 5:6ffeac53b7cb 279 break;
ubhat 5:6ffeac53b7cb 280 }
ubhat 5:6ffeac53b7cb 281
ubhat 5:6ffeac53b7cb 282 default:
ubhat 5:6ffeac53b7cb 283 {
ubhat 5:6ffeac53b7cb 284 // Schedule next packet transmission
ubhat 13:6b6f4be13633 285 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
ubhat 5:6ffeac53b7cb 286 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
ubhat 5:6ffeac53b7cb 287 TimerStart( &TxNextPacketTimer );
ubhat 5:6ffeac53b7cb 288 break;
ubhat 5:6ffeac53b7cb 289 }
ubhat 5:6ffeac53b7cb 290 }
ubhat 5:6ffeac53b7cb 291
ubhat 5:6ffeac53b7cb 292 }
ubhat 5:6ffeac53b7cb 293
ubhat 0:69f2e28d12c1 294 /*!
ubhat 0:69f2e28d12c1 295 * \brief What to do during JOIN process ? blink/toggle LED etc.
ubhat 0:69f2e28d12c1 296 */
ubhat 0:69f2e28d12c1 297 void JoinEvent( void )
ubhat 0:69f2e28d12c1 298 {
ubhat 0:69f2e28d12c1 299 // CtrlLED is defined in LoRaBoardAppIf.h
ubhat 0:69f2e28d12c1 300 // param 1: LED color (Red, Yellow or Green)
ubhat 0:69f2e28d12c1 301 // param 2: LED_ON or LED_OFF
ubhat 0:69f2e28d12c1 302 CtrlLED( Red, LED_ON );
ubhat 0:69f2e28d12c1 303 }
ubhat 0:69f2e28d12c1 304
ubhat 0:69f2e28d12c1 305
ubhat 0:69f2e28d12c1 306 /*!
ubhat 0:69f2e28d12c1 307 * \brief What to do during TX ? blink/toggle LED etc.
ubhat 0:69f2e28d12c1 308 */
ubhat 0:69f2e28d12c1 309 void TxEvent( void )
ubhat 0:69f2e28d12c1 310 {
ubhat 0:69f2e28d12c1 311 int blinkTime = 25000;
ubhat 0:69f2e28d12c1 312
ubhat 0:69f2e28d12c1 313 // Blink Red LED for 25msec
ubhat 0:69f2e28d12c1 314 BlinkLED( Red, blinkTime );
ubhat 0:69f2e28d12c1 315 }
ubhat 0:69f2e28d12c1 316
ubhat 0:69f2e28d12c1 317 void RxEvent()
ubhat 0:69f2e28d12c1 318 {
ubhat 0:69f2e28d12c1 319 // Toggle yellow LED
ubhat 0:69f2e28d12c1 320 ToggleLED( Yellow );
ubhat 0:69f2e28d12c1 321
ubhat 0:69f2e28d12c1 322 // If Rx Data is 0x01 turn on Green LED else if 0x0 Turn Green LED off
ubhat 0:69f2e28d12c1 323 if( LoRaMacDownlinkStatus.BufferSize == 1 )
ubhat 0:69f2e28d12c1 324 {
ubhat 0:69f2e28d12c1 325 if( LoRaMacDownlinkStatus.Buffer[0] == 0x01 )
ubhat 0:69f2e28d12c1 326 {
ubhat 0:69f2e28d12c1 327 AppLed = 1;
ubhat 0:69f2e28d12c1 328 }
ubhat 0:69f2e28d12c1 329 else
ubhat 0:69f2e28d12c1 330 {
ubhat 0:69f2e28d12c1 331 if( LoRaMacDownlinkStatus.Buffer[0] == 0x00 )
ubhat 0:69f2e28d12c1 332 {
ubhat 0:69f2e28d12c1 333 AppLed = 0;
ubhat 0:69f2e28d12c1 334 }
ubhat 0:69f2e28d12c1 335 }
ubhat 0:69f2e28d12c1 336 }
ubhat 0:69f2e28d12c1 337
ubhat 0:69f2e28d12c1 338 if( AppLed != 0 )
ubhat 0:69f2e28d12c1 339 {
ubhat 0:69f2e28d12c1 340 // Turn USR_LED ON
ubhat 0:69f2e28d12c1 341 CtrlLED( Usr, LED_ON );
ubhat 0:69f2e28d12c1 342 }
ubhat 0:69f2e28d12c1 343 else
ubhat 0:69f2e28d12c1 344 {
ubhat 0:69f2e28d12c1 345 // Turn USR_LED OFF
ubhat 0:69f2e28d12c1 346 CtrlLED( Usr, LED_OFF );
ubhat 0:69f2e28d12c1 347 }
ubhat 0:69f2e28d12c1 348 }
ubhat 0:69f2e28d12c1 349