Identify Device by QR Code

How to look up Haltian IoT device information using QR code data

Every Haltian device has a QR code containing its unique identifier (TUID). This guide shows how to query device information from Haltian IoT using QR code data.

Understanding Device Identifiers

Haltian devices use two types of identifiers:

IdentifierDescriptionExample
TUIDThingsee Unique Identifier - printed on device QR codeTSPR04EZU31901021
UUIDHaltian IoT internal identifier550e8400-e29b-41d4-a716-446655440000

The TUID is physically readable from the device, while the UUID is used in MQTT topics and API responses.

QR Code Format

Scanning a Haltian device QR code typically returns a URL like:

https://thingsee.com/d/TSPR04EZU31901021

The TUID is the last segment of the URL path.

Python Example: Device Lookup

#!/usr/bin/env python3
"""
Look up Haltian IoT device information using TUID from QR code.
"""

import requests
import re

# Haltian IoT API endpoint
API_URL = "https://api.eu.haltian.io/graphql"

# Your API credentials
API_KEY_ID = "your-api-key-id"
API_KEY_TOKEN = "your-api-key-token"


def extract_tuid_from_qr(qr_data: str) -> str:
    """
    Extract TUID from QR code data.
    
    Handles various formats:
    - Full URL: https://thingsee.com/d/TSPR04EZU31901021
    - Path only: /d/TSPR04EZU31901021
    - TUID only: TSPR04EZU31901021
    """
    # Pattern for TUID (starts with TS, followed by alphanumeric)
    pattern = r'(TS[A-Z0-9]+)'
    match = re.search(pattern, qr_data)
    
    if match:
        return match.group(1)
    
    raise ValueError(f"Could not extract TUID from: {qr_data}")


def get_device_by_tuid(tuid: str) -> dict:
    """
    Query Haltian IoT API to get device information by TUID.
    """
    # GraphQL query to find device by TUID
    query = """
    query GetDeviceByTuid($tuid: String!) {
        devices(filter: { tuid: $tuid }) {
            edges {
                node {
                    id
                    tuid
                    name
                    deviceModel {
                        name
                        manufacturer
                    }
                    state
                    lastSeenAt
                    space {
                        id
                        name
                        path
                    }
                    measurements(last: 5) {
                        edges {
                            node {
                                type
                                measuredAt
                                value
                            }
                        }
                    }
                }
            }
        }
    }
    """
    
    headers = {
        "Content-Type": "application/json",
        "X-API-Key-ID": API_KEY_ID,
        "X-API-Key-Token": API_KEY_TOKEN,
    }
    
    response = requests.post(
        API_URL,
        json={"query": query, "variables": {"tuid": tuid}},
        headers=headers
    )
    
    response.raise_for_status()
    result = response.json()
    
    if "errors" in result:
        raise Exception(f"GraphQL errors: {result['errors']}")
    
    devices = result["data"]["devices"]["edges"]
    
    if not devices:
        raise ValueError(f"No device found with TUID: {tuid}")
    
    return devices[0]["node"]


def main():
    """Main entry point."""
    # Example QR code data (replace with actual scanned data)
    qr_data = "https://thingsee.com/d/TSPR04EZU31901021"
    
    try:
        # Extract TUID from QR code
        tuid = extract_tuid_from_qr(qr_data)
        print(f"Extracted TUID: {tuid}")
        
        # Look up device
        device = get_device_by_tuid(tuid)
        
        # Display device information
        print(f"\n=== Device Information ===")
        print(f"UUID: {device['id']}")
        print(f"TUID: {device['tuid']}")
        print(f"Name: {device.get('name', 'N/A')}")
        print(f"Model: {device['deviceModel']['name']}")
        print(f"Manufacturer: {device['deviceModel']['manufacturer']}")
        print(f"State: {device['state']}")
        print(f"Last Seen: {device.get('lastSeenAt', 'N/A')}")
        
        if device.get('space'):
            print(f"\n=== Location ===")
            print(f"Space: {device['space']['name']}")
            print(f"Path: {device['space']['path']}")
        
        if device.get('measurements', {}).get('edges'):
            print(f"\n=== Recent Measurements ===")
            for edge in device['measurements']['edges']:
                m = edge['node']
                print(f"  {m['type']}: {m['value']} ({m['measuredAt']})")
                
    except ValueError as e:
        print(f"Error: {e}")
    except requests.RequestException as e:
        print(f"API Error: {e}")


if __name__ == "__main__":
    main()

GraphQL Query Details

Find Device by TUID

query GetDeviceByTuid($tuid: String!) {
  devices(filter: { tuid: $tuid }) {
    edges {
      node {
        id
        tuid
        name
        deviceModel {
          name
          manufacturer
        }
        state
        lastSeenAt
      }
    }
  }
}

Find Multiple Devices

To look up multiple devices at once:

query GetDevicesByTuids($tuids: [String!]!) {
  devices(filter: { tuids: $tuids }) {
    edges {
      node {
        id
        tuid
        name
      }
    }
  }
}

Mobile App Integration

When building a mobile app with QR scanning:

  1. Scan QR Code - Use device camera to scan the QR code
  2. Extract TUID - Parse the URL to get the TUID
  3. Query API - Use GraphQL to fetch device details
  4. Display/Process - Show device info or perform actions
# Simplified flow
def process_qr_scan(qr_data: str):
    tuid = extract_tuid_from_qr(qr_data)
    device = get_device_by_tuid(tuid)
    return {
        "uuid": device["id"],
        "tuid": tuid,
        "name": device.get("name"),
        "model": device["deviceModel"]["name"],
        "location": device.get("space", {}).get("name")
    }

TUID Format Reference

TUID format varies by device type:

Device TypeTUID PatternExample
Presence SensorTSPR*TSPR04EZU31901021
Environment SensorTSEN*TSEN01ABC12345678
GatewayTSGW*TSGW02XYZ98765432
Angle SensorTSAN*TSAN01DEF11223344

Next Steps