Skip to content

Raspberry Pi

Connect sensors, buttons, LEDs, and more to your Meow Meow Scratch® API.


Setup

Install the SDK on your Pi:

pip install meow-sdk

Set your API key:

export MEOW_APP_API_KEY=YOUR_APP_API_KEY

Python version

The SDK works with Python 3.8+. Raspberry Pi OS ships with Python 3.11+.


Temperature & humidity (DHT22)

pip install adafruit-circuitpython-dht
import time
import adafruit_dht
import board
from meow_sdk import Meow

sensor = adafruit_dht.DHT22(board.D4)  # GPIO pin 4
api = Meow(api_key="YOUR_APP_API_KEY")

while True:
    try:
        api.send("my-pi", "climate", {
            "temperature": sensor.temperature,
            "humidity": sensor.humidity,
        })
        print(f"{sensor.temperature}°C, {sensor.humidity}%")
    except RuntimeError as e:
        # DHT sensors occasionally fail — just retry
        print(f"Sensor glitch: {e}")
    except Exception as e:
        print(f"API error: {e}")

    time.sleep(10)

Button press counter

import RPi.GPIO as GPIO
from meow_sdk import Meow

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

api = Meow(api_key="YOUR_APP_API_KEY")
count = 0

def on_press(channel):
    global count
    count += 1
    api.send("my-pi", "buttons", {"count": count, "pin": 17})
    print(f"Button pressed! Count: {count}")

GPIO.add_event_detect(17, GPIO.FALLING, callback=on_press, bouncetime=300)

print("Waiting for button presses... (Ctrl+C to exit)")
try:
    GPIO.wait_for_edge(17, GPIO.FALLING)  # keep alive
    while True:
        pass
except KeyboardInterrupt:
    GPIO.cleanup()

LED control from dashboard

Use a dashboard widget to control a physical LED:

import time
import RPi.GPIO as GPIO
from meow_sdk import Meow

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)

api = Meow(api_key="YOUR_APP_API_KEY")

while True:
    settings = api.get_payload("home", "settings")
    GPIO.output(17, settings.get("led_on", False))

    time.sleep(2)

Set up the dashboard:

admin = Meow(api_key="YOUR_PLATFORM_TOKEN")
admin.create_dashboard("My Room", "my-room")
admin.create_dashboard_widget(
    "my-room", "home", "settings",
    "led_on", "toggle", "LED Light"
)

Now toggle the LED from the web app or your phone.


Camera snapshot

pip install picamera2
import time
import base64
from picamera2 import Picamera2
from meow_sdk import Meow

cam = Picamera2()
cam.configure(cam.create_still_configuration())
cam.start()

api = Meow(api_key="YOUR_APP_API_KEY")

while True:
    cam.capture_file("/tmp/snapshot.jpg")

    with open("/tmp/snapshot.jpg", "rb") as f:
        img_b64 = base64.b64encode(f.read()).decode()

    api.set_payload("my-pi", "camera", {
        "image": f"data:image/jpeg;base64,{img_b64}",
        "captured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
    })

    print("Snapshot uploaded")
    time.sleep(60)

One-shot with CLI

Don't need a long-running script? Use the CLI in a cron job:

# Send a heartbeat every 5 minutes
*/5 * * * * MEOW_APP_API_KEY=YOUR_APP_API_KEY meow send my-pi heartbeat ts="$(date -u +\%Y-\%m-\%dT\%H:\%M:\%SZ)" host="$(hostname)"

Or read a value from a shell command:

# Send CPU temperature
meow send my-pi system cpu_temp=$(vcgencmd measure_temp | grep -o '[0-9.]*')

Run on boot with systemd

Create a service file so your script starts automatically:

sudo nano /etc/systemd/system/meow-sensor.service
[Unit]
Description=Meow Meow Scratch sensor
After=network-online.target
Wants=network-online.target

[Service]
User=pi
Environment=MEOW_APP_API_KEY=YOUR_APP_API_KEY
ExecStart=/usr/bin/python3 /home/pi/sensor.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable meow-sensor
sudo systemctl start meow-sensor

# Check status
sudo systemctl status meow-sensor

# View logs
journalctl -u meow-sensor -f

Tips

  • Rate limits — the API allows 300 requests per minute. A 10-second sleep() keeps you well under.
  • Error handling — always wrap sensor reads in try/except. Hardware is flaky. The script should never crash.
  • Offline buffering — if the network drops, catch the exception and queue data locally. Send it when the connection comes back.
  • Multiple sensors — send all readings in a single api.send() call rather than one per sensor. Fewer API calls, same data.
  • Static endpoints — use set_payload() for "current state" data (like a thermostat reading). Use send() for time-series data you want to keep.