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

zephyr-binary-log-transformer

v1.2.0

Published

Transforms binary log format of Zephyr RTOS to a human readable form

Downloads

8

Readme

Zephyr Binary Log Transformer

Intro

This library implements a parser and two transform streams (one for browser and one for node.js) that can read binary log format of Zephyr RTOS (not pushed to main stream yet) and print it in a human-readable form.

The purpose of the binary format is to free space used by the log buffers on memory-constrained chips. To turn the binary format on use LOG_FORMAT_BINARY=y option in your KConfig.

In order for the library to be able to transform string pointers to the text, you need to provide the parser with a string map and the base address of the strings section in the RAM. Check LogParserOptions interface for more details.

Usage

To install the library use npm as usual:

npm install zephyr-binary-log-transformer --save

You may either use the parser directly or use one of the wrapping transform streams instead:

Node.js transform stream

Below is an example of how to implement a log transformer using JLink RTT Telnet in node.js.

The first step involves parsing a string map from a JSON file. The rodata_data field includes the string map in format "offset": "string value" and the rodata_sh_addr contains the address of the rodata section in the memory.

import * as fs from 'fs';
import * as net from 'net';
import { promisify } from 'util';
import { ParserEventLevel } from 'zephyr-binary-log-transformer/lib/parser';
import { LogStreamNode } from 'zephyr-binary-log-transformer/lib/log-stream-node';

const readFile = promisify(fs.readFile);

async function doIt() {
    const filePath = process.argv[2] || './zephyr-resources.json';

    try {
        const fileContent = await readFile(filePath);
        const data = JSON.parse(fileContent.toString('ascii'));
        const stringMap = new Map();
        Object.entries(data.rodata_data).forEach(([key, value]) => stringMap.set(+key, value));
        const stringsOffset = BigInt(data.rodata_sh_addr);

        const stream = new LogStreamNode({ stringMap, stringsOffset });
        stream.addEventListener((level, event) => console.log(`[${level}]: ${event}`), ParserEventLevel.Warning);
        stream.on('data', data => console.log(data.toString('ascii')));

        const socket = new net.Socket();
        socket.connect(19021, 'localhost');
        socket.pipe(stream);
    } catch (err) {
        console.error('Failed to read resources', err);
    }
}

doIt().then(
    () => console.log('Finished')
)  

Browser transform stream

Below is an example of how you can implement similar functionality in a web browser. This time the source is Web Serial API.

import { LogStreamBrowser } from 'zephyr-binary-log-transformer/lib/log-stream-browser';

async function startLogCapture() {
  const port = await navigator.serial.requestPort();
  await port.open(options);
  const transformer = new LogStreamBrowser({ stringMap, stringsOffset });
  const stream = port.readable.pipeThrough(new TransformStream(transformer));
  const reader = stream.getReader();

  readLoop(reader);
}

async function readLoop(reader) {
  while (true) {
    const { value, done } = await reader.read();
    if (value) {
      appendLogLine(value);
    }
    if (done) {
      reader.releaseLock();
      break;
    }
  }
}

Parser

If the transform streams don't fit your needs, you may use the parser directly. It's API is pretty straight-forward

import { LogParser, ParserEventLevel, ParserEventListener } from './parser';

const parser = new LogParser({ stringMap, stringsOffset });
parser.addMessageListener(msg => console.log(msg));         // Emitted for every transformed log line
parser.addEventListener(listener, ParserEventLevel.Debig);  // Optional, it may be used for diagnostics, details follow in the description

parser.feed(data);  // Send chunk of binary data to the parser any ArrayLike<number> value can be used

API Details

LogParser

Constructor

The constructor accepts a single parameter of type LogParserOptions, it has the following members:

  • stringMap: Map<number, string> (required): Maps offsets in the strings section in the firmware memory to concrete strings
  • stringsOffset: biging (required): Offset of the strings section in the firmware memory
  • emitIgnored: boolean (optional): If true, the parser will emit messages from characters it ignored (default is false)

The emitIgnored flag may come handy when the incoming data does also include some raw strings that are not binary encoded. This is for example the case of the JLink RTT Telnet where the incoming data start with a string header describing the version of JLink and data may be interleaved with string messages informing about dropped log lines. If the parser is waiting for the message preamble (0xfe) and this flag is set, it stores all the incoming characters different from 0xfe to a buffer. Once it receives the message preamble, it emits this whole buffer (parsed as string) as a message.

Message Event

All the transformed messages (and eventually ignored characters) are emitted asynchronously through this event. You attach a listener using addMessageListener(listener: MessageListener): void and eventually remove it using removeMessageListener(listener: MessageListener): void.

Diagnostic Events

If you have troubles with your log output, you may want to check the diagnostic events of the parser. Events have different levels from debug to error:

  • Error: Emitted only under serious conditions when something prevents parsing the message. Examples are missing entry in the string map or wrong binary data.
  • Warning: Emitted when parser ignores some incoming data
  • Info: Informative messages, currently not used
  • Debug: Detailed information about the parser state, incoming data and their handling

You can listen to diagnostic events using addEventListener(listener: ParserEventListener, minLevel: ParserEventLevel): void. minLevel specifies the minimum event level that you are interested in with debug being the lowest and error the highest. The listener then receives both the event level and event message (type ParserEventListener = (level: ParserEventLevel, message: string) => void;).

Data Feed

You feed the data into the parser using the feed(chunk: ArrayLike<number>): void method. You may feed the data in as they arrive, no matter if they are aligned to messages or not.

LogStreamNode

Both streams are essentially just wrappers around the LogParser class that adapt it to the appropriate stream API.

Constructor

You instantiate the LogStreamNode class using the same LogParserOptions interface as the LogParser class.

'data' event

Instead of the message listener, you consume the standard 'data' event of the stream.

Diagnostics

The stream still exposes the diagnostic events using the addEventListener(listener: ParserEventListener, minLevel: ParserEventLevel): void

Feeding data

To feed the data into the parser you write to the stream. Standard usage of the transform stream is to pipe it after your input stream.

LogStreamBrowser

Constructor

You instantiate the LogStreamBrowser class using the same LogParserOptions interface as the LogParser class.

Reader

Instead of the message listener, you use the stream reader using stream.getReader() and reading from it in a loop as shown in the example above.

Diagnostics

The stream still exposes the diagnostic events using the addEventListener(listener: ParserEventListener, minLevel: ParserEventLevel): void

Feeding data

To feed the data into the parser you write to the stream. Standard usage of the transform stream is to pipe your input stream through the transformer, e.g.

readable.pipeThrough(new TransformStream(new LogStreamBrowser(stringMap, stringsOffset)))

Format description

  • 1B Message Preamble (0xfe)
  • 1B Message Header
    • 1 Top-most bit = message type (0 = STD, 1 = HEXDUMP)
    • 3 bits = severity (0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug)
    • 4 bits = variadic arguments count (for STD message)
  • 4B Timestamp
  • 8B Pointer to message string

STD Message Variadic Arguments:

  • 1B Header
    • Topmost bit = type (0 = Uint, 1 = StringZ)
    • 7 lower bits = length in bytes (for Uint argument)
  • Argument value

HEXDUMP Message:

  • 4B length of the data
  • Data

RAW String messages are STD message with severity none, timestamp and string pointer 0 and 1 variadic StringZ argument