import * as plugins from '../../plugins.js'; import type { IIntegrationEntity } from '../../core/types.js'; import type { IIppJobInfo, IIppMarkerInfo, IIppSnapshot } from './ipp.types.js'; const ippDomain = 'ipp'; export class IppMapper { public static toDevices(snapshotArg: IIppSnapshot): plugins.shxInterfaces.data.IDeviceDefinition[] { const updatedAt = snapshotArg.updatedAt || new Date().toISOString(); const features: plugins.shxInterfaces.data.IDeviceFeature[] = [ { id: 'status', capability: 'sensor', name: 'Printer status', readable: true, writable: false }, { id: 'queued_jobs', capability: 'sensor', name: 'Queued jobs', readable: true, writable: false }, { id: 'accepting_jobs', capability: 'sensor', name: 'Accepting jobs', readable: true, writable: false }, ]; const state: plugins.shxInterfaces.data.IDeviceState[] = [ { featureId: 'status', value: snapshotArg.status.printerState, updatedAt }, { featureId: 'queued_jobs', value: snapshotArg.status.queuedJobCount ?? null, updatedAt }, { featureId: 'accepting_jobs', value: snapshotArg.status.acceptingJobs ?? null, updatedAt }, ]; for (const marker of snapshotArg.markers) { const featureId = `marker_${marker.index}`; features.push({ id: featureId, capability: 'sensor', name: marker.name, readable: true, writable: false, unit: '%' }); state.push({ featureId, value: marker.level ?? null, updatedAt }); } for (const job of snapshotArg.jobs) { const featureId = `job_${this.slug(job.id)}`; features.push({ id: featureId, capability: 'sensor', name: job.name || `Job ${job.id}`, readable: true, writable: false }); state.push({ featureId, value: job.state || null, updatedAt }); } return [{ id: this.printerDeviceId(snapshotArg), integrationDomain: ippDomain, name: this.printerName(snapshotArg), protocol: 'http', manufacturer: snapshotArg.printer.manufacturer || 'Unknown', model: snapshotArg.printer.model || snapshotArg.printer.makeAndModel || 'IPP printer', online: snapshotArg.online, features, state, metadata: this.cleanAttributes({ serialNumber: snapshotArg.printer.serialNumber, uuid: snapshotArg.printer.uuid, location: snapshotArg.printer.location, info: snapshotArg.printer.info, moreInfo: snapshotArg.printer.moreInfo, commandSet: snapshotArg.printer.commandSet, uriSupported: snapshotArg.printer.uriSupported, host: snapshotArg.printer.host, port: snapshotArg.printer.port, basePath: snapshotArg.printer.basePath, tls: snapshotArg.printer.tls, source: snapshotArg.source, stateReasons: snapshotArg.status.stateReasons, markerCount: snapshotArg.markers.length, jobCount: snapshotArg.jobs.length, error: snapshotArg.error, }), }]; } public static toEntities(snapshotArg: IIppSnapshot): IIntegrationEntity[] { const deviceId = this.printerDeviceId(snapshotArg); const uniqueBase = this.uniqueBase(snapshotArg); const baseName = this.printerName(snapshotArg); const entities: IIntegrationEntity[] = []; entities.push(this.entity('sensor', 'printer', `${baseName} Status`, snapshotArg.status.printerState, deviceId, uniqueBase, snapshotArg.online, { deviceClass: 'enum', options: ['idle', 'printing', 'stopped'], info: snapshotArg.printer.info, serial: snapshotArg.printer.serialNumber, uuid: snapshotArg.printer.uuid, location: snapshotArg.printer.location, stateMessage: snapshotArg.status.stateMessage, stateReason: snapshotArg.status.stateReasons, commandSet: snapshotArg.printer.commandSet, uriSupported: snapshotArg.printer.uriSupported?.join(','), manufacturer: snapshotArg.printer.manufacturer, model: snapshotArg.printer.model, source: snapshotArg.source, error: snapshotArg.error, })); if (snapshotArg.status.bootedAt) { entities.push(this.entity('sensor', 'uptime', `${baseName} Uptime`, snapshotArg.status.bootedAt, deviceId, uniqueBase, snapshotArg.online, { deviceClass: 'timestamp', entityCategory: 'diagnostic', })); } if (snapshotArg.status.queuedJobCount !== undefined) { entities.push(this.entity('sensor', 'queued_jobs', `${baseName} Queued Jobs`, snapshotArg.status.queuedJobCount, deviceId, uniqueBase, snapshotArg.online, { stateClass: 'measurement', })); } if (snapshotArg.status.acceptingJobs !== undefined) { entities.push(this.entity('binary_sensor', 'accepting_jobs', `${baseName} Accepting Jobs`, snapshotArg.status.acceptingJobs ? 'on' : 'off', deviceId, uniqueBase, snapshotArg.online, { deviceClass: 'running', })); } for (const marker of snapshotArg.markers) { entities.push(this.markerEntity(marker, deviceId, uniqueBase, snapshotArg.online)); } for (const job of snapshotArg.jobs) { entities.push(this.jobEntity(job, deviceId, uniqueBase, baseName, snapshotArg.online)); } return entities; } public static printerDeviceId(snapshotArg: IIppSnapshot): string { return `ipp.printer.${this.uniqueBase(snapshotArg)}`; } public static slug(valueArg: string): string { return valueArg.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'ipp'; } private static markerEntity(markerArg: IIppMarkerInfo, deviceIdArg: string, uniqueBaseArg: string, availableArg: boolean): IIntegrationEntity { return this.entity('sensor', `marker_${markerArg.index}`, markerArg.name, markerArg.level ?? null, deviceIdArg, uniqueBaseArg, availableArg, { unit: '%', stateClass: 'measurement', markerType: markerArg.type, markerKind: markerArg.kind, markerColor: markerArg.color, markerLowLevel: markerArg.lowLevel, markerHighLevel: markerArg.highLevel, }); } private static jobEntity(jobArg: IIppJobInfo, deviceIdArg: string, uniqueBaseArg: string, baseNameArg: string, availableArg: boolean): IIntegrationEntity { return this.entity('sensor', `job_${this.slug(jobArg.id)}`, jobArg.name || `${baseNameArg} Job ${jobArg.id}`, jobArg.state || 'unknown', deviceIdArg, uniqueBaseArg, availableArg, { jobId: jobArg.id, owner: jobArg.owner, impressionsCompleted: jobArg.impressionsCompleted, createdAt: jobArg.createdAt, processingAt: jobArg.processingAt, completedAt: jobArg.completedAt, ...jobArg.attributes, }); } private static entity(platformArg: IIntegrationEntity['platform'], keyArg: string, nameArg: string, stateArg: unknown, deviceIdArg: string, uniqueBaseArg: string, availableArg: boolean, attributesArg: Record): IIntegrationEntity { return { id: `${platformArg}.${this.slug(nameArg)}`, uniqueId: `ipp_${uniqueBaseArg}_${keyArg}`, integrationDomain: ippDomain, deviceId: deviceIdArg, platform: platformArg, name: nameArg, state: stateArg, attributes: this.cleanAttributes(attributesArg), available: availableArg, }; } private static printerName(snapshotArg: IIppSnapshot): string { return snapshotArg.printer.name || snapshotArg.printer.model || snapshotArg.printer.host || 'IPP printer'; } private static uniqueBase(snapshotArg: IIppSnapshot): string { return this.slug(snapshotArg.printer.uuid || snapshotArg.printer.serialNumber || snapshotArg.printer.id || snapshotArg.printer.host || this.printerName(snapshotArg)); } private static cleanAttributes(attributesArg: Record): Record { return Object.fromEntries(Object.entries(attributesArg).filter(([, valueArg]) => valueArg !== undefined)); } }