Appearance
Basic Telemetry
Overview
The Urban Sky SDK provides access to real-time balloon telemetry data. This guide covers the fundamental telemetry data you'll receive and how to work with it.
Telemetry Data Structure
Balloon Update Event
When a balloon's position changes, you'll receive a balloon:update event with the following structure:
javascript
{
balloonId: "BLN-2024-001",
missionId: "MSN-2024-001",
devices: [
{
deviceId: "PLD-001",
deviceType: "PLD",
lat: 40.7128,
lng: -74.0060,
altitude: 15240,
timestamp: "2024-01-15T10:30:00.000Z"
}
]
}Device Types
Each balloon typically carries multiple devices that report telemetry:
- PLD - Payload device (main tracking device)
- APX - Apex device (top of balloon)
- BLS - Ballaster device (ballast control system)
Working with Telemetry Data
JavaScript Example
javascript
sdk.on('balloon:update', (update) => {
console.log(`Balloon ${update.balloonId} - Mission ${update.missionId}`)
update.devices.forEach(device => {
console.log(`Device ${device.deviceId} (${device.deviceType}):`)
console.log(` Location: ${device.lat}, ${device.lng}`)
console.log(` Altitude: ${device.altitude}m`)
console.log(` Time: ${new Date(device.timestamp).toLocaleString()}`)
})
})Python Example
python
def handle_balloon_update(update):
print(f"Balloon {update['balloon_id']} - Mission {update['mission_id']}")
for device in update['devices']:
print(f"Device {device['device_id']} ({device['device_type']}):")
print(f" Location: {device['lat']}, {device['lng']}")
print(f" Altitude: {device['altitude']}m")
print(f" Time: {device['timestamp']}")
sdk.on('balloon:update', handle_balloon_update)Data Processing Examples
Tracking Latest Positions
Keep track of the most recent position for each device:
javascript
class BalloonTracker {
constructor() {
this.latestPositions = new Map()
}
handleUpdate(update) {
update.devices.forEach(device => {
const key = `${update.balloonId}-${device.deviceId}`
this.latestPositions.set(key, {
balloonId: update.balloonId,
missionId: update.missionId,
...device
})
})
}
getLatestPosition(balloonId, deviceId) {
return this.latestPositions.get(`${balloonId}-${deviceId}`)
}
getAllLatestPositions() {
return Array.from(this.latestPositions.values())
}
}
const tracker = new BalloonTracker()
sdk.on('balloon:update', (update) => tracker.handleUpdate(update))Distance Calculations
Calculate distance between positions:
javascript
function calculateDistance(lat1, lng1, lat2, lng2) {
const R = 6371e3 // Earth's radius in meters
const φ1 = lat1 * Math.PI/180
const φ2 = lat2 * Math.PI/180
const Δφ = (lat2-lat1) * Math.PI/180
const Δλ = (lng2-lng1) * Math.PI/180
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2)
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
return R * c // Distance in meters
}
// Usage
sdk.on('balloon:update', (update) => {
const payload = update.devices.find(d => d.deviceType === 'PLD')
const apex = update.devices.find(d => d.deviceType === 'APX')
if (payload && apex) {
const distance = calculateDistance(
payload.lat, payload.lng,
apex.lat, apex.lng
)
console.log(`Distance between payload and apex: ${distance.toFixed(2)}m`)
}
})Data Logging
Log telemetry data to a file:
javascript
const fs = require('fs')
class TelemetryLogger {
constructor(filename = 'telemetry.log') {
this.filename = filename
}
log(update) {
const timestamp = new Date().toISOString()
const logEntry = {
receivedAt: timestamp,
...update
}
fs.appendFileSync(this.filename, JSON.stringify(logEntry) + '\n')
}
}
const logger = new TelemetryLogger()
sdk.on('balloon:update', (update) => logger.log(update))Data Quality Considerations
Timestamp Handling
Always use the device timestamp for accurate positioning:
javascript
sdk.on('balloon:update', (update) => {
update.devices.forEach(device => {
const deviceTime = new Date(device.timestamp)
const receivedTime = new Date()
const delay = receivedTime - deviceTime
console.log(`Device ${device.deviceId} data is ${delay}ms old`)
})
})Coordinate Validation
Validate coordinates before processing:
javascript
function isValidCoordinate(lat, lng) {
return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180
}
sdk.on('balloon:update', (update) => {
update.devices.forEach(device => {
if (!isValidCoordinate(device.lat, device.lng)) {
console.warn(`Invalid coordinates for device ${device.deviceId}`)
return
}
// Process valid coordinates
processLocation(device)
})
})Testing Your Telemetry Processing
Use the test endpoint to verify your telemetry processing:
javascript
// Send a test balloon update
const testResponse = await fetch('https://api.atmosys.com/sdk/test/balloon', {
method: 'POST',
headers: {
'x-api-token': 'your-api-token',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})
if (testResponse.ok) {
console.log('Test message sent - check your telemetry processing')
}Next Steps
- Error Handling - Handle connection and data errors
- JavaScript SDK - Full JavaScript SDK reference
- Python SDK - Full Python SDK reference