Demonstration of possible usage of the the NFCController class.

NFC SmartPoster example

Demonstration of possible usage of the the NFCController class.

The application creates a smart poster record and sends it when a connected peer requests it. The smart poster record generated contains:

  • A URI: https://www.mbed.com
  • A title: "mbed website"
  • An action: EXECUTE which asks the peer to open the URI.

Running the application

Verification of the sample application can be seen on any a smartphone with an NFC reader. After running you will be able to read the tag with an NFC tag reader application.

Information about activity is also printed over the serial connection - please have a client open. You may use:

Tera Term - https://ttssh2.osdn.jp/index.html.en

This example is known to work on boards connected to a PN512 shield.

SmartPoster.cpp

Committer:
mbed_official
Date:
2019-11-29
Revision:
6:52cd72e84703
Parent:
0:9a16c3f036b0

File content as of revision 6:52cd72e84703:

/* mbed Microcontroller Library
 * Copyright (c) 2018-2018 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SmartPoster.h"

#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/util.h"

using mbed::Span;

using mbed::nfc::ndef::MessageBuilder;
using mbed::nfc::ndef::RecordType;
using mbed::nfc::ndef::Record;
using mbed::nfc::ndef::RecordID;
using mbed::nfc::ndef::RecordPayload;
using mbed::nfc::ndef::common::span_from_cstr;
using mbed::nfc::ndef::common::Mime;
using mbed::nfc::ndef::common::Text;
using mbed::nfc::ndef::common::URI;

namespace {
static RecordType smart_poster_record_type()
{
    return RecordType(
        RecordType::well_known_type,
        span_from_cstr("Sp")
    );
}

static RecordType action_record_type() {
    return RecordType(
        RecordType::well_known_type,
        span_from_cstr("act")
    );
}

static RecordType size_record_type() {
    return RecordType(
        RecordType::well_known_type,
        span_from_cstr("s")
    );
}

static RecordType type_record_type() {
    return RecordType(
        RecordType::well_known_type,
        span_from_cstr("T")
    );
}

static size_t compute_record_size(const RecordType& type, const RecordPayload& payload)
{
    return MessageBuilder::compute_record_size(
        Record(
            type,
            payload,
            RecordID(),
            false,
            false
        )
    );
}

} // end of anonymous namespace


SmartPoster::SmartPoster(const URI &uri) :
    _uri(uri),
    _action(),
    _resource_size(0),
    _action_set(false),
    _resource_size_set(false)
{ }

void SmartPoster::set_title(const Text &text)
{
    _title = text;
}

void SmartPoster::set_icon(const Mime &icon)
{
    _icon = icon;
}

void SmartPoster::set_action(action_t action)
{
    _action = action;
    _action_set = true;
}

void SmartPoster::set_resource_size(uint32_t size)
{
    _resource_size = size;
    _resource_size_set = true;
}

void SmartPoster::set_resource_type(Span<const uint8_t> &type)
{
    _type.set_text(Text::UTF8, Span<const uint8_t>(), type);
}

bool SmartPoster::append_record(MessageBuilder &ndef_builder, bool is_last_record) const
{
    if (_uri.get_uri_field().empty()) {
        return false;
    }

    struct PayloadBuilder : MessageBuilder::PayloadBuilder {
        PayloadBuilder(const SmartPoster &sp) : sp(sp) { }

        virtual size_t size() const
        {
            return sp.get_uri_record_size() +
                sp.get_title_record_size() +
                sp.get_icon_record_size() +
                sp.get_action_record_size() +
                sp.get_resource_size_record_size() +
                sp.get_type_record_size();
        }

        virtual void build(const Span<uint8_t> &buffer) const
        {
            MessageBuilder smart_poster_builder(buffer);
            sp.append_title(smart_poster_builder);
            sp.append_icon(smart_poster_builder);
            sp.append_resource_size(smart_poster_builder);
            sp.append_type(smart_poster_builder);
            sp.append_action(smart_poster_builder);
            sp.append_uri(smart_poster_builder);
        }

        const SmartPoster &sp;
    };

    bool result = ndef_builder.append_record(
        smart_poster_record_type(),
        PayloadBuilder(*this),
        is_last_record
    );
    return result;
}

void SmartPoster::append_uri(MessageBuilder& builder) const
{
    _uri.append_as_record(builder, true);
}

size_t SmartPoster::get_uri_record_size() const
{
    return _uri.get_record_size();
}

void SmartPoster::append_title(MessageBuilder& builder) const
{
    if (_title.get_text().empty()) {
        return;
    }
    _title.append_as_record(builder);
}

size_t SmartPoster::get_title_record_size() const
{
    if (_title.get_text().empty()) {
        return 0;
    }

    return _title.get_record_size();
}

void SmartPoster::append_icon(MessageBuilder& builder) const
{
    if (_icon.get_mime_content().empty()) {
        return;
    }
    _icon.append_as_record(builder);
}

size_t SmartPoster::get_icon_record_size() const
{
    if (_icon.get_mime_content().empty()) {
        return 0;
    }

    return _icon.get_record_size();
}

void SmartPoster::append_action(MessageBuilder& builder) const
{
    if (!_action_set) {
        return;
    }

    const uint8_t action_value[1] = { _action };
    builder.append_record(
        action_record_type(),
        action_value
    );
}

size_t SmartPoster::get_action_record_size() const
{
    if (!_action_set) {
        return 0;
    }

    const uint8_t action_value[1] = { _action };

    return compute_record_size(
        action_record_type(),
        action_value
    );
}

void SmartPoster::append_resource_size(MessageBuilder& builder) const
{
    if (!_resource_size_set) {
        return;
    }

    uint8_t value[4];
    std::reverse_copy(&_resource_size, &_resource_size + 4, value);

    builder.append_record(
        size_record_type(),
        value
    );
}

size_t SmartPoster::get_resource_size_record_size() const
{
    if (!_resource_size_set) {
        return 0;
    }

    uint8_t value[4];

    return compute_record_size(
        size_record_type(),
        value
    );
}

void SmartPoster::append_type(MessageBuilder& builder) const
{
    if (_type.get_text().empty()) {
        return;
    }

    builder.append_record(
        type_record_type(),
        _type.get_text()
    );
}

size_t SmartPoster::get_type_record_size() const
{
    if (_type.get_text().empty()) {
        return 0;
    }

    return compute_record_size(
        type_record_type(),
        _type.get_text()
    );
}