- Pluggable multi-provider architecture (ReferenceEngine) - Wassup provider implementation (HTTP GET + X_WASSUP_USER_IP) - Auto-resolve references on Inform (BOOT/BOOTSTRAP events) - References displayed in device Identity card - REST API: GET/POST references per device - Config via config/references.json - Fix event extraction for single EventStruct and numeric EventCodes - Mock Wassup provisioned by home-device-simulator on device creation
88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
import type { HttpContext } from '@adonisjs/core/http'
|
|
import DeviceModel from '#models/device'
|
|
import { getReferenceEngine } from '../services/references/reference_engine.js'
|
|
|
|
export default class ReferencesController {
|
|
/**
|
|
* GET /api/v1/devices/:identifier/references
|
|
*/
|
|
async index({ params, response }: HttpContext) {
|
|
const device = await DeviceModel.findByIdentifier(params.identifier)
|
|
if (!device) {
|
|
return response.status(404).json({ message: 'Device not found' })
|
|
}
|
|
return response.json({ references: device.references || [] })
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/devices/:identifier/references/:provider
|
|
*/
|
|
async show({ params, response }: HttpContext) {
|
|
const device = await DeviceModel.findByIdentifier(params.identifier)
|
|
if (!device) {
|
|
return response.status(404).json({ message: 'Device not found' })
|
|
}
|
|
const ref = (device.references || []).find((r: any) => r.provider === params.provider)
|
|
if (!ref) {
|
|
return response.status(404).json({ message: `No reference from provider '${params.provider}'` })
|
|
}
|
|
return response.json(ref)
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/devices/:identifier/references/resolve
|
|
* Trigger resolution for all applicable providers.
|
|
*/
|
|
async resolveAll({ params, response }: HttpContext) {
|
|
const device = await DeviceModel.findByIdentifier(params.identifier)
|
|
if (!device) {
|
|
return response.status(404).json({ message: 'Device not found' })
|
|
}
|
|
|
|
const engine = getReferenceEngine()
|
|
const context = { events: ['MANUAL'], remoteIp: '', headers: {} }
|
|
|
|
// For manual resolution, use all providers regardless of trigger
|
|
const results = await engine.resolveAll(device, { ...context, events: ['0 BOOTSTRAP'] })
|
|
|
|
if (results.length > 0) {
|
|
// Merge with existing references (replace by provider name)
|
|
const existing = (device.references || []).filter(
|
|
(r: any) => !results.some((nr) => nr.provider === r.provider)
|
|
)
|
|
const merged = [...existing, ...results]
|
|
await DeviceModel.updateOne({ identifier: params.identifier }, { $set: { references: merged, updatedAt: new Date() } })
|
|
}
|
|
|
|
return response.json({ resolved: results.length, references: results })
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/devices/:identifier/references/resolve/:provider
|
|
* Trigger resolution for a single provider.
|
|
*/
|
|
async resolveOne({ params, response }: HttpContext) {
|
|
const device = await DeviceModel.findByIdentifier(params.identifier)
|
|
if (!device) {
|
|
return response.status(404).json({ message: 'Device not found' })
|
|
}
|
|
|
|
const engine = getReferenceEngine()
|
|
const context = { events: ['0 BOOTSTRAP'], remoteIp: '', headers: {} }
|
|
const result = await engine.resolveOne(params.provider, device, context)
|
|
|
|
if (!result) {
|
|
return response.status(404).json({ message: `Provider '${params.provider}' not found or cannot resolve` })
|
|
}
|
|
|
|
// Merge into device references
|
|
const existing = (device.references || []).filter((r: any) => r.provider !== params.provider)
|
|
await DeviceModel.updateOne(
|
|
{ identifier: params.identifier },
|
|
{ $set: { references: [...existing, result], updatedAt: new Date() } }
|
|
)
|
|
|
|
return response.json(result)
|
|
}
|
|
}
|