Frontend

(May be password protected if the corresponding configuration option is disabled.)

Dashboard tab

(the contents and behavior depend on the user code being executed. May be hidden if the corresponding configuration option is disabled.)

Displays information about the current tag, if it is in the database. Otherwise, a locked sign is displayed.

Editor tab

(May be hidden if the corresponding configuration option is disabled.)

The contents of the usercode.py file are displayed.

  • Run - Write changes and reboot the device.
  • Read - drop all the unsaved changes made in the browser and reload the usercode.py file from the device's flash.
  • Write - write the contents of the editor to the usercode.py file on the flash.

See below for examples.

Settings tab

(May be password protected (in addition to the whole frontend) if the corresponding configuration option is disabled.)

In order to display the current configuration and start editing, press the Read button. When all the necessary changes are made, press the Write button to apply them.

RFID Settings

GUI Item Config key
Format string format
Protocol protocol
Destination IP dest
Port dport
Key type keytype
Key key

Notes:

  • Keys A/B are for the Mifare Classic card - Key field expects 12 hex digits.
  • Key UL is for the Mifare Ultralight card - Key field expects 8 hex digits.
  • Key PL is for the Mifare Plus card - Key field expects 32 hex digits.

Administration

GUI Item Config key
Protect Web with password web_auth
Protect Settings with password set_auth
Dash dash
Editor editor
WDT wdt

Notes:

  • If web password or settings password is set, it will not be displayed when Read button is pressed for security reasons. Before writing the settings, make sure you have retyped the required passwords.

Interface

GUI Item Config key
Language lang
IP type iptype
IP address ip
From 1 ip_start
To 1 ip_end
DNS dns

DataBase

Database entries:

  • Import - append entries from a CSV file to the current database.
  • Export - export the current database to a CSV file.
  • Clean - remove all entries from the database

Images:

  • Import - upload one or more images to the flash storage.
  • Export - download selected image from the flash storage.
  • Clean - remove all images stored in the flash.

Actions

  • Update - select and upload an update package. Do not interrupt, disconnect or reboot the device during the update process. It is recommended to reboot the device and reload the web page immediately after the update completion.
  • Reboot - reboots the device. The web page will be automatically reloaded. Please note, that if the device IP settings have changed, the device may receive a different IP address after a restart, in which case the web page will fail to reload.
  • To Bootloader
    • HTML Bootloader - this is the factory reset option. The flash contents will be wiped and a web-based bootloader will be started. The device will try to download the latest application files (i.e. the usercode, web interface etc.) from the internet and reboot. Should any of the operations fail, the device will stay in the web bootloader mode. You can access the device from within your LAN and upload the application files manually.
    • USB Bootloader - this option puts the device in the low-level bootloader (like the fastboot mode for the Android devices). The application and user files residing in the flash are not touched. Please proceed to this mode only if absolutely necessary and consult the documentation.

Usercode examples

Transmit UID over CAN

from canmgr import CANManager
from rfid import G_43dB
from time import time
from rfid_utils import CardFilter, Buzzer, RFID, GLED, RLED
from uasyncio import sleep_ms, get_event_loop
from binascii import unhexlify
from machine import WDT, reset
from config import settings
from webserver import erfid, eprint


VERSION = '2.0'
tcan = CANManager(int(settings['src']), int(settings['baud']))
buzz = Buzzer() if settings['buz'] else None
get_event_loop().create_task(tcan.task(delay=10))


async def can_rx(msg):
    print('From {}: {}'.format(*msg))
    payload = msg[1].decode()
    if payload == '~I':
        await tcan.send(('~I' + VERSION).encode())
    elif payload.startswith('~A'):
        settings['src'] = int(payload[2:])
        settings.write()
        await tcan.send(('~A{}'.format(settings['src'])).encode())
    elif payload.startswith('~D'):
        settings['dst'] = int(payload[2:])
        settings.write()
        await tcan.send(('~D{}'.format(settings['dst'])).encode())
    elif payload == '~R':
        RLED.on()
        await tcan.send(b'~R500')
        if buzz:
            buzz.off()
        print('Resetting...')
        await sleep_ms(500)
        reset()


async def run():

    tcan.filter(int(settings['dst']))
    tcan.set_rx_cb(can_rx)
    cardfilter = CardFilter(5)
    mfrc = RFID(gain=settings.get('gain', G_43dB),
                key=unhexlify(settings['key']), typ=settings['keytype'].encode())
    wdt = WDT(timeout=30000) if settings['wdt'] else None

    while 1:
        if wdt:
            wdt.feed()

        res = mfrc.read(settings.get('fmt', 'hU*'))
        if res and (res not in cardfilter):
            GLED.on()
            await eprint('UID: {}'.format(res))
            await erfid(res)
            cardfilter.append(res)
            await tcan.send(res)
            if buzz:
                await buzz.beep()
            await sleep_ms(500)
            GLED.off()
        await sleep_ms(100)
        cardfilter.clean(time())


  1. Visible only if the DHCP IP type is selected.