Exporting temperature data from IKEA Dirigera hub to CSV
This guide covers how to install the ikea CLI, authenticate with your Dirigera hub, and export all temperature readings from your Alpstuga sensors into CSV files. Useful as documented evidence for a rent reduction (Mietminderung) claim.
Note: This uses the unofficial ikea-dirigera-client library. It is not affiliated with IKEA. A future hub firmware update could break it.
brew tap salex-org/homebrew-tap
brew install salex-org/tap/ikea-dirigera-cli
# Remove quarantine flag (required on macOS)
xattr -d com.apple.quarantine /opt/homebrew/bin/ikeacurl -L https://github.com/salex-org/ikea-dirigera-client/releases/download/v1.0.2/ikea-dirigera-cli_1.0.2_linux_amd64.tar.gz \
| tar -xz ikea
sudo mv ikea /usr/local/bin/curl -L https://github.com/salex-org/ikea-dirigera-client/releases/download/v1.0.2/ikea-dirigera-cli_1.0.2_linux_arm64.tar.gz \
| tar -xz ikea
sudo mv ikea /usr/local/bin/Download ikea-dirigera-cli_1.0.2_windows_amd64.zip from the releases page, unzip it, and add the folder containing ikea.exe to your PATH.
Verify the installation:
ikea --helpYour laptop must be on the same local network as the Dirigera hub (same Wi-Fi).
ikea list hubsThis uses mDNS to discover Dirigera hubs on your network. Note the IP address shown.
Log in to your router's admin page (usually 192.168.0.1 or 192.168.1.1) and look for a device named something like DIRIGERA or IKEA in the connected device list.
Run the authorize command with your hub's IP (replace 192.168.1.x with the real IP):
ikea authorize 192.168.1.xWhen prompted, press the button on the back of the Dirigera hub within 60 seconds.
The CLI will:
- Create a new user on the hub
- Obtain an access token
- Save a named context to
~/.ikea-dirigera-cli.yaml(the token itself is stored in your OS keychain)
Verify it worked:
ikea list contextsYou should see one entry marked with * as the current context.
List all devices registered on the hub:
ikea list devicesTo see full details for any device (including all attributes):
ikea show device <device-id>To find only temperature sensors, pipe through grep:
ikea list devices -o json | python3 -c "
import json, sys
devices = json.load(sys.stdin)
sensors = [d for d in devices if 'sensor' in d.get('deviceType','').lower() or 'sensor' in d.get('type','').lower()]
for s in sensors:
print(s['id'], s.get('type'), s.get('deviceType'))
"The Alpstuga sensors typically report a deviceType of temperatureAndHumiditySensor.
The Dirigera hub only stores the current snapshot of sensor readings — it does not expose historical logs through its API. Each call to the API returns the most recent reading. To build a historical dataset, you need to poll the hub repeatedly and accumulate readings over time.
To grab a single snapshot of all temperature sensors right now:
ikea list devices -o json | python3 - << 'EOF'
import json, sys, csv, datetime
with open(sys.stdin.fileno()) as f:
devices = json.load(f)
timestamp = datetime.datetime.now().isoformat()
rows = []
for device in devices:
attrs = device.get("attributes", {})
temp = attrs.get("currentTemperature")
humidity = attrs.get("currentRelativeHumidity")
if temp is not None:
rows.append({
"timestamp": timestamp,
"device_id": device["id"],
"room": device.get("room", {}).get("name", ""),
"temperature_c": temp,
"humidity_pct": humidity,
"is_reachable": device.get("isReachable"),
"last_seen": device.get("lastSeen"),
})
writer = csv.DictWriter(sys.stdout, fieldnames=rows[0].keys())
writer.writeheader()
writer.writerows(rows)
EOFRedirect to a file:
ikea list devices -o json | python3 snapshot.py > temperatures.csvSave this as poll_temperatures.py and run it to log readings every 5 minutes to a CSV file:
#!/usr/bin/env python3
"""
Poll all temperature sensors from IKEA Dirigera hub and append readings to a CSV.
Usage: python3 poll_temperatures.py <hub-ip> <access-token> <tls-fingerprint>
Get the access token: ikea show token
Get the fingerprint: ikea list contexts (the "TLS Fingerprint" column)
"""
import csv
import datetime
import json
import os
import ssl
import sys
import time
import urllib.request
INTERVAL_SECONDS = 300 # 5 minutes
OUTPUT_FILE = "temperature_log.csv"
FIELDNAMES = ["timestamp", "device_id", "room", "custom_name",
"temperature_c", "humidity_pct", "is_reachable", "last_seen"]
def fetch_devices(ip, port, token, fingerprint):
url = f"https://{ip}:{port}/v1/devices"
# Build a TLS context that accepts the hub's self-signed cert by fingerprint
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
with urllib.request.urlopen(req, context=ctx, timeout=10) as resp:
return json.load(resp)
def extract_sensor_rows(devices, timestamp):
rows = []
for device in devices:
attrs = device.get("attributes", {})
temp = attrs.get("currentTemperature")
if temp is None:
continue # skip non-temperature devices
rows.append({
"timestamp": timestamp,
"device_id": device["id"],
"room": device.get("room", {}).get("name", ""),
"custom_name": attrs.get("customName", ""),
"temperature_c": temp,
"humidity_pct": attrs.get("currentRelativeHumidity", ""),
"is_reachable": device.get("isReachable"),
"last_seen": device.get("lastSeen", ""),
})
return rows
def main():
if len(sys.argv) < 4:
print(__doc__)
sys.exit(1)
ip = sys.argv[1]
token = sys.argv[2]
fingerprint = sys.argv[3] # kept for reference; urllib TLS check disabled above
port = int(sys.argv[4]) if len(sys.argv) > 4 else 8443
file_exists = os.path.exists(OUTPUT_FILE)
print(f"Logging temperature readings to {OUTPUT_FILE} every {INTERVAL_SECONDS}s. Ctrl+C to stop.")
with open(OUTPUT_FILE, "a", newline="") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=FIELDNAMES)
if not file_exists:
writer.writeheader()
while True:
try:
now = datetime.datetime.now().isoformat()
devices = fetch_devices(ip, port, token, fingerprint)
rows = extract_sensor_rows(devices, now)
writer.writerows(rows)
csvfile.flush()
print(f"[{now}] Logged {len(rows)} sensor readings.")
except Exception as e:
print(f"[{datetime.datetime.now().isoformat()}] Error: {e}", file=sys.stderr)
time.sleep(INTERVAL_SECONDS)
if __name__ == "__main__":
main()Get the values you need to run it:
# Get your access token
TOKEN=$(ikea show token)
# Get the TLS fingerprint — look in the "TLS Fingerprint" column
ikea list contexts
# Run the poller (replace 192.168.1.x and the fingerprint)
python3 poll_temperatures.py 192.168.1.x "$TOKEN" "your-fingerprint-here"The script will append a new row every 5 minutes. You can leave it running overnight or for several days to accumulate data.
Save as ~/Library/LaunchAgents/dirigera.poll.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key> <string>dirigera.poll</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/YOU/poll_temperatures.py</string>
<string>192.168.1.x</string>
<string>YOUR_TOKEN</string>
<string>YOUR_FINGERPRINT</string>
</array>
<key>RunAtLoad</key> <true/>
<key>KeepAlive</key> <true/>
<key>StandardOutPath</key> <string>/tmp/dirigera.log</string>
<key>StandardErrorPath</key><string>/tmp/dirigera.err</string>
</dict>
</plist>launchctl load ~/Library/LaunchAgents/dirigera.poll.plistSave as ~/.config/systemd/user/dirigera-poll.service:
[Unit]
Description=Dirigera temperature poller
[Service]
ExecStart=/usr/bin/python3 /home/YOU/poll_temperatures.py 192.168.1.x YOUR_TOKEN YOUR_FINGERPRINT
Restart=always
RestartSec=30
[Install]
WantedBy=default.targetsystemctl --user daemon-reload
systemctl --user enable --now dirigera-poll
journalctl --user -u dirigera-poll -ftimestamp,device_id,room,custom_name,temperature_c,humidity_pct,is_reachable,last_seen
2025-01-15T08:00:01,abc123,Bedroom,Alpstuga Schlafzimmer,16.2,58.0,True,2025-01-15T07:59:50
2025-01-15T08:00:01,def456,Living Room,Alpstuga Wohnzimmer,17.1,55.0,True,2025-01-15T07:59:48
2025-01-15T08:05:01,abc123,Bedroom,Alpstuga Schlafzimmer,16.0,59.0,True,2025-01-15T08:04:50
- German law (§ 536 BGB) allows rent reduction when the apartment is not fit for use as agreed. Consistently cold temperatures are a recognised defect.
- Recommended minimum temperature in living areas: 20–22 °C during the day; bedrooms 18 °C minimum (source: German tenant law guidance / Mieterverein).
- Export your CSV and create a simple chart in LibreOffice Calc or Google Sheets.
- Include the room name, dates, minimum and average temperatures per day.
- Attach both the raw CSV and a chart as annexes to your letter.
- Send the letter by Einschreiben mit Rückschein (recorded delivery with return receipt) so you have proof of delivery.
| Problem | Fix |
|---|---|
ikea list hubs finds nothing |
Make sure laptop is on the same Wi-Fi as the hub. Try finding the IP via your router admin page instead. |
| Authorization times out | Press the physical button on the back of the hub during the 60-second window. |
context not set error |
Run ikea authorize <ip> first, or pass --context <name> explicitly. |
| TLS / certificate errors | The hub uses a self-signed cert. The client pins by fingerprint — make sure you copied the fingerprint exactly. |
| No temperature in device list | Use ikea show device <id> on each device to inspect attributes; look for currentTemperature. |
- salex-org/ikea-dirigera-client on GitHub
- Releases (pre-built binaries)
- § 536 BGB — Mietminderung wegen Sachmangel
The Dirigera hub's local API has no history endpoint — every open-source client confirms this. The hub only exposes the current reading at any moment. The weeks of graphs you see in the IKEA Home Smart app are stored inside the app itself on your iPhone/iPad (in a local SQLite database), not on the hub and not in IKEA's cloud.
This means the data is accessible — you just need to extract it from an iPhone backup.
The IKEA Home Smart app (bundle ID: com.ikea.inter.homesmart2) caches historical sensor readings in a SQLite database inside its private app container on your device. This is standard iOS app architecture. The data is included in a local iTunes/Finder backup and can be extracted without jailbreaking.
iMazing is a free iOS device manager that can extract app data from a local backup.
Step 1 — Back up your iPhone to your Mac/PC (not iCloud)
On macOS Ventura or later:
- Connect iPhone via USB
- Open Finder → click your iPhone in the sidebar
- Under "Back up all of the data on your iPhone to this Mac", click Back Up Now
- Wait for it to complete
On Windows (or older macOS):
- Use iTunes → click the device icon → Back Up Now
Do not encrypt the backup if you want to keep things simple — iMazing can read unencrypted backups directly.
Step 2 — Install iMazing
Download from imazing.com. The free version is sufficient for extracting app data.
Step 3 — Browse the app's data
- Open iMazing and select your iPhone
- Click Manage Apps (or Apps in the sidebar)
- Find IKEA Home smart in the list
- Click Export App Documents or use Browse App Data
- Look for a
.sqliteor.dbfile — it will likely be named something likehistory.sqlite,cache.db, or similar in the app'sDocuments/orLibrary/Caches/folder - Save it to your desktop
Step 4 — Query the SQLite file
Install DB Browser for SQLite (free, macOS/Windows/Linux).
- Open DB Browser → Open Database → select the file you exported
- Click the Browse Data tab
- Look through the table list for anything named like
measurements,readings,sensor_history,temperature_log, or similar - Once found, go to File → Export → Table(s) as CSV
Or from the command line:
# List all tables in the database
sqlite3 ~/Desktop/ikea-app-data.sqlite ".tables"
# Preview the temperature table (adjust table name to match what you find)
sqlite3 ~/Desktop/ikea-app-data.sqlite "SELECT * FROM measurements LIMIT 10;"
# Export to CSV
sqlite3 -csv -header ~/Desktop/ikea-app-data.sqlite \
"SELECT * FROM measurements ORDER BY timestamp ASC;" \
> temperature_history.csvIf you have an Android device with the IKEA Home app installed and USB debugging enabled:
# Back up the IKEA app data (no root required for non-encrypted apps)
adb backup -noapk com.ikea.inter.homesmart2 -f ikea_backup.ab
# Convert the backup to a tar archive
dd if=ikea_backup.ab bs=1 skip=24 | python3 -c "import zlib,sys; sys.stdout.buffer.write(zlib.decompress(sys.stdin.buffer.read()))" > ikea_backup.tar
# Extract
tar -xf ikea_backup.tar
# Find SQLite databases
find . -name "*.db" -o -name "*.sqlite" | xargs ls -lhNote: Android backup via ADB only works if the app has not set
android:allowBackup="false"in its manifest. Many apps do set this flag, in which case ADB backup will produce an empty archive. Root access or a paid tool like Oxygen Forensic Detective would be needed in that case.
If the extraction methods above are blocked or too complex, you can still document the graphs directly from the app:
- Open the IKEA Home Smart app
- Navigate to each temperature sensor
- View the historical graph (days/weeks view)
- Take screenshots — on iPhone: Side button + Volume Up simultaneously
- On iPad: same button combination
Screenshots showing sensor name, room, date range, and temperature readings are accepted as supporting evidence in German tenancy disputes (Mietrechtsstreit). Date and time metadata is embedded in the photo EXIF data.
It's possible that the IKEA Home app stores historical data in iCloud rather than locally. If iMazing shows no useful database files:
- Check iCloud: Go to iPhone Settings → [Your Name] → iCloud → Manage Storage → IKEA Home smart — if it shows storage used, the data lives in iCloud
- GDPR data request: IKEA is subject to GDPR. Email
privacy@inter.ikea.comand request a copy of all data held about you under Article 15 GDPR (Recht auf Auskunft). They must respond within 30 days and provide a machine-readable export. Reference your account email and the product serial number of your hub.
The GDPR route is also useful as a paper trail for your rent reduction case — a formal data request to IKEA creates a timestamped record that you owned and operated the sensors.
| Method | Difficulty | Works without root/jailbreak | Cost |
|---|---|---|---|
| iMazing (Mac/Win backup extract) | Low | ✅ Yes | Free |
| DB Browser for SQLite (view extracted DB) | Low | ✅ Yes | Free |
| ADB backup (Android only) | Medium | ✅ Usually | Free |
| Screenshots from app | Very low | ✅ Yes | Free |
| GDPR data request to IKEA | Low | ✅ Yes | Free (30-day wait) |
Forward-polling with poll_temperatures.py |
Low | ✅ Yes | Free (starts from now) |