Florian Mikulik
Created February 13, 2021 © LGPL

Drone access restriction by using NFC Tags

Bind the usage of a drone, may it be as the receiver of a drone-delivered package, or the pilot, to the possession of a special NFC card

IntermediateProtip20 hours15
Drone access restriction by using NFC Tags

Things used in this project

Hardware components

ACR122u
×1
NXP NavQ
×1

Software apps and online services

libnfc

Story

Read more

Code

MIFARE_Ultralight_read.c

C/C++
This code will connect to the NFC reader via LibNFC
/**
 * @file quick_start_example1.c
 * @brief Quick start example that presents how to use libnfc
 */

// To compile this simple example:
// gcc -o MIFARE_Ultralight_read MIFARE_Ultralight_read.c -lnfc

#include <stdio.h>
#include <stdlib.h>
#include <nfc/nfc.h>
#include <string.h>


const char* getfield(char* line, int num)
{
    const char* tok;
    for (tok = strtok(line, ";");
            tok && *tok;
            tok = strtok(NULL, ";\n"))
    {
        if (!--num)
            return tok;
    }
    return NULL;
}

static void
print_hex(const uint8_t *pbtData, const size_t szBytes)
{
  size_t  szPos;

  for (szPos = 0; szPos < szBytes; szPos++) {
    printf("%02x  ", pbtData[szPos]);
  }
  printf("\n");
}

int
main(int argc, const char *argv[])
{
  nfc_device *pnd;
  nfc_target nt;

  // Allocate only a pointer to nfc_context
  nfc_context *context;

  // Initialize libnfc and set the nfc_context
  nfc_init(&context);
  if (context == NULL) {
    printf("Unable to init libnfc (malloc)\n");
    exit(EXIT_FAILURE);
  }

  // Display libnfc version
  const char *acLibnfcVersion = nfc_version();
  (void)argc;
  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);

  // Open, using the first available NFC device which can be in order of selection:
  //   - default device specified using environment variable or
  //   - first specified device in libnfc.conf (/etc/nfc) or
  //   - first specified device in device-configuration directory (/etc/nfc/devices.d) or
  //   - first auto-detected (if feature is not disabled in libnfc.conf) device
  pnd = nfc_open(context, NULL);

  if (pnd == NULL) {
    printf("ERROR: %s\n", "Unable to open NFC device.");
    exit(EXIT_FAILURE);
  }
  // Set opened NFC device to initiator mode
  if (nfc_initiator_init(pnd) < 0) {
    nfc_perror(pnd, "nfc_initiator_init");
    exit(EXIT_FAILURE);
  }

  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));

  // Poll for a ISO14443A (MIFARE) tag
  const size_t szModulations = 1;
  const nfc_modulation nmMifare[1] = {
	{    .nmt = NMT_ISO14443A, .nbr = NBR_106}
  };


  printf("Polling for target...\n");
  //  while (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0);
  while(nfc_initiator_poll_target(pnd, nmMifare, szModulations, 0xFF, 0x05, &nt) <= 0);
 
 printf("Target detected!\n");


  printf("Tag UID: ");
  char curuid[15];
  if(nt.nti.nai.szUidLen == 7) sprintf (curuid,"%02X%02X%02X%02X%02X%02X%02X", nt.nti.nai.abtUid[0],nt.nti.nai.abtUid[1],nt.nti.nai.abtUid[2],nt.nti.nai.abtUid[3],nt.nti.nai.abtUid[4],nt.nti.nai.abtUid[5],nt.nti.nai.abtUid[6]);
  else if (nt.nti.nai.szUidLen == 4) sprintf (curuid,"%02X%02X%02X%02X", nt.nti.nai.abtUid[0],nt.nti.nai.abtUid[1],nt.nti.nai.abtUid[2],nt.nti.nai.abtUid[3]);
  else return 0; //No valid UID found

  printf("%s\n", curuid);


  //Read UID file and check if UID is there
  FILE* stream = fopen("/home/navq/nfc_example/uids.csv", "r");

  printf("Check if UID is in CSV file...\n");

    char line[128];
    while (fgets(line, 128, stream))
    {
        const char* uid = getfield(strdup(line), 1);
	const char* script = getfield(strdup(line), 2);

        if(strcmp(uid,curuid)==0)
	{
	  printf("UID found: %s\n", uid); 
	  //UID was found!
	  char command[120];
    	  sprintf(command,"%s%s", "sudo -u navq ", script);
	  int status = system(command);
	  printf("Run Command: %s\n",command);
	}
    }


 // int status = system("sudo -u navq ./test.sh");

/*
    printf("The following (NFC) ISO14443A tag was found:\n");
    printf("    ATQA (SENS_RES): ");
    print_hex(nt.nti.nai.abtAtqa, 2);
    printf("       UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
    print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen);
    printf("      SAK (SEL_RES): ");
    print_hex(&nt.nti.nai.btSak, 1);
    if (nt.nti.nai.szAtsLen) {
      printf("          ATS (ATR): ");
      print_hex(nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
    }
  */


  // Close NFC device
  nfc_close(pnd);
  // Release the context
  nfc_exit(context);
  exit(EXIT_SUCCESS);
}

nfc_arm_node.cpp

C/C++
Source of the ROS node that arms the drone, modified from the Offboard example code
#include <ros/ros.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>

mavros_msgs::State current_state;
void state_cb(const mavros_msgs::State::ConstPtr& msg){
    current_state = *msg;
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "nfc_arm_node");
    ros::NodeHandle nh;

    ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>
            ("mavros/state", 10, state_cb);
    ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>
            ("mavros/cmd/arming");

    //the setpoint publishing rate MUST be faster than 2Hz
    ros::Rate rate(20.0);

    // wait for FCU connection
    while(ros::ok() && !current_state.connected){
        ros::spinOnce();
        rate.sleep();
	ROS_INFO("No connection");   
	 }

    mavros_msgs::CommandBool arm_cmd;
    arm_cmd.request.value = true;

    ros::Time last_request = ros::Time::now();

    while(ros::ok() && !current_state.armed ){
            if((ros::Time::now() - last_request > ros::Duration(5.0))){
                if( arming_client.call(arm_cmd) && arm_cmd.response.success){
                    ROS_INFO("Vehicle armed");
			return 0;
                }
                last_request = ros::Time::now();
            }
        ros::spinOnce();
        rate.sleep();
    }

    return 0;
}

arm_drone.sh

BatchFile
Shell command to start a ROD node. source-commands are needed to set up the correct ROS environment
bash -c 'source /opt/ros/noetic/setup.bash;source /home/navq/catkin_ws/devel/setup.bash;rosrun nfc_arm nfc_arm_node' 

start_ROS1.sh

BatchFile
Start ROS1 and run NFC detection loop
#!/bin/sh

#Start ROS1 as user navq
bash -c 'source /opt/ros/noetic/setup.bash;source /home/navq/catkin_ws/devel/setup.bash;roslaunch mavros px4.launch fcu_url:="/dev/ttymxc2:921600" &'

#Run NFC detection loop
/home/navq/nfc_example/MIFARE_Ultralight_read

Credits

Florian Mikulik

Florian Mikulik

1 project • 0 followers

Comments