Software signing troubles swapping NRF24s radios and / or Arduinos [Sketches and pics inside]


  • Hardware Contributor

    Happy Xmas to all forum users!
    I need your help to focus and solve my troubles about NRF24, signing and Arduinos (UNO and nanos).

    Previously I did start another discussion about this, opening a new one 'cause I did collect other infos and I would restart the discussion from zero.

    Preamble > My environment

    ** Controller + Gateway **
    Domoticz as controller on a Raspberry PI2 + Arduino UNO as gateway + NRF24L01+ PA/LNA. Antenna is powered from a socket getting 5V from PI Gpio and converted to 3V3. PI itself is powered with a charger 5V / 2A. UNO has write in EEPROM a fixed software serial from the security personalizer sketch and shares the same AES KEY for all nodes.

    Current image of setup:

    alt text

    ** Nodes **
    I have 4 nodes with SI7021, custom PCBs, battery powered without boosters. NO signing, no security. They works perfectly.

    Software: they have a software serial and share the same AES KEY with all other nodes.

    3 of them have NRF24 black, I think counterfeit, but with 47uF caps on 3v3 and gnd. 1 of them has another type of NRF24, "red aliexpress version", with 47uF caps like others.

    This is the "red" version:

    alt text

    Heater commander relay node
    As name says, it's a node with a SI7021 + relay (based on secture actuator) that poweron the heater. It is on a custom PCB.

    Software: has a software serial and share the same AES KEY with all other nodes.

    alt text

    You can see DOUBLE caps on it. Cap on the antenna + caps on the PCB (47uF + 0.1uF). Powered from a 5V / 2A Samsung charger (you can see the AMS converting the 5V to 3v3 and TPs, voltage are perfect) it works perfectly with UNO gateway.

    That antenna was for testing solder, before mount on the wall. Now it has this kind of antenna:

    alt text

    It has security and whitelisting. Only because I don't want that another familty with mysensors could poweron my heater 😄 .

    The big troubles

    1 - If I swap the Antennas (BLACK LNA on relay node and GREEN on the gateway), security doesn't work. Period. Node relay wait for infinite for the nonce from gateway. I have 2x green and 4x black. I did try ALL antenna in every combination. No possibility to work.

    The log is:

    19544 Nonce requested from 0. Waiting...
    24549 Timeout waiting for nonce!
    

    2 - Sketch for Relay is a bit "fat". Uses 85% of memory. Cannot "put to diet". If I enable DEBUG + DEBUG SIGNING, it wait for infinite for

    2134 Waiting for GW to send signing preferences...
    

    The issues goes away when I comment both DEBUG or only the DEBUG_SIGNING. So, for debugging, need to remove the library for SI7021 and it's functions. Not very handly.

    3 - Yesterday I did change the UNO with a NANO (on the gateway). Used same antenna and same power shield (5V from PI > 3v3 to antenna). Security signing stop working. After some restart of relay secure node, got the signing working. Of course, I did personalized with same serial software of the UNO and the AES KEY. From an hardware view, I did "swap" an ATMEGA328 with another with same, same, same configuration. No reason to break the environment.

    For the moment (12h) all works, with the NANO. I cannot explain reason for relay node to make about 30/40 reset before re-start.

    So, now my questions.

    1. This is the GATEWAY UNO/NANO sketch. Based on the (looooong) preamble, is it right?

    TL;DR:

    • 1 gateway, software signing + software serial + aes key
    • 4 temperature nodes without security
    • 1 relay node with security
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    #define MY_DEBUG_VERBOSE_SIGNING //!< Enable signing related debug prints to serial monitor
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    #define MY_RF24_CHANNEL 125
    
    #define MY_SIGNING_SOFT
    #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
    #define MY_SIGNING_REQUEST_SIGNATURES
    
    #include <MySensors.h>
    #include <avr/wdt.h>
    
    void setup()
    {
      // Setup locally attached sensors
      wdt_enable(WDTO_2S);
    }
    
    void presentation()
    {
      // Present locally attached sensors
    }
    
    void loop()
    {
      // Send locally attached sensor data here
      wdt_reset();
    }
    

    2 - This is the RELAY secure sketch, reporting the temp and relay state. It is a bit fat, use 85% of resource and cannot enable DEBUG_SIGNING without removing the SI7021 library. Is it possible to put to diet? 🙂

     * DEFINE MYSENSORS SECTION
     */
    //#define MY_DEBUG                    // Enable Basic Debug
    //#define MY_DEBUG_VERBOSE_SIGNING    // Enable Signing Debug
    #define MY_RADIO_NRF24
    #define MY_RF24_CHANNEL 125
    #define MY_TRANSPORT_WAIT_READY_MS (5000)
    #define MY_SIGNING_SOFT
    #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
    #define MY_SIGNING_REQUEST_SIGNATURES
    #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x3B,0xF4,0x61,0xDF,0x1E,0x97,0xB1,0x2D,0xEC}}} // corretto!!!
    #define MY_NODE_ID 4               // Default ID
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    #define MY_WITH_LEDS_BLINKING_INVERSE
    #define MY_DEFAULT_ERR_LED_PIN 16
    #define MY_DEFAULT_TX_LED_PIN 15
    #define MY_DEFAULT_RX_LED_PIN 14
    
    #define MY_BAUD_RATE 57600
    
    /*
     * Relay section
     */
    #define RELAY_ON     1  // If logic of relay is inverted, invert here
    #define RELAY_OFF    0  // If logic of relay is inverted, invert here
    
    /**
     * PIN section
     */
    #define PIN_RELAY     4
    
    /**
     * Include libraries
     */
    #include <MySensors.h>
    #include "Adafruit_Si7021.h"
    #include <avr/wdt.h>
    
    /**
     * Define section.
     * 
     *    // NAME
     */
    #define SKETCH_NAME       "Termostato - I2C+Relay"
    #define SKETCH_VERSION    "2.2"
    
    //  CHILD ID
    #define CHILD_ID_TEMP     0
    #define CHILD_ID_HUM      1
    #define CHILD_ID_RELAY    2
    
    // initialize the sensor
    Adafruit_Si7021 sensor = Adafruit_Si7021();
    
    bool is_first_start = true;
    // offset of temperature
    float temperature_offset = -1.5;
    // the max temperature, after which automatically shutdown
    float max_temperature = 23;
    
    // storing for millis
    unsigned long previous_millis = 0;      // will store last time loop was executed
    // constants won't change:
    const long interval = 120000;            // interval at which to make the loop (milliseconds)
    // finally simply wait
      // 1000 millisecondi = 1 sec
      // 1000 * 30 sec = 30000 = 30 sec
      // 1000 * 60 sec = 60000 = 1 minuto 
      // 60000 * 2 = 120000 milli = 2 minuti
      // 60000 * 5 = 300000 millisecondi = 5 minuti
      //wait(120000);
      //wait(1000);
    
    #define MAX_RETRY_SEND_BEFORE_DELAY 30 // after this try, it will call delay
    
    /**
     * Mysensors message
     */
    // Initialize temperature message
    MyMessage msg_temperature(CHILD_ID_TEMP , V_TEMP);
    // Initialize humidity message
    MyMessage msg_humidity(CHILD_ID_HUM , V_HUM);
    // Initialize relay message
    MyMessage msg_relay(CHILD_ID_RELAY , V_STATUS);
    
    /**
     * Presentation.
     * 
     * Presents the child to the controller
     * 
     * @since 1.0
     * 
     */
    void presentation() {
    
      // send sketch name
      sendSketchInfo(SKETCH_NAME , SKETCH_VERSION);
      // Present all sensors to controller.
      // TEMPERATURE
      present(CHILD_ID_TEMP, S_TEMP);
      // HUMIDITY
      present(CHILD_ID_HUM , S_HUM);
      // RELAY
      present(CHILD_ID_RELAY , S_BINARY);
      
    }
    
    /**
     * Our Setup
     * 
     * @since 1.0
     */
    
    void setup() {
    
      // enable Watchdog to 2 seconds
      wdt_enable(WDTO_2S);
    
      // send a serial output to advice
      Serial.println("================================");
      Serial.println("=====>>>> Start sketch <<<<=====");
      Serial.println("================================");
      
      // Initialize relay
      initializeRelay();
    
      // Initialize sensor
      sensor.begin(); // si7021
      
    }
    
    /**
     * Relay initialization
     * 
     * @since 1.0
     */
    void initializeRelay() {
    
      pinMode(PIN_RELAY , OUTPUT);
      digitalWrite(PIN_RELAY , RELAY_OFF);
      
    }
    
    
    /**
     * Our loop
     * 
     * @since 1.0
     * 
     */
    void loop() {
    
      // check to see if it's time to execute the loop; that is, if the difference
      // between the current time and last time we executed the loop is bigger than
      // the interval at which you want to make the loop.
      unsigned long current_millis = millis();
    
      if ( (current_millis - previous_millis >= interval) || ( is_first_start == true ) ) {
    
        Serial.println("Time to do our loop!");
    
        // false the is_first_start;
        is_first_start = false;
    
        // update previous millis
        previous_millis = current_millis;
      
        // get the temperature from sensor
        String type = "temperature";
        float temperature = getDataFromSensor(type);
    
        if ( temperature >= max_temperature ) {
    
          digitalWrite(PIN_RELAY , RELAY_OFF);
          Serial.println("Temp is over, shutdown the relay");
          
        } else {
    
          Serial.println("Temp is not over");
          
        }
    
        if ( temperature < 100 ) {
          sendDataToGateway(type , temperature);
        }
        
        // get the humidity from sensor
        type = "humidity";
        float humidity = getDataFromSensor(type);
        // send hum to gateway
        if ( humidity < 100 ) {
          sendDataToGateway(type , humidity);
        }
      
        // send relay data to the gateway
        sendRelayToGateway();
    
      }
      
    
    }
    
    /**
     * Get the data from sensor
     * 
     * @param string the type of request for sensor
     * 
     * @return float the temperature
     * 
     * @since 1.0
     */
    float getDataFromSensor(String type) {
    
      float data;
      if ( type == "temperature") {
    
        data = sensor.readTemperature();
    
        Serial.print("Temp read direct from sensor is ");
        Serial.println(data);
    
        data = data+temperature_offset;
    
        Serial.print("Temp after apply offset is ");
        Serial.println(data);
    
      } else {
    
        data = sensor.readHumidity();
        
      }
      Serial.print("The read of ");
      Serial.print(type);
      Serial.print(" is ");
      Serial.print(data);
      Serial.print(", so returning is ");
      Serial.println(data);
      return data;
      
    }
    
    /**
     * Send relay state to the gateway
     * 
     * 
     * @since 1.0
     */
    void sendRelayToGateway() {
    
      bool current_state = digitalRead(PIN_RELAY);
    
      //current_state = !current_state; // delete if NOT inverted
    
      if (current_state == 1) {
    
        current_state = RELAY_ON;
        
      } else {
    
        current_state = RELAY_OFF;
        
      }
    
      //send(msg_relay.set(current_state) , true);
      bool transmission_was_ok = false;
      int i = 0;
      do {
    
        transmission_was_ok = send(msg_relay.set(current_state) , true);
    
        Serial.println("Send RELAY to the gateway.");
        Serial.print("Variable i is ");
        Serial.println(i);
        Serial.print("Variable transmission_was_ok value is ");
        Serial.println(transmission_was_ok);
        i++;
        wait(150);
      
        if ( i > MAX_RETRY_SEND_BEFORE_DELAY ) {
        
          delay(5000); // this delay will call watchdog!
            
        }
          
      } while (transmission_was_ok == false);
      
      
    }
     
    
    /**
     * Send the data to the gateway
     * 
     * @param string the type of data to send
     * @param float the data to send
     * 
     * @since 1.0
     */
    
    void sendDataToGateway(String type , float data) {
    
      bool transmission_was_ok = false;
      int i = 0;
      do {
    
        if ( type == "temperature" ) { 
        
          transmission_was_ok = send(msg_temperature.setSensor(CHILD_ID_TEMP).set(data,1) , true);
    
        } else {
    
          transmission_was_ok = send(msg_humidity.setSensor(CHILD_ID_HUM).set(data,1) , true);
          
        }
    
        Serial.print("Send data to the gateway, the type sending is ");
        Serial.println(type);
        Serial.print("Variable i is ");
        Serial.println(i);
        Serial.print("Variable transmission_was_ok value is ");
        Serial.println(transmission_was_ok);
        i++;
        wait(150);
      
        if ( i > MAX_RETRY_SEND_BEFORE_DELAY ) {
        
          delay(5000); // this delay will call watchdog!
            
        }
          
      } while (transmission_was_ok == false);
      
    }
    
    /**
     * Receive function from gateway
     * 
     * @since 1.0
     */
    void receive(const MyMessage &message) {
    
      /*Serial.println("-------------- DEBUG receive() ---------------");
      Serial.print("message.type value is ");
      Serial.println(message.type);
      Serial.println("------------------------------------------");
      Serial.print("message.getCommand() value is ");
      Serial.println(message.getCommand());
      Serial.println("------------------------------------------");*/
    
      if ( message.isAck() ) {
    
        /*if ( message.type == V_STATUS ) {
    
          Serial.println("Relay state transmitted");
          
        }
    
        if ( message.type == V_TEMP ) {
    
          Serial.println("Temperature transmitted");
          
        }*/
        
      }
    
      if ( !message.isAck() ) {
    
        if ( message.type == V_STATUS) {
      
          if (  message.getCommand() == 1 ) {
      
            bool received_state = message.getBool();
            Serial.print("We did receive a new value. Received_state value is ");
            Serial.println(received_state);
      
            if ( received_state == 1) {
      
              digitalWrite(PIN_RELAY , RELAY_ON);
              
            } else {
      
              digitalWrite(PIN_RELAY , RELAY_OFF);
              
            }
            
          }
          
        }
    
      }
    
    }
    

    Thank you and again Merry Xmas!


  • Contest Winner

    @sineverba
    Looks about right. You use the official release I can see. Because on development (and in v2.2) a gateway that require signatures will do it from all nodes without an additional flag to relax that option (you can read more on that in the documentation and in the security migration post here on the forum).
    As for your troubles, yes, using signing and encryption with full debug on atmga328p may lead to stack usage problems (stack growing into ram) which manifests as a warning from the linker on memory use. (and also as unpredictable execution behavior).
    If the problem dissappear by removing debug features or other components, this is the cause for the problem.

    Then you have to options.

    1. Reduce the size of your sketch by stripping away things you don't really need (debug options for instance only serve a purpose if you actually have a problem)
    2. Use a device with more ram.

    Happy holidays!


  • Contest Winner

    @sineverba one additional thing, you point out that you use the same AES key on all devices but it does not look like you actually enable encryption, so from the code you posted, it seem you don't use encryption. So the AES key is currently not used for anything.


  • Hardware Contributor

    @Anticimex Thank you! You confirm me that need 2 sketch version for relay. 1 sketch only with relay, to debug, full production with the temperature. SO i can debug.

    What do you think instead about point 1 and 3 ? 1 was swapping antennas and 2 was about swapping UNO / Nano.

    Happy holidays!

    PS Did not received email notification for post answer but it is enbled 😞


  • Contest Winner

    @sineverba regarding antenna swap, you probably affected rf performance and security require lossless rf link.
    As for switching between different atmga328p boards, the only difference is could think of would be that the radio power supply is also affected and again degrade the radio performence. If you get NACKs in the log, that is the problem.


 

386
Online

7.6k
Users

8.5k
Topics

91.3k
Posts