UNPKG

rxpoweredup

Version:

A Typescript RxJS-based library for controlling LEGO Powered UP hubs & peripherals.

129 lines (128 loc) 7.43 kB
import { Observable, distinctUntilChanged, filter, map, of, share, switchMap, take, takeUntil } from 'rxjs'; import { HubProperty, MAX_NAME_SIZE } from '../../constants'; export class HubPropertiesFeature { messageFactoryService; messenger; logging; inboundMessages; errorsFactory; onDisconnected$; batteryLevel = this.createPropertyStream(HubProperty.batteryVoltage).pipe(map((r) => r.level), distinctUntilChanged(), share()); rssiLevel = this.createPropertyStream(HubProperty.RSSI).pipe(map((r) => r.level), distinctUntilChanged(), share()); buttonState = this.createPropertyStream(HubProperty.button).pipe(map((r) => r.isPressed), distinctUntilChanged(), share()); characteristicUnsubscribeHandlers = new Map(); constructor(messageFactoryService, messenger, logging, inboundMessages, errorsFactory, onDisconnected$) { this.messageFactoryService = messageFactoryService; this.messenger = messenger; this.logging = logging; this.inboundMessages = inboundMessages; this.errorsFactory = errorsFactory; this.onDisconnected$ = onDisconnected$; } setHubAdvertisingName(advertisingName) { if (advertisingName.length > MAX_NAME_SIZE || advertisingName.length === 0) { throw this.errorsFactory.createInvalidPropertyValueError(HubProperty.advertisingName, advertisingName); } const charCodes = advertisingName.split('').map((char) => char.charCodeAt(0)); const message = this.messageFactoryService.setProperty(HubProperty.advertisingName, charCodes); return this.messenger.sendWithoutResponse(message); } getAdvertisingName() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.advertisingName); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.advertisingName)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.advertisingName)); } getBatteryLevel() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.batteryVoltage); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.batteryVoltage)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.level)); } getButtonState() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.button); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.button)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.isPressed)); } getPrimaryMacAddress() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.primaryMacAddress); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.primaryMacAddress)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.macAddress)); } getRSSILevel() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.RSSI); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.RSSI)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.level)); } getSystemTypeId() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.systemTypeId); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.systemTypeId)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.hubType)); } getManufacturerName() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.manufacturerName); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.manufacturerName)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.manufacturerName)); } getFirmwareVersion() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.firmwareVersion); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.firmwareVersion)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.firmwareVersion)); } getHardwareVersion() { const message = this.messageFactoryService.requestPropertyUpdate(HubProperty.hardwareVersion); const reply = this.inboundMessages.pipe(filter((r) => r.propertyType === HubProperty.hardwareVersion)); return this.messenger.sendWithResponse({ message, reply }).pipe(map((r) => r.hardwareVersion)); } sendSubscribeMessage(property) { if (this.characteristicUnsubscribeHandlers.has(property)) { return of(void 0); } const subscribeMessage = this.messageFactoryService.createSubscriptionMessage(property); this.characteristicUnsubscribeHandlers.set(property, () => { const unsubscribeMessage = this.messageFactoryService.createUnsubscriptionMessage(property); return new Observable((subscriber) => { if (this.characteristicUnsubscribeHandlers.has(property)) { this.logging.debug(`Sending unsubscribe message for property ${HubProperty[property]}`); this.characteristicUnsubscribeHandlers.delete(property); this.messenger.sendWithoutResponse(unsubscribeMessage).subscribe({ complete: () => { subscriber.next(); subscriber.complete(); }, error: (err) => { subscriber.error(err); }, }); } else { subscriber.next(); subscriber.complete(); } return () => void 0; }); }); return this.messenger.sendWithoutResponse(subscribeMessage); } createPropertyStream(trackedProperty) { return new Observable((subscriber) => { this.logging.debug('subscribing to property stream', HubProperty[trackedProperty]); const dataSub = this.sendSubscribeMessage(trackedProperty) .pipe(switchMap(() => this.inboundMessages), filter((reply) => reply.propertyType === trackedProperty), takeUntil(this.onDisconnected$)) .subscribe((message) => { subscriber.next(message); }); const handleDisconnectSub = this.onDisconnected$.pipe(take(1)).subscribe(() => { this.logging.debug('dropping property stream', HubProperty[trackedProperty], 'due to disconnect'); this.characteristicUnsubscribeHandlers.delete(trackedProperty); }); return () => { const unsubscribeHandler = this.characteristicUnsubscribeHandlers.get(trackedProperty); if (unsubscribeHandler) { this.logging.debug('unsubscribing from property stream', HubProperty[trackedProperty]); unsubscribeHandler().subscribe(); } handleDisconnectSub.unsubscribe(); dataSub.unsubscribe(); }; }); } }