Jan 2021
This project uses a motion sensor to trigger a WAV file player that plays the sound of a angry dog growling and barking. It is intended to be a theft deterrent. I utilized one Arduino Uno with Adafruit WaveShield, and two Adafruit M0 Feathers with LoRa radios. A PIR sensor is connected to the one Adafruit M0 Feather (Tx unit).
The PIR motion sensor from Adafruit has a range of about 20 feet (120 ° cone), an adjustable delay of 2 to 4 seconds, and adjustable sensitivity.
// RV_PIR_Tx.ino
// Sends an encrypted message to the receiver consisting of an integer indicating
// if the PIR sensor has been triggered, or if has not been.
// This is a derivative of 'AF_Feather_M0_Basic_LoRa900MHz_ReliableDatagram_encrypted_sendr.ini'
// Reliable Datagram is reliable in the sense that messages are acknowledged by the
// recipient, and unacknowledged messages are retransmitted until acknowledged or the
// retries are exhausted.
// The message to be sent is encrypted with AES 256 bit encryption using
// Spaniakos - AES Encryption Library.
// The built in M0 red LED will blink S-O-S upon startup if a hardware issue
// prevents initialization of the LoRa radio (typically wrong jumper wire
// or corresponding software settings).
// The built in M0 red LED will turn on briefly when a message is sent, and
// then it will go out when receipt confirmation (from receiver) is received.
// The M0 red LED will stay on if the receiver is not responding. But it will
// recover and begin sending again once the receiver is found.
// Resources:
// Pins 13, A7/9, 6, 10, 11, 5, A5/19
// M0 (Feather M0)
const byte pin_LED = 13;
const byte pin_BATT = A7;
//////////////////////////////////////////////////////////////////////////////
// 10000 ms = 10 sec = 0.1 Hz
// 1000 ms = 1 sec = 1 Hz
// 100 ms = 0.1 sec = 10 Hz
// 10 ms = 0.01 sec = 100 Hz
unsigned long timerInterval = random(500,5000);
unsigned long timerLast = 0; // timer
//////////////////////////////////////////////////////////////////////////////
// RHReliableDatagram is reliable in the sense that messages are acknowledged by the
// recipient, and unacknowledged messages are retransmitted until acknowledged or the
// retries are exhausted.
//////////////////////////////////////////////////////////////////////////////
// LoRa 900 MHz Radio
// RadioHead library for LoRa Radio
// http://www.airspayce.com/mikem/arduino/RadioHead/index.html
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
#include <SPI.h>
#define SENDER_ADDRESS 0x1 // This LoRa device
#define RECEIVER_ADDRESS 0x2 // The LoRa device that will receive messages from this device
// Feather M0 LoRa 900 MHz (AF product #3178)
//#define RFM95_INT 3
//#define RFM95_CS 8
//#define RFM95_RST 4
// Feather M0 (AF #2772) with the 900 MHz LoRa FeatherWing (AF #3231) stacked onto it.
#define RFM95_INT 6 // "D" alternative is 3
#define RFM95_CS 10 // "B" alternative is 8
#define RFM95_RST 11 // "A" alternative is 4
// Define frequency (set later)
#define RF95_FREQ 915.0
// RH_RF95 (uint8_t slaveSelectPin=SS, uint8_t interruptPin=2, RHGenericSPI &spi=hardware_spi)
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Class to manage message delivery and receipt, using the rf95 declared above
RHReliableDatagram manager(rf95, SENDER_ADDRESS);
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; // holds reply from receiver
//////////////////////////////////////////////////////////////////////////////
// Show serial messages when DEBUG = true, otherwise minimize them.
// WARNING: I experienced the Feather M0 waiting for the serial monitor to be
// loaded from the IDE before the sketch would continue to run.
// For this reason, I am wrapping serial output around a DEBUG check.
#define DEBUG false
//////////////////////////////////////////////////////////////////////////////
// Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi
// Download library from: https://github.com/spaniakos/AES/archive/master.zip
// https://spaniakos.github.io/AES/index.html
// https://www.arduinolab.net/aes-encryptiondecryption-using-arduino-uno/
#include <AES.h>
AES aes;
byte *key = (unsigned char*)"29304320399850709430905983949092"; // encryption key
unsigned long long int myIv = 36753562; // CBC initialization vector; real iv = iv x2 ex: 01234567 = 0123456701234567
byte iv [N_BLOCK] ;
boolean bVerbose = false;
// You must define arrays for encryption / decryption here globally
// if you intend to populate the contents of strToEncrypt in a loop
// where the contents change (such as sensor data).
// Define arrays for encryption.
byte iSizeUnpadded = 31;
byte iSizePadded = 33; // +17 works for any size. See setup() for calculation of exact padding.
byte arrToEncrypt[31]; // Array with data to be encrypted. arrToEncrypt[iSizePadded]
byte cipher[33]; // Encrypted arrToEncrypt. cipher[iSizePadded]
//////////////////////////////////////////////////////////////////////////////
unsigned long successCount = 0;
boolean bStopOnError = false;
//////////////////////////////////////////////////////////////////////////////
int iPIR = 0;
byte pinPIR = 5;
byte pirState = LOW;
byte pinMotionLED = A5; //19
void setup() {
pinMode(pin_LED, OUTPUT);
#if DEBUG
Serial.begin(9600);
while (!Serial) {
delay(1);
}
Serial.println("Serial ready");
#endif
// declare and initialize the variables for encryption / decryption
aes.iv_inc();
// Use the statement below to calculate the exact size for iSizePadded
//Serial.print("iSizePadded = "); Serial.println(sizeof(arrToEncrypt) + (N_BLOCK - ((sizeof(arrToEncrypt)-1) % 16)));
pinMode(pinPIR, INPUT);
delay(1);
pinMode(pinMotionLED, OUTPUT);
delay(1);
//////////////////////////////////////////////////////////////////////////////
// LoRa 900 MHz Radio
pinMode(RFM95_RST, OUTPUT);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
// manual reset
digitalWrite(RFM95_RST, LOW);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
if (!manager.init()) {
#if DEBUG
Serial.println("init failed");
#endif
while (1) blinkERR(pin_LED);
}
#if DEBUG
Serial.println("LoRa radio init OK!");
#endif
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
if (!rf95.setFrequency(RF95_FREQ)) {
#if DEBUG
Serial.println("setFrequency failed");
#endif
while (1) blinkERR(pin_LED);
}
#if DEBUG
Serial.print("LoRa to: "); Serial.print(RF95_FREQ); Serial.println(" Hz");
#endif
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// The default transmitter power is 13dBm, using PA_BOOST.
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
// you can set transmitter powers from 5 to 23 dBm:
rf95.setTxPower(23, false);
// If you are using Modtronix inAir4 or inAir9,or any other module which uses the
// You can optionally require this module to wait until Channel Activity
// Detection shows no activity on the channel before transmitting by setting
// the CAD timeout to non-zero:
// rf95.setCADTimeout(10000);
randomSeed(micros());
blinkLED(pinMotionLED);
blinkLED(pin_LED);
} // setup();
void loop() {
// Read the PIR sensor
if (digitalRead(pinPIR) == HIGH) {
if (pirState == LOW) {
// motion detected
pirState = HIGH;
digitalWrite(pinMotionLED, HIGH);
iPIR = 1;
}
} else {
if (pirState == HIGH) {
// motion ended
pirState = LOW;
digitalWrite(pinMotionLED, LOW);
iPIR = 0;
}
}
if (timerLast > millis()) timerLast = millis();
if ((millis() - timerLast) > timerInterval) {
// Send a message to manager_server
//blinkLED(pin_LED); // pretty, but consumes time
#if DEBUG
Serial.println("Sending encrypted data via RadioHead Reliable Datagram");
#endif
digitalWrite(pin_LED, HIGH);
// Send a 5 character unsigned integer (0 to 32767) + null char
int iTmp = iPIR;
WriteIntToByteArr(arrToEncrypt, sizeof(arrToEncrypt), iPIR);
iPIR = iTmp; // restore the value if iPIR because for some reason it is changed.
#if DEBUG
Serial.print("'");
for (int i=0; i < sizeof(arrToEncrypt); i++) {
Serial.print(char(arrToEncrypt[i]));
}
Serial.println("'");
#endif
int iSizePadded = sizeof(arrToEncrypt) + (N_BLOCK - ((sizeof(arrToEncrypt)-1) % 16)); // length of padded string
if (iSizePadded > sizeof(cipher)) {
#if DEBUG
Serial.print("ERROR - array size of cipher or arrDecryptedPadded is too small!");
#endif
while (1) blinkERR(pin_LED);
}
// Encrypt arrToEncrypt and update cipher with the result
aesEncrypt(256, bVerbose);
if (manager.sendtoWait(cipher, sizeof(cipher), RECEIVER_ADDRESS)) {
// Now wait for a reply from the server
uint8_t len = sizeof(buf);
uint8_t from;
if (manager.recvfromAckTimeout(buf, &len, 2000, &from)) {
#if DEBUG
Serial.print("Reply from : 0x");Serial.print(from, HEX);
Serial.print(": '"); Serial.print((char*)buf); Serial.println("'");
#endif
// Compare the received data buff to the data sent arrToEncrypt
int matches = 0;
for(int i=0; i < sizeof(arrToEncrypt); i++){
if(buf[i]==arrToEncrypt[i]){
matches++;
}
}
if (matches == sizeof(arrToEncrypt)) {
successCount++;
digitalWrite(pin_LED, LOW);
//iPIR = 0;
iPIR = iTmp;
}
#if DEBUG
Serial.print(matches/sizeof(arrToEncrypt)*100);
Serial.print("% match between arrToEncrypt and buff for size = ");
Serial.print(sizeof(arrToEncrypt)); Serial.print(" bytes ( encrypt/decrypt count = ");
Serial.print(successCount); Serial.println(") ");
if (matches != sizeof(arrToEncrypt)) {
Serial.print("ERROR after "); Serial.print(successCount); Serial.println(" encrypt/decrypt cycles");
Serial.print("sizeof(arrToEncrypt) = "); Serial.println(sizeof(arrToEncrypt));
Serial.print("matches = "); Serial.println(matches);
for(int i=0; i < sizeof(arrToEncrypt); i++){
Serial.print(i); Serial.print(",0x"); Serial.print(arrToEncrypt[i],HEX);
Serial.print(",0x"); Serial.println(buf[i],HEX);
}
if (bStopOnError == true)
while (1);
}
Serial.println();
#endif
} else {
#if DEBUG
Serial.println("No reply, is receiver running?\n");
#endif
}
} else {
#if DEBUG
Serial.println("sendtoWait failed\n");
#endif
}
timerInterval = 100;
//timerInterval = random(5,500);
timerLast = millis();
} // timer
} // loop()
////////////////////////////////////////////////////////////////
void blinkLED(byte ledPIN){
// consumes 300 ms.
for(int i = 5; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(30);
digitalWrite(ledPIN, LOW);
delay(30);
}
} // blinkLED()
void blinkERR(byte ledPIN){
// S-O-S
const int S = 150, O = 300;
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(O);
digitalWrite(ledPIN, LOW);
delay(O);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
} // blinkERR()
//////////////////////////////////////////////////////////////////////////////
// Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi
void aesEncrypt(int bits, boolean bVerbose) {
// Encrypts arrToEncrypt based on bits (256) bit encryption and updates
// cipher with the encrypted result.
aes.set_IV(myIv);
aes.get_IV(iv);
unsigned long us = micros ();
//Serial.print("aesEncrypt aes.get_size() = "); Serial.println(aes.get_size());
aes.do_aes_encrypt(arrToEncrypt,iSizeUnpadded+1,cipher,key,bits,iv);
if (bVerbose == true) {
Serial.print("Encryption took "); Serial.print(micros() - us); Serial.println(" us");
}
} // aesEncrypt()
//////////////////////////////////////////////////////////////////////////////
// Feather M0 specific functions
/*
dtostrf - Emulation for dtostrf function from avr-libc
Copyright (c) 2015 Arduino LLC. All rights reserved.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/avr/dtostrf.c
/*
char buff[14];
float f = -3.1415926;
Serial.print("f = ");Serial.println(f, 6);
sprintf(buff, "%E", f);
Serial.print("buff = '"); Serial.print(buff); Serial.println("'");
*/
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
asm(".global _printf_float");
char fmt[20];
sprintf(fmt, "%%%d.%df", width, prec);
sprintf(sout, fmt, val);
return sout;
} // dtostrf()
//////////////////////////////////////////////////////////////////////////////
void WriteIntToByteArr(byte *arr, int len, int &iVal) {
// Works on Feather M0 (ATSAMD21 Cortex M0)
// WARNING: Value of iVal may change due to sprintf()
for (int i=0; i<len; i++) {
arr[i] = 0x20; // space character
}
// ITOA() converts int to string
//itoa(iVal, cInt, 10);
char cInt[len-1];
sprintf(cInt, "%1u", iVal);
for (int i=0; i<strlen(cInt); i++) {
arr[i] = cInt[i];
}
arr[len] = 0x00; // null character
} // WriteIntToByteArr()
//////////////////////////////////////////////////////////////////////////////
// RV_PIR_Rx.ino
// Receives an encrypted message consisting of an integer that indicates
// if the PIR sensor at the sender has been triggered (0 = false, 1 = true).
// The digital output on pinPIR will change corresponding to the received
// PIR state (for the sender with the PIR sensor).
// This is a derivative of 'AF_Feather_M0_Basic_LoRa900MHz_ReliableDatagram_encrypted_recvr.ini'
// Reliable Datagram is reliable in the sense that messages are acknowledged by the
// recipient, and unacknowledged messages are retransmitted until acknowledged or the
// retries are exhausted.
// The message to be sent is encrypted with AES 256 bit encryption using
// Spaniakos - AES Encryption Library.
// The built in M0 red LED will blink S-O-S upon startup if a hardware issue
// prevents initialization of the LoRa radio (typically wrong jumper wire
// or corresponding software settings).
// The built in M0 red LED will turn on briefly when a message is received, and
// then it will go out when receipt confirmation is sent and received (it sends
// the message back to the sender unencrypted, and then the sender confirms
// receipt). Not production intent.
// Resources:
// Pins 13, A7/9, 6, 10, 11, 5
// M0 (Feather M0)
const byte pin_LED = 13;
const byte pin_BATT = A7;
//////////////////////////////////////////////////////////////////////////////
// LoRa 900 MHz Radio
// RadioHead library for LoRa Radio
// http://www.airspayce.com/mikem/arduino/RadioHead/index.html
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
#include <SPI.h>
#define SENDER_ADDRESS 0x1 // The LoRa device that sends messages to this device
#define RECEIVER_ADDRESS 0x2 // This LoRa device
// Feather M0 (AF #2772) with the 900 MHz LoRa FeatherWing (AF #3231) stacked onto it.
#define RFM95_INT 6 // "D" alternative is 3
#define RFM95_CS 10 // "B" alternative is 8
#define RFM95_RST 11 // "A" alternative is 4
// Define the frequency
#define RF95_FREQ 915.0
// Singleton instance of the radio rf95
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Class to manage message delivery and receipt, using the rf95 declared above
RHReliableDatagram manager(rf95, RECEIVER_ADDRESS);
byte buf[RH_RF95_MAX_MESSAGE_LEN];
/////////////////////////////////////////////////////////////////////////////\/
// Show serial messages when DEBUG = true, otherwise minimize them.
// WARNING: I experienced the Feather M0 waiting for the serial monitor to be
// loaded from the IDE before the sketch would continue to run.
// For this reason, I am wrapping serial output around a DEBUG check.
#define DEBUG false
//////////////////////////////////////////////////////////////////////////////
// Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi
// Download library from: https://github.com/spaniakos/AES/archive/master.zip
// https://spaniakos.github.io/AES/index.html
// https://www.arduinolab.net/aes-encryptiondecryption-using-arduino-uno/
#include <AES.h>
AES aes;
byte *key = (unsigned char*)"29304320399850709430905983949092"; // encryption key
unsigned long long int myIv = 36753562; // CBC initialization vector; real iv = iv x2 ex: 01234567 = 0123456701234567
byte iv [N_BLOCK] ;
boolean bVerbose = false;
// You must define arrays for encryption / decryption here globally
// if you intend to populate the contents of strToEncrypt in a loop
// where the contents change (such as sensor data).
// Define arrays for encryption
byte iSizeUnpadded = 31;
byte iSizePadded = 33; // =iSizeUnpadded+17 works for any size. See setup() for calculation of exact padding.
byte cipher[33]; // Encrypted arrToEncrypt. cipher[iSizePadded]
byte arrDecryptedPadded[33]; // decrypted cipher with padding. arrDecryptedPadded[iSizePadded]
byte decrypted[31]; // decrypted string without padding. decrypted[iSizeUnpadded]
//////////////////////////////////////////////////////////////////////////////
byte pinPIR = A4; // #18
void setup() {
pinMode(pin_LED, OUTPUT);
#if DEBUG
Serial.begin(9600);
while (!Serial) {
delay(1);
}
Serial.println("Serial ready");
#endif
// declare and initialize the variables for encryption / decryption
aes.iv_inc();
// Use the statement below to calculate the exact size for iSizePadded
//Serial.print("iSizePadded = "); Serial.println(sizeof(arrToEncrypt) + (N_BLOCK - ((sizeof(arrToEncrypt)-1) % 16)));
//////////////////////////////////////////////////////////////////////////////
// LoRa 900 MHz Radio
pinMode(RFM95_RST, OUTPUT);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
// manual reset
digitalWrite(RFM95_RST, LOW);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
while (!manager.init()) {
#if DEBUG
Serial.println("LoRa radio init failed");
#endif
while (1) blinkERR(pin_LED);
}
#if DEBUG
Serial.println("LoRa radio mgr init OK!");
#endif
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
if (!rf95.setFrequency(RF95_FREQ)) {
#if DEBUG
Serial.println("setFrequency failed");
#endif
while (1) blinkERR(pin_LED);
}
#if DEBUG
Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
#endif
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// The default transmitter power is 13dBm, using PA_BOOST.
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
// you can set transmitter powers from 5 to 23 dBm:
rf95.setTxPower(23, false);
// You can optionally require this module to wait until Channel Activity
// Detection shows no activity on the channel before transmitting by setting
// the CAD timeout to non-zero:
//rf95.setCADTimeout(10000);
pinMode(pinPIR, OUTPUT);
delay(1);
digitalWrite(pinPIR, LOW);
delay(1);
#if DEBUG
Serial.println("Setup complete\n");
#endif
blinkLED(pin_LED);
} // setup()
void loop() {
if (manager.available()) {
// Wait for a message addressed to us from the client
uint8_t len = sizeof(buf);
uint8_t from;
if (manager.recvfromAck(buf, &len, &from)) {
//blinkLED(pin_LED); pretty; but consumes time
digitalWrite(pin_LED, HIGH);
// Decrypt cipher, and update decrypted with the result
// clear cipher, arrDecryptedPadded, decrypted
for (int i=0; i < sizeof(cipher); i++) {
cipher[i] = 0x00;
}
for (int i=0; i < sizeof(arrDecryptedPadded); i++) {
arrDecryptedPadded[i] = 0x00;
}
for (int i=0; i < sizeof(decrypted); i++) {
decrypted[i] = 0x00;
}
// Assign the contents of buf to cipher
for (int i=0; i < sizeof(cipher); i++) {
cipher[i] = buf[i];
}
// Decrypt cipher, and update decrypted with the result
aesDecrypt(256, bVerbose);
#if DEBUG
Serial.print("From : 0x"); Serial.print(from, HEX); Serial.print(": '");
for (int i=0; i < sizeof(decrypted); i++) {
Serial.print(char(decrypted[i]));
}
Serial.print("' RSSI:");
Serial.println(rf95.lastRssi(),DEC);
#endif
// Send the decrypted message back to the originator client (sender).
// (In production you wouldn't send back the decrypted message)
if (!manager.sendtoWait(decrypted, sizeof(decrypted), from)) {
#if DEBUG
Serial.println("sendtoWait (reply) failed");
#endif
} else {
digitalWrite(pin_LED, LOW);
if (decrypted[0] == '1' && decrypted[1] == 0x20)
digitalWrite(pinPIR, HIGH);
else
digitalWrite(pinPIR, LOW);
}
#if DEBUG
Serial.print("decrypted[1]: "); Serial.println(char(decrypted[1]));
#endif
}
}
} // loop()
//////////////////////////////////////////////////////////////////////////////
void blinkLED(byte ledPIN){
// consumes 300 ms.
for(int i = 5; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(30);
digitalWrite(ledPIN, LOW);
delay(30);
}
} //blinkLED()
void blinkERR(byte ledPIN){
// S-O-S
const int S = 150, O = 300;
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(O);
digitalWrite(ledPIN, LOW);
delay(O);
}
delay(200);
for(int i = 3; i>0; i--){
digitalWrite(ledPIN, HIGH);
delay(S);
digitalWrite(ledPIN, LOW);
delay(S);
}
delay(200);
} // blinkERR()
//////////////////////////////////////////////////////////////////////////////
// Encryption using Spaniakos - AES Encryption Library for Arduino and Raspberry Pi
void aesDecrypt(int bits, boolean bVerbose) {
// Decrypt cipher and write to arrDecryptedPadded
aes.set_IV(myIv);
aes.get_IV(iv);
unsigned long us = micros();
aes.do_aes_decrypt(cipher,iSizeUnpadded+1,arrDecryptedPadded,key,bits,iv);
if (bVerbose == true) {
Serial.print("Decryption took "); Serial.print(micros() - us); Serial.println(" us");
}
// Create new array decrypted with the unencrypted content
// from arrDecryptedPadded excluding the padding.
for (int i=0; i < iSizeUnpadded; i++) {
decrypted[i] = arrDecryptedPadded[i];
}
} // aesDecrypt()
//////////////////////////////////////////////////////////////////////////////
Do you need help developing or customizing a IoT product for your needs? Send me an email requesting a free one hour phone / web share consultation.
The information presented on this website is for the author's use only. Use of this information by anyone other than the author is offered as guidelines and non-professional advice only. No liability is assumed by the author or this web site.