AI-Assisted Migration
Use these prompts with your preferred AI assistant (ChatGPT, Claude, Gemini, etc.) to get hands-on help migrating your integration code. Each prompt contains the full technical context needed — just paste your existing code at the end.
How to Use
Before pasting code into any AI tool, remove or mask all sensitive values: API keys, passwords, tokens, certificates, private keys, connection strings, and internal hostnames. Replace them with synthetic placeholders (e.g. YOUR_API_KEY_HERE, mqtt.example.com).
- Copy the prompt for your migration task
- Paste it into your AI assistant
- Append your current integration code where indicated (with credentials redacted)
- The AI will analyze your code and produce updated versions with step-by-step explanations
AI-generated code should always be reviewed and tested. Use these prompts as a starting point — validate the output against the Haltian IoT API documentation before deploying to production.
If your code parses specific Thingsee message fields (tsmId + field names), include the relevant rows from the Measurement Mapping reference to give the AI the exact field-name translations.
1. MQTT Stream Migration
Use this when migrating from Thingsee MQTT data streaming to Haltian IoT Stream API (MQTT).
You are an IoT integration specialist helping me migrate my MQTT integration
from Thingsee IoT to Haltian IoT. Analyze my current code and guide me through
the required changes.
## Platform Differences
### Authentication
- OLD (Thingsee): Client certificate authentication using .pem and .key files,
no username/password
- NEW (Haltian IoT): API key authentication — API Key ID as username, API Key
Token as password. No client certificates. Tokens are valid for 90 days.
Use the Service API query `apiKeys { token { expiresAt } }` to check expiry.
Refresh via `refreshApiKeyToken` mutation (old token is invalidated immediately;
plan for a brief MQTT reconnection window).
### Topic Structure
- OLD: cloudext/json/{product}/{region}/{customer}/{TUID}/{messageProfileId}/{tsmEv}
Where tsmEv is the event type code indicating why the message was sent
(e.g. 10=periodic/timed, 7=state change, 8=sensor trigger).
Subscription pattern: cloudext/json/pr/#
- NEW: haltian-iot/events/{integration-id}/{api-key-id}/{event-kind}/{measurement-type}/{device-uuid}
Subscription pattern: haltian-iot/events/{integration-id}/{api-key-id}/#
You can filter by measurement type in the topic
(e.g. .../measurements/ambient_temperature/#)
Note: measurement-type uses snake_case (ambient_temperature, battery_voltage,
occupancy_status). See the Stream API reference for exact event-type names.
Note: Haltian IoT does not have a direct equivalent to the event type code —
all messages are delivered as measurement events regardless of trigger reason.
### Payload Format
- OLD (Thingsee): Multi-field JSON with metadata embedded in each message:
{"tsmId": 2100, "tsmEv": 7, "tsmTs": 1747646772,
"tsmTuid": "TSPR04EZU31901021", "tsmGw": "TSGW01ABC12345678",
"ambient_temperature": 23.5, "humidity": 45.2}
- NEW (Haltian IoT): Minimal JSON — context comes from the topic path:
{"measured_at": "2025-01-28T08:52:11.626Z", "value": 23.5}
### Device Identifiers
- OLD: TUID is in both the topic path AND the message payload
- NEW: UUID is in the topic path ONLY (not in payload). UUID is not printed on
the device. The human-readable vendor ID (printed on QR code/label) corresponds
to `identifiers.vendorSerial` in GraphQL queries. Use vendorSerial or query the
Service API to map between UUID, vendorSerial, and TUID.
### Timestamps
- OLD: Unix epoch integer (e.g. 1747646772)
- NEW: ISO 8601 string (e.g. "2025-01-28T08:52:11.626Z")
### Measurement Model
- OLD: One message may contain multiple sensor readings grouped by message
profile (e.g. tsmId 2100 = environment profile with temperature + humidity)
- NEW: Each measurement type is a separate MQTT message on its own topic
## Your Task
1. Review my current MQTT integration code (pasted below)
2. Identify all sections that need changes for the migration
3. Provide updated code with:
- API key authentication replacing certificate auth
- New topic subscription pattern
- New message parsing logic (extract device UUID from topic, parse ISO 8601
timestamp, handle single-value payload)
- UUID-to-TUID mapping logic if my application uses TUIDs internally
4. Flag any credential refresh handling I should implement (90-day token expiry)
5. Highlight breaking changes that could cause silent data loss if missed
## My Current Code
[PASTE YOUR MQTT CLIENT CODE HERE]
2. REST API to GraphQL Service API Migration
Use this when migrating from Thingsee Open Service API (REST) to Haltian IoT Service API (GraphQL).
You are an IoT platform integration specialist helping me migrate from the
Thingsee Open Service API (REST) to the Haltian IoT Service API (GraphQL).
Analyze my current code and produce the equivalent GraphQL implementation.
## Platform Differences
### Authentication
- OLD (Thingsee): POST /auth/client-token with client_id and client_secret,
returns a 15-minute JWT. Multiple simultaneous tokens allowed.
Header: Authorization: Bearer {token}
- NEW (Haltian IoT): GraphQL login mutation with email, organizationName, and
password. Returns accessToken (15 min) and refreshToken (12 hours).
Header: Authorization: Bearer {accessToken}
Refresh via RefreshMutation before accessToken expires.
### API Style
- OLD: REST with URL path parameters (e.g. GET /things/{tuid}/messages?limit=10)
- NEW: GraphQL with typed queries, variables, and field selection
Endpoint: POST https://{api-url}/v1/graphql
Body: {"query": "...", "variables": {...}}
### Device Identity
- OLD: Devices identified by TUID in URL paths
- NEW: Devices identified by UUID (internal). TUID available as a cross-reference
in device.identifiers.tuid field. The human-readable vendor ID (printed on
QR code/label) corresponds to `identifiers.vendorSerial` in GraphQL queries.
### Endpoint Mapping
| Thingsee REST | Haltian IoT GraphQL | Notes |
|---------------|---------------------|-------|
| POST /auth/client-token | mutation login(...) | Returns accessToken + refreshToken |
| GET /things/{tuid} | query { devices(where: {identifiers: {tuid: {_eq: "..."}}}) {...} } | Search by TUID, returns UUID and all fields |
| GET /things/{tuid}/messages | query { measurementLast...(where: {deviceId: {_eq: $uuid}}) {...} } | Query by measurement type, not message profile |
| POST /things/{tuid}/commands | Not yet available via GraphQL | Contact Haltian for device configuration |
| GET /things/{tuid}/alerts | No direct equivalent — implement alerting in your integration by subscribing to measurement streams and applying threshold rules | Build your own alert logic |
| POST /things/{tuid}/installations | Managed via Haltian Field app | Device lifecycle in mobile app |
| GET /groups | query { devices(where: {keywords: {keyword: {_eq: "#dg-groupname"}}}) {...} } | Deployment groups → keywords |
| POST /groups | Use keywords on devices | No explicit group creation needed |
| POST /things/{tuid}/group | mutation assignDeviceKeyword(...) | Assign keyword instead |
### Data Structure Changes
- OLD: Flat device list with deployment groups
- NEW: Hierarchical: Organization > Space > Zone > Device
- Deployment groups can be mapped to keywords (e.g. #dg-northern-finland)
- Devices can be assigned to Spaces (physical locations)
- Keywords support arbitrary grouping and filtering
### GraphQL Login Example
mutation Login($email: String!, $organizationName: String!, $password: String!) {
login(loginInput: {
email: $email, organizationName: $organizationName, password: $password
}) {
accessToken
expiresIn
refreshToken
refreshExpiresIn
organizationId
}
}
### GraphQL Device Query Example
query DevicesByTextSearch($searchText: String) {
devices(where: {
_or: [
{identifiers: {vendorSerial: {_ilike: $searchText}}}
{name: {_ilike: $searchText}}
]
}) {
id
name
lastSeen
availableMeasurements
identifiers { tuid vendorSerial wirepasNodeId }
keywords { keyword }
deviceType { make model productName }
}
}
### GraphQL Measurement Query Example
query MeasurementLastAmbientTemperature($device: uuid) {
measurementLastAmbientTemperature(where: {deviceId: {_eq: $device}}) {
deviceId
measuredAt
ambientTemperature
}
}
Note: The value field name matches the measurement type (e.g. ambientTemperature,
batteryVoltage, occupancyStatus). For special cases, consult the GraphQL schema
for available field names.
## Your Task
1. Review my current REST integration code (pasted below)
2. Map each REST API call to its GraphQL equivalent
3. Provide updated code with:
- GraphQL login replacing client-token auth
- Token refresh logic (accessToken expires in 15 min, refreshToken in 12 hours)
- Device queries using UUID with TUID cross-reference where needed
- Measurement queries replacing message fetching (individual types, not profiles)
- Keyword-based grouping replacing deployment groups (if applicable)
4. For any Thingsee features without a direct GraphQL equivalent (commands,
installation status), explain the alternative approach
5. Highlight changes that affect data semantics (not just syntax)
## My Current Code
[PASTE YOUR REST API INTEGRATION CODE HERE]
3. Data Model and Device Identity Migration
Use this when your application stores Thingsee device data locally (databases, caches, dashboards) and you need to restructure for Haltian IoT’s hierarchical model.
You are a data architect helping me restructure my application's data model
from the Thingsee IoT flat structure to the Haltian IoT hierarchical model.
Analyze my current schema/code and propose the migration.
## Platform Differences
### Device Identity
- OLD (Thingsee): Each device identified by a TUID (e.g. "TSPR04EZU31901021").
TUID is printed on label, used in APIs, and appears in data streams.
- NEW (Haltian IoT): Primary identifier is UUID (internal, assigned by platform).
Not printed on device. The human-readable vendor ID (printed on QR code/label)
corresponds to `identifiers.vendorSerial` in GraphQL queries. TUID is preserved
as a cross-reference in device.identifiers.tuid.
Data streams and APIs use UUID exclusively.
### Organizational Structure
- OLD: Flat structure:
- Devices belong to deployment groups (simple string labels)
- No hierarchy beyond device → group
- Installation status tracks device lifecycle (new/installed/uninstalled/quarantine/retired)
- NEW: Hierarchical structure:
Organization > Space > Zone > Device
- Organization: top-level tenant (your company)
- Space: physical location with hierarchy (building > floor > area)
- Zone: polygon region within a space (meeting room, desk area, parking slot)
- Device: sensor or gateway, assigned to a space with optional coordinates
Plus flexible metadata:
- keywords: tags for grouping/filtering (replaces deployment groups)
- externalId: your own ID from another system
- name: free-form device name
- notes: free-text annotations
### Measurement Data
- OLD: Messages grouped by profile (tsmId). One message may contain multiple
sensor readings. Message profile determines the combination of fields.
Example: tsmId 2100 → {ambient_temperature, humidity, air_pressure}
- NEW: Individual measurement types, each as a separate named entity.
Examples: measurementAmbientTemperature, measurementOccupancyStatus,
measurementBatteryPercentage. Each has its own timestamp and value.
Query/subscribe to specific types independently.
### Timestamps
- OLD: Unix epoch integers (tsmTs field)
- NEW: ISO 8601 strings (measuredAt field)
### Migration Mapping Summary
| Thingsee Concept | Haltian IoT Equivalent |
|------------------|------------------------|
| TUID | UUID (primary) + vendorSerial (human-readable, QR code) + TUID (cross-ref) |
| Deployment group | Keyword (e.g. #dg-northern-finland) or Space |
| Installation status | Managed via Haltian Field app (not in your DB) |
| Message profile (tsmId) | Individual measurement types |
| tsmTs (Unix epoch) | measuredAt (ISO 8601) |
| tsmGw (gateway TUID) | Gateway UUID (via Service API lookup) |
| Single flat device list | Organization > Space > Zone > Device tree |
## Your Task
1. Review my current data model / schema / code (pasted below)
2. Identify all structures that reference Thingsee concepts
3. Propose a migrated data model that:
- Stores UUID as primary device key while preserving TUID for backward compatibility
- Supports the hierarchical Organization > Space > Zone > Device structure
(if relevant to my application)
- Replaces deployment group references with keywords or space assignments
- Updates measurement storage from profile-based to type-based
- Handles ISO 8601 timestamps
4. Provide migration scripts or code to:
- Transform existing TUID-keyed records to UUID-keyed
- Map deployment groups to keywords
- Convert stored Unix timestamps to ISO 8601 (if applicable)
5. Flag any data that cannot be automatically migrated and needs manual mapping
## My Current Schema / Code
[PASTE YOUR DATABASE SCHEMA, DATA MODELS, OR APPLICATION CODE HERE]
Tips for Best Results
- Redact all secrets — Replace API keys, passwords, tokens, certificates, and internal hostnames with placeholders like
YOUR_API_KEY,mqtt.internal.example.combefore pasting - Be specific about your tech stack — Add a line like “I’m using Python with paho-mqtt” or “This is a Node.js Express app with PostgreSQL” at the top of your pasted code
- Include configuration structure (not values) — Share the shape of connection configs and environment variables with placeholder values, not real credentials
- Ask follow-up questions — After the initial migration, ask about error handling, retry logic, or edge cases specific to your deployment
- Test incrementally — Migrate one integration at a time and validate against the Stream API or Service API documentation