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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mehrwiedu/ecowitt-api

v0.1.3

Published

Transport-independent TypeScript SDK for local Ecowitt weather gateway integrations

Readme

@mehrwiedu/ecowitt-api

Transport-independent TypeScript SDK for local Ecowitt weather gateway integrations.

The package provides a high-level client, an MQTT transport, payload parsing, normalized weather observations, sensor diagnostics, unknown-field preservation, and log-safe payload sanitizing. It is intended to serve as the shared protocol layer for applications such as an ioBroker adapter.

Current status

The package currently provides:

  • a transport-independent EcowittClient,
  • an MQTT client transport,
  • parsing of URL-encoded Ecowitt payloads,
  • gateway metadata extraction,
  • typed and normalized weather measurements,
  • typed piezo-rain measurements,
  • typed WS90 diagnostic values,
  • preservation of unknown fields,
  • preservation of the original raw message,
  • masking of sensitive payload fields,
  • reconnect and transport-state events,
  • unsubscribe-capable event listeners,
  • TypeScript declarations and native ECMAScript modules.

The MQTT path has been validated live with an Ecowitt GW2000A gateway and a WS90 outdoor sensor.

Requirements

  • Node.js 22 or newer
  • ECMAScript modules

Installation

npm install @mehrwiedu/ecowitt-api

Quick start with MQTT

import {
    EcowittClient,
    EcowittMqttTransport,
} from "@mehrwiedu/ecowitt-api";

const transport = new EcowittMqttTransport({
    url: "mqtt://192.168.178.10:1883",
    topicFilter: "ecowitt/#",
    username: "ecowitt",
    password: process.env.ECOWITT_MQTT_PASSWORD,
    clientId: `my-ecowitt-client-${process.pid}`,
    clean: true,
    reconnectPeriodMs: 1000,
    connectTimeoutMs: 30000,
});

const client = new EcowittClient({
    transport,
});

client.onStateChanged((state) => {
    console.log("Ecowitt state:", state);
});

client.onObservation((observation) => {
    console.log(
        observation.gatewayId,
        observation.observedAt,
        observation.measurements,
    );
});

client.onDiagnostic((diagnostic, observation) => {
    console.log(
        observation.gatewayId,
        diagnostic.sensorModel,
        diagnostic.kind,
        diagnostic.value,
        diagnostic.unit,
    );
});

client.onError((error, message) => {
    console.error(
        "Ecowitt error:",
        error.message,
        message?.topic,
    );
});

await client.connect();

Disconnect the client during application shutdown:

await client.disconnect();

Client events

EcowittClient exposes the following event APIs:

  • onRawMessage(handler)
  • onObservation(handler)
  • onDiagnostic(handler)
  • onStateChanged(handler)
  • onError(handler)

Every registration method returns an unsubscribe callback:

const unsubscribe = client.onObservation((observation) => {
    console.log(observation.gatewayId);
});

unsubscribe();

The client forwards transport states and parses every received raw message into an EcowittObservation.

Parser errors are emitted through onError() and do not disconnect the transport. Exceptions thrown by raw-message, observation, diagnostic, or state listeners are also converted into client error events. Errors thrown by error handlers themselves are ignored to prevent recursive error emission.

MQTT transport

import {
    EcowittMqttTransport,
} from "@mehrwiedu/ecowitt-api";

const transport = new EcowittMqttTransport({
    url: "mqtt://192.168.178.10:1883",
    username: "ecowitt",
    password: "secret",
    topicFilter: "ecowitt/#",
});

Supported options:

  • url
  • username
  • password
  • topicFilter
  • clientId
  • clean
  • reconnectPeriodMs
  • connectTimeoutMs

Defaults:

  • topicFilter: ecowitt/#
  • clean: true
  • reconnectPeriodMs: 1000
  • connectTimeoutMs: 30000

The transport exposes these states:

  • disconnected
  • connecting
  • connected
  • disconnecting
  • reconnecting
  • error

