Hi George, yes, I tested it on two different iOS devices.
Here’s some simple component code I made to test, perhaps this would reveal a mistake in my approach?
// Ultra Simple GPS Location Component Template
// Uses both watchPosition and getCurrentPosition with immediate printing
import * as ecs from '@8thwall/ecs'
/**
* A minimal component that gets GPS coordinates using both watchPosition and
* getCurrentPosition methods, printing values immediately when received.
*
* This implementation:
* 1. Uses watchPosition() for real-time updates when the device moves
* 2. Uses getCurrentPosition() at regular intervals for consistent updates
* 3. Prints values immediately when received (no local caching)
* 4. Clearly labels which method provided each update
*/
const TemplateComponentGpsLocationSimple = ecs.registerComponent({
name: 'template-component-gps-location-simple',
schema: {
isEnabled: ecs.boolean,
printIntervalMs: ecs.i32, // How often to call getCurrentPosition
},
schemaDefaults: {
isEnabled: true,
printIntervalMs: 1000, // Default to checking every 1 second
},
data: {
watchId: ecs.i32,
lastPrintTime: ecs.f64,
watchCount: ecs.i32,
getCurrentCount: ecs.i32,
},
add: (world, component) => {
const {eid, dataAttribute} = component
console.log('[gps-simple] Component added to entity', eid)
// Initialize component data
dataAttribute.set(eid, {
watchId: -1,
lastPrintTime: 0,
watchCount: 0,
getCurrentCount: 0,
})
// Check if geolocation is supported
if (!navigator.geolocation) {
console.error('[gps-simple] Geolocation is not supported by this browser/device')
return
}
// Set up watch for real-time GPS updates
const watchId = navigator.geolocation.watchPosition(
(position) => {
// Check if entity still exists
if (!dataAttribute.has(eid)) {
return
}
// Increment watch count
dataAttribute.mutate(eid, (cursor) => {
cursor.watchCount++
})
// Get updated data
const data = dataAttribute.get(eid)
// Extract position data
const lat = position.coords.latitude
const lng = position.coords.longitude
const accuracy = position.coords.accuracy || 0
// Get current time for timestamp
const now = new Date()
const timestamp = now.toLocaleTimeString()
// Print GPS coordinates with timestamp and method
console.log(`[WATCH GPS #${data.watchCount} @ ${timestamp}] Lat: ${lat.toFixed(6)}, Lng: ${lng.toFixed(6)} (Accuracy: ${accuracy.toFixed(1)}m)`)
},
(error) => {
console.error(`[gps-simple] Watch position error: ${error.code} - ${error.message}`)
},
{
// Request the most accurate position available (uses more battery)
enableHighAccuracy: true,
// Don't use cached positions (0 = always get fresh position)
maximumAge: 0,
// Wait up to 15 seconds for a position
timeout: 15000,
}
)
// Store watch ID for cleanup
dataAttribute.mutate(eid, (cursor) => {
cursor.watchId = watchId
})
console.log(`[gps-simple] GPS watch started with ID: ${watchId}`)
},
tick: (world, component) => {
const {eid, dataAttribute, schemaAttribute} = component
const schema = schemaAttribute.get(eid)
const data = dataAttribute.get(eid)
if (!schema.isEnabled) return
const currentTime = world.time.elapsed
// Only call getCurrentPosition at the specified interval
if (currentTime - data.lastPrintTime >= schema.printIntervalMs) {
// Update last print time
dataAttribute.mutate(eid, (cursor) => {
cursor.lastPrintTime = currentTime
})
// Get current position
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
// Check if entity still exists
if (!dataAttribute.has(eid)) {
return
}
// Increment getCurrentPosition count
dataAttribute.mutate(eid, (cursor) => {
cursor.getCurrentCount++
})
// Get updated data
const updatedData = dataAttribute.get(eid)
// Extract position data
const lat = position.coords.latitude
const lng = position.coords.longitude
const accuracy = position.coords.accuracy || 0
// Get current time for timestamp
const now = new Date()
const timestamp = now.toLocaleTimeString()
// Print GPS coordinates with timestamp and method
console.log(`[GET_CURRENT GPS #${updatedData.getCurrentCount} @ ${timestamp}] Lat: ${lat.toFixed(6)}, Lng: ${lng.toFixed(6)} (Accuracy: ${accuracy.toFixed(1)}m)`)
},
(error) => {
console.error(`[gps-simple] GetCurrentPosition error: ${error.code} - ${error.message}`)
},
{
// Request the most accurate position available (uses more battery)
enableHighAccuracy: true,
// Don't use cached positions (0 = always get fresh position)
maximumAge: 0,
// Wait up to 15 seconds for a position
timeout: 15000,
}
)
}
}
},
remove: (world, component) => {
// Check if the component is still attached before accessing data
if (!component.dataAttribute || !component.dataAttribute.has(component.eid)) {
return
}
const {eid, dataAttribute} = component
const data = dataAttribute.get(eid)
// Clear geolocation watch
if (data?.watchId !== -1) {
navigator.geolocation.clearWatch(data.watchId)
console.log(`[gps-simple] GPS watch stopped (ID: ${data.watchId})`)
}
console.log('[gps-simple] Component removed')
},
})
export {TemplateComponentGpsLocationSimple}