npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

llrpjs

v1.0.1

Published

A Low Level Reader Protocol (LLRP) library for node

Downloads

304

Readme

Low Level Reader Protocol (LLRP) library for node.

Synopsis & Motivation

LLRP (Low Level Reader Protocol) is a binary protocol published by EPCglobal Inc. to define the standard communication interface between RFID readers (servers) and clients. For more infomration, check out the LLRP standard definition.

The LLRP ToolKit (LTK) project was created back in 2008 by a group of companies and universities to help the development of LLRP-based applications. The toolkit provided support for many languages including C, C++, Java, Perl, etc. A year later, however, Node.js came around and opened the door to countless possibilities and proved to be one of the easiest and fastest ways to IoT development.

LLRP makes the perfect use case for JavaScript, given that it's a message-oriented protocol with many messages that are best handled asynchronously. See reader reports handling in the example below.

Example

llrpjs helps create programs for both servers (readers) and clients. The following example shows how to connect to a reader and collect EPC data of RFID tags.

const { LLRPClient, LLRPCore } = require("llrpjs");
const ADD_ROSPEC = require("./ADD_ROSPEC.json");

// create a client
const reader = new LLRPClient({ host: "192.168.7.2" });

// print RFID tags
reader.on("RO_ACCESS_REPORT", msg => {
    let tagReportDataList = msg.getTagReportData();
    if (!Array.isArray(tagReportDataList)) {
        tagReportDataList = [tagReportDataList]
    }
    for (let tagReportData of tagReportDataList) {
        let epc = tagReportData.getEPCParameter();
        console.log(`EPC: ${epc.getEPC()}`);
    }
});
reader.on("READER_EVENT_NOTIFICATION", msg => {
    // handle reader event notification messages here
});

reader.on("error", err => {
    // handle errors
});
reader.on("connect", () => {
    console.log("connected");
})
reader.on("disconnect", () => {
    console.log("disconnected");
});

/** Main */
(async () => {
    try {
        // connect to reader
        await reader.connect();
        // wait for connection confirmation
        await checkConnectionStatus();

        // delete all existing ROSpecs (if any)
        await reader.transact(new LLRPCore.DELETE_ROSPEC({
            data: { ROSpecID: 0 /** all */ }
        }));

        // factory reset
        await reader.transact(new LLRPCore.SET_READER_CONFIG({
            data: { ResetToFactoryDefault: true }
        }));

        // add ROSpec defined in "./ADD_ROSPEC.json"
        await reader.transact(new LLRPCore.ADD_ROSPEC(ADD_ROSPEC));

        // enable ROSpec
        const { ROSpecID } = ADD_ROSPEC.data.ROSpec;
        await reader.transact(new LLRPCore.ENABLE_ROSPEC({
            data: { ROSpecID }
        }));

        // start ROSpec
        await reader.transact(new LLRPCore.START_ROSPEC({
            data: { ROSpecID }
        }));

        console.log("Press ctrl+c to exit");
    } catch (e) {
        console.error(e);
        process.exit(1);
    }
})();

/**
 * wait for a READER_EVENT_NOTIFICATION message
 */
const checkConnectionStatus = async () => {
    let msg = await reader.recv(7000);
    if (!(msg instanceof LLRPCore.READER_EVENT_NOTIFICATION)) {
        throw new Error(`connection status check failed - unexpected message ${msg.getName()}`);
    }
    const status = msg.getReaderEventNotificationData().getConnectionAttemptEvent()?.getStatus();
    if (status != "Success") {
        throw new Error(`connection status check failed ${status}`);
    }
    return;
}

process.on("SIGINT", async () => {
    // request termination
    const rsp = await reader.transact(new LLRPCore.CLOSE_CONNECTION);
    if (rsp instanceof LLRPCore.CLOSE_CONNECTION_RESPONSE) {
        const status = rsp.getLLRPStatus();
        console.log(`${status.getErrorDescription()} - ${status.getStatusCode()}`)
    }
    // make sure it's disconnected
    if (reader.socketWritable) await reader.disconnect();
});

Static typing

llrpjs is written in TypeScript and provides static typing support:

JSON and JSON Schema support

llrpjs commits to the same goals set by the LTK project. However, llrpjs attempts at accomplishing some of these goals differently:

JSON over XML

The LTK project used XML to represent human-readable LLRP documents. However, given that JSON has out-of-the-box support in Node.js as well as many APIs and document-oriented databases (e.g. MongoDB), it makes sense to use it over XML in llrpjs. llrpjs uses a one-to-one mapping of the same XML format used in LTK:

llrpjs JSON (full example)

{
  "$schema": "https://llrpjs.github.io/schema/core/encoding/json/1.0/llrp-1x0.schema.json",
  "id": 103, "type": "ADD_ROSPEC",
  "data": {
    "ROSpec": {
      "ROSpecID": 1,
      "Priority": 0,
      "CurrentState": "Disabled",
      // ...
    }
  }
}

LTK XML (full example)

<ADD_ROSPEC MessageID='103'
  xmlns:llrp='http://www.llrp.org/ltk/schema/core/encoding/xml/1.0'
  xmlns='http://www.llrp.org/ltk/schema/core/encoding/xml/1.0'>
  <ROSpec>
    <ROSpecID>1</ROSpecID>
    <Priority>0</Priority>
    <CurrentState>Disabled</CurrentState>
    <!-- ... -->
  </ROSpec>
</ADD_ROSPEC>

JSON Schema over XSD

The LLRP JSON schema is generated from the source LTK definition and supports all types and formats. VSCode supports JSON schema out of the box:

CLI Tools

On installation, the package makes two CLI programs available: llrp2json and json2llrp. These commands can be used to convert binary llrp messages to JSON and the other way around. Use --help flag to get information on how to use.

Development

llrpjs uses the same definition llrp-1x0-def.xml set by the LTK project to generate runtime type definitions and schema. This library is written in TypeScript and allows dynamic static typing using a given LLRP definition. That said, llrpjs in itself is definition-agnostic, meaning that the code itself only conforms to the meta schema that was set by the LTK project (llrpdef.xsd) and any definition that complies with the meta schema can be used to generate types for llrpjs.

Check out llrpjs-tools for more information.

Author

Haytham Halimeh

Contributing

Contributions, issues and feature requests are welcome! Feel free to check issues page.

TODO

  • Tool to convert from llrpjs JSON to LTK XML and vice versa
  • Vendor definitions support
  • Documentation

Disclaimer

This project is independent.