rxpoweredup
Version:
A Typescript RxJS-based library for controlling LEGO Powered UP hubs & peripherals.
129 lines (128 loc) • 7.43 kB
JavaScript
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();
};
});
}
}