Skip to content

TechPreacher/weather-receipts

Repository files navigation

weather-receipts

CI License: MIT Node

Print a weather forecast to a thermal receipt printer.

A small TypeScript / Node.js CLI that fetches a forecast from Open-Meteo and prints it to an Epson TM-T88V or TM-T88VII thermal printer (80 mm paper), optimized for the 40-character column width.

Weather forecast receipt

Features

  • Current conditions plus today's daily summary and an 8-slot hourly forecast (every 3 hours, 00:00-21:00), tomorrow-only view with its own hourly slots, or a multi-day rollup (1-7 days)
  • Metric or imperial units
  • Configurable default location via ~/.weather-receipts.config.json, override per run with --location
  • Connects to a printer over USB (libusb), raw TCP (network printers, port 9100 by default), or CUPS
  • No API key required — Open-Meteo is free for non-commercial use
  • Zero runtime dependencies beyond commander and usb

Example output

========================================
           WEATHER FORECAST
              Zurich, CH
        1 Jun 2026  17:00 GMT+2
========================================

NOW
----------------------------------------
                  24°C
              Partly cloudy

Feels like                          23°C
Humidity                             36%
Wind                          8 km/h WNW

----------------------------------------
TODAY                         Mon, Jun 1
----------------------------------------
  Light showers
  High                              24°C
  Low                               17°C
  Precip                          0.2 mm
  Wind max                        9 km/h
  Sunrise                          05:33
  Sunset                           21:14

----------------------------------------
HOURLY
----------------------------------------
  00:00   18°  Light rain            85%
  03:00   17°  Light showers         88%
  06:00   17°  Overcast              65%
  09:00   17°  Overcast              63%
  12:00   20°  Overcast               0%
  15:00   23°  Mainly clear           0%
  18:00   24°  Mainly clear           0%
  21:00   22°  Overcast               0%

       Powered by Open-Meteo

Requirements

  • Node.js 22 or newer (uses native fetch)
  • A supported thermal printer
    • Epson TM-T88V (USB VID/PID 04b8:0202)
    • Epson TM-T88VII (USB VID/PID 04b8:0e28)
    • Or any ESC/POS-compatible printer reachable over TCP or CUPS
  • For USB on macOS / Linux: libusb (bundled via the usb npm package's native bindings; you may need node-gyp build tools for first install)

Installation

git clone https://github.com/TechPreacher/weather-receipts.git
cd weather-receipts
npm install
npm run build

To run the CLI directly:

node bin/weather-receipts.js print

To install globally so weather-receipts is on your PATH:

npm link
weather-receipts print

Quick start

# Set a default location
weather-receipts config --set location="Zurich, CH"

# Print today's forecast
weather-receipts print

# Print tomorrow's forecast only
weather-receipts print --tomorrow

# Print the next 7 days
weather-receipts print --days 7

# One-off override
weather-receipts print --location "Tokyo, JP" --units imperial

Weather forecast types

Usage

weather-receipts [command] [options]

print (default)

Fetches and prints a weather forecast.

Option Description Default
-d, --days <n> Number of days to forecast (1-7); mutually exclusive with --tomorrow 1
-t, --tomorrow Print tomorrow's forecast only (daily summary + 8 hourly slots) off
-l, --location <text> Location query (e.g. "Zurich, CH", "Tokyo") from config
-u, --units <units> metric or imperial metric
-p, --printer <iface> usb, usb:VID:PID, tcp://host:port, or a CUPS printer name usb
--printermodel <m> t88v or t88vii (selects USB Product ID when --printer usb) t88v
--dry-run Print a decoded preview to the terminal (or raw ESC/POS bytes when piped to a file) off

config

Manages persistent configuration stored at ~/.weather-receipts.config.json.

Option Description
--show Print current configuration (default if no flags given)
--set <key=value> Set one configuration key
--reset Reset configuration to defaults

Allowed keys: location, units, printer, printermodel, timezone.

Examples:

weather-receipts config --show
weather-receipts config --set location="Zurich, CH"
weather-receipts config --set units=imperial
weather-receipts config --set printer="tcp://192.168.1.100:9100"
weather-receipts config --set printermodel=t88vii
weather-receipts config --reset

Location format

Locations are resolved through the Open-Meteo geocoding API. You can pass either a bare city name or "City, CC" / "City, Country":

weather-receipts print --location "Zurich"
weather-receipts print --location "Zurich, CH"
weather-receipts print --location "Zurich, Switzerland"
weather-receipts print --location "Springfield, US"

When a country qualifier is supplied, the resolver picks the first geocoding result that matches the ISO 3166-1 alpha-2 code or full name, falling back to the top hit if no match is found.

Printer setup

USB (default)

Plug an Epson TM-T88V or TM-T88VII into a USB port:

weather-receipts print --printer usb --printermodel t88v

If you have a different ESC/POS printer over USB, find its VID/PID with lsusb (Linux) or system_profiler SPUSBDataType (macOS), then:

weather-receipts print --printer usb:04b8:0202

macOS: the OS may claim the printer. The tool detaches the kernel driver automatically when needed. If you hit permission errors, run with sudo or grant your user access to the USB device.

Linux: create a udev rule so non-root users can talk to the printer. Example for an Epson VID:

SUBSYSTEM=="usb", ATTR{idVendor}=="04b8", MODE="0666"

Save to /etc/udev/rules.d/99-thermal-printer.rules and reload udev.

Network (TCP, raw port 9100)

weather-receipts print --printer tcp://192.168.1.100:9100

CUPS

If the printer is configured in CUPS (any name supported by lpstat):

weather-receipts print --printer "Epson_TM_T88V"

The tool spools the raw ESC/POS bytes via lp -o raw.

Development

# TypeScript watch build
npm run dev

# Run tests
npm test

# Watch tests
npm run test:watch

# Inspect the receipt buffer without a printer
node bin/weather-receipts.js print --location "Zurich, CH" --dry-run \
  > /tmp/receipt.bin

Project layout

src/
├── cli.ts                    # commander entry
├── commands/
│   ├── print.ts              # main: fetch + render + print
│   └── config.ts             # config get/set/reset
├── core/
│   ├── thermal-printer.ts    # EscPosBuilder + USB/TCP/CUPS senders
│   ├── weather-fetcher.ts    # Open-Meteo forecast client
│   ├── geocoder.ts           # Open-Meteo geocoding client
│   ├── receipt-builder.ts    # composes the ESC/POS receipt
│   └── config-manager.ts     # ~/.weather-receipts.config.json I/O
├── types/
│   ├── config.ts
│   └── weather.ts
└── utils/
    ├── formatting.ts         # temp, wind, precip, time helpers
    └── weather-codes.ts      # WMO code → description

Tests

Vitest covers the pure helpers, both API clients (with mocked fetch), and the receipt-builder (decoded text + 40-column width invariant + final cut command).

npm test

Acknowledgements

  • Open-Meteo for the free weather and geocoding APIs
  • Inspired by claude-receipts by Chris Hutchinson, whose ESC/POS builder and USB/CUPS handling served as the starting point for the thermal-printer code

License

MIT

About

Print weather reports on a thermal receipt printer.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages