NodeMCU and RC522 and REST communication

Last time we made a device that reads RFID card and communicates with devices by broadcasting a message. This implies that on the same network a server must be. We can use another device to work as a proxy between reader and remote server but why? We can communicate directly with the server via HTTP requests and box can inform other devices about the result.

Code added to  NodeMCU Boilerplat@GitHub

Direct communication

To work on this we will change Python’s server to our needs. It will react to REST call and respond with JSON. As a base, we will use Flask. It is light and perfect for our case.

import random
from flask import jsonify
from flask import Flask

app = Flask(__name__)


@app.route("/card/<card_id>/<office_id>")
def card_read(card_id, office_id):
    if random.randint(0, 100) > 50:
        response = response_fail(card_id, office_id)
    else:
        response = response_ok(card_id, office_id)
    print(response)

    return jsonify(response)


def response_ok(cid, office_id):
    tmp = get_packet(office_id)
    tmp['parameters']['id'] = cid
    tmp['parameters']['response'] = 'OK'

    return tmp


def response_fail(cid, office_id):
    tmp = get_packet(office_id)
    tmp['parameters']['id'] = cid
    tmp['parameters']['response'] = 'ERROR'

    return tmp


def get_packet(office_id):
    return {
        'protocol': 'iot:1',
        'node': 'computer',
        'chip_id': 'd45656b45afb58b1f0a46',
        'event': 'rc522.response',
        'parameters': {
            'id': '',
            'response': '',
            'office_id': office_id
        },
        'targets': [
            'ALL'
        ]
    }

We have one route: /card/{id}/{officeid} . This uses the same randomization as the previous version and returns JSON response.
My device will work in a few places and I need to distinguish between them, that’s why I added office_id but I think it is better to send Node name. We will see how it ends.
It is a test script so there is no security, no secret token. Don’t do this on production 🙂 Always protect your endpoints!
How to start a script? On Windows open PS terminal and type:

$env:FLASK_APP="rc522_http_server.py"
flask run --host=0.0.0.0

or good old cmd:

set FLASK_APP=rc522_http_server.py
flask run --host=0.0.0.0

We may return to NodeMCU. First, let’s add server URL to parameters

RC522_SERVER_URL = "http://192.168.1.102:5000/card/"

Next, we can remove handler and server listener. We are ready to refactor callback in init function, it comes in the package with two timers:

clear_last = tmr.create()
clear_last:register(LED_CONFIRM_LEN, tmr.ALARM_AUTO, function()
    last = ""
    triled.clear()   
    clear_last:stop()
end)

response_timeout = tmr.create()
response_timeout:register(5000, tmr.ALARM_AUTO, function()
    last = ""
    triled.clear()
    triled.red(true, LED_CONFIRM_LEN)
    response_timeout:stop()
end)

rc522.init(function(cardid) 
    print("Tag Found: "..cardid)   
    triled.clear()
    triled.blue(true)
    response_timeout:start() 
    http.get(RC522_SERVER_URL..cardid.."/"..NODE_ID, nil, function(code, data)
        if code == 200 then
            response = network_message.decodeMessage(data)
            if response == nil then
                print('not decoded')
            elseif last ~= nil and response.parameters.id == last then
                response_timeout:stop()                               
                print(response.parameters.response)
                triled.clear()      
                if response.parameters.response == 'OK' then triled.green(true) else triled.red(true) end        
                clear_last:start() 
            end
        else
            print('response problems')    
        end
    end)   
end)

We have two timers instead of one. The response_timeout will handle all network errors, failed connection, wrong response and such.
The clear_last timer clears variable and LED after a defined number of seconds. This also locks the device for some time.

And I just noticed something.. variable last is global but it should be bound to the RC522 module. Fixed, all instances of last in RC522 module changed to RC522.last and in main changed to rc522.last.

So my first test and… nothing… strange.
After some debugging (and time) I found out that the new tag I was using has code with length 9 and until now all have length 10. I’m not sure if this is error in card or my wrong assumption… but if with length check changed to 7 chars 🙂

Summary

This post shows that the Node can be used with an external server. This is second way, first is with broadcast messages.

Advertisements

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s