Both connect() and disconnect() are safe to call repeatedly.

Parsing a payload directly

The parser can also be used independently from a transport:

import {
    EcowittMeasurementKind,
    parseEcowittPayload,
    type RawEcowittMessage,
} from "@mehrwiedu/ecowitt-api";

const message: RawEcowittMessage = {
    transport: "mqtt-client",
    topic: "ecowitt/3076F567649B",
    receivedAt: new Date(),
    payload:
        "PASSKEY=secret"
        + "&stationtype=GW2000A_V3.3.1"
        + "&dateutc=2026-07-22%2010%3A23%3A19"
        + "&model=GW2000A"
        + "&tempf=64.58"
        + "&humidity=69"
        + "&windspeedmph=2.01"
        + "&rrain_piezo=0.008"
        + "&ws90cap_volt=5.3"
        + "&wh90batt=3.28"
        + "&ws90_ver=161",
};

const observation = parseEcowittPayload(message);

const outdoorTemperature = observation.measurements.find(
    measurement =>
        measurement.kind
        === EcowittMeasurementKind.OutdoorTemperature,
);

console.log(observation.gateway);
console.log(outdoorTemperature);
console.log(observation.diagnostics);
console.log(observation.unknownFields);

Values are normalized to public SI-oriented units where appropriate:

  • Fahrenheit to degrees Celsius,
  • miles per hour to metres per second,
  • inches of rain to millimetres,
  • inches of mercury to hectopascals.

Every typed measurement retains its original field name and raw value.

Observation structure

EcowittObservation contains:

  • gatewayId
  • observedAt
  • receivedAt
  • gateway
  • measurements
  • diagnostics
  • unknownFields
  • rawMessage

Unknown fields are deliberately retained so that new Ecowitt firmware fields and additional sensor values are not silently discarded.

Sanitizing payloads

Ecowitt payloads may contain sensitive values such as PASSKEY or password. Sanitize a payload before writing it to logs:

import {
    sanitizeEcowittPayload,
} from "@mehrwiedu/ecowitt-api";

const safePayload = sanitizeEcowittPayload(
    "PASSKEY=secret&tempf=64.58",
);

console.log(safePayload);

Field-name matching is case-insensitive.

Recognized gateway metadata

  • model
  • stationtype
  • runtime
  • heap
  • dns_err_cnt
  • freq
  • interval
  • dateutc

Recognized measurements

Gateway and weather data

  • tempinf
  • humidityin
  • baromrelin
  • baromabsin
  • tempf
  • humidity
  • vpd
  • winddir
  • winddir_avg10m
  • windspeedmph
  • windgustmph
  • maxdailygust
  • solarradiation
  • uv

WS90 piezo rain

  • rrain_piezo
  • erain_piezo
  • hrain_piezo
  • last24hrain_piezo
  • drain_piezo
  • wrain_piezo
  • mrain_piezo
  • yrain_piezo
  • srain_piezo

WS90 diagnostics

  • ws90cap_volt
  • wh90batt
  • ws90_ver

Public API

The package exports:

  • EcowittClient
  • EcowittMqttTransport
  • normalizeEcowittMqttClientOptions
  • parseEcowittPayload
  • sanitizeEcowittPayload
  • EcowittPayloadError
  • EcowittMeasurementKind
  • EcowittMeasurementUnit
  • EcowittSensorDiagnosticKind
  • EcowittSensorDiagnosticUnit

It also exports the corresponding public TypeScript types for clients, transports, raw messages, observations, gateways, measurements, diagnostics, unknown fields, MQTT options, transport states, handlers, and unsubscribe callbacks.

See docs/API.md for the full API reference.

Examples

Development

npm install
npm run check

npm run check performs:

  1. TypeScript type checking
  2. unit tests
  3. a clean production build

Architecture

The design and transport boundaries are documented in docs/ARCHITECTURE.md.

License

MIT