Add typings and jsdoc comments to improve developer experience

This commit is contained in:
Victor Hagelbäck 2021-03-29 12:48:27 +02:00
parent f219b4b2bf
commit 764a3ca223
9 changed files with 765 additions and 4 deletions

View file

@ -1,9 +1,12 @@
const fs = require('fs'); const fs = require('fs');
class Configuration { class Configuration {
/** @type {import('types/Configuration').Options} */
static _options = null; static _options = null;
/** @type {import('types/Configuration').AddonInfo} */
static _addonInfo = null; static _addonInfo = null;
/** @returns Options */
static getOptions() { static getOptions() {
if (!Configuration._options) { if (!Configuration._options) {
Configuration._hydrateCache(); Configuration._hydrateCache();
@ -11,6 +14,7 @@ class Configuration {
return Configuration._options; return Configuration._options;
} }
/** @returns AddonInfo */
static getAddonInfo() { static getAddonInfo() {
if (!Configuration._addonInfo) { if (!Configuration._addonInfo) {
Configuration._hydrateCache(); Configuration._hydrateCache();
@ -20,10 +24,10 @@ class Configuration {
static _hydrateCache() { static _hydrateCache() {
const rawData = fs.readFileSync('/data/options.json'); const rawData = fs.readFileSync('/data/options.json');
const config = JSON.parse(rawData); const config = JSON.parse(rawData.toString());
const defaultRawData = fs.readFileSync('/plejd/config.json'); const defaultRawData = fs.readFileSync('/plejd/config.json');
const defaultConfig = JSON.parse(defaultRawData); const defaultConfig = JSON.parse(defaultRawData.toString());
Configuration._options = { ...defaultConfig.options, ...config }; Configuration._options = { ...defaultConfig.options, ...config };
Configuration._addonInfo = { Configuration._addonInfo = {

View file

@ -1,7 +1,7 @@
const dbus = require('dbus-next'); const dbus = require('dbus-next');
const crypto = require('crypto'); const crypto = require('crypto');
const xor = require('buffer-xor'); const xor = require('buffer-xor');
const EventEmitter = require('events'); const { EventEmitter } = require('events');
const Configuration = require('./Configuration'); const Configuration = require('./Configuration');
const constants = require('./constants'); const constants = require('./constants');
@ -874,7 +874,7 @@ class PlejBLEHandler extends EventEmitter {
(pl) => pl.writeInt32LE(Math.trunc(newLocalTimestamp), 5), (pl) => pl.writeInt32LE(Math.trunc(newLocalTimestamp), 5),
); );
try { try {
this.write(payload); this._write(payload);
} catch (err) { } catch (err) {
logger.error( logger.error(
'Failed writing new time to Plejd. Will try again in one hour or at restart.', 'Failed writing new time to Plejd. Will try again in one hour or at restart.',

View file

@ -189,6 +189,11 @@ The code in this project follows the [Airbnb JavaScript guide](https://github.co
For a nice developer experience it is very convenient to have `eslint` and `prettier` installed in your favorite editor (such as VS Code) and use the "format on save" option (or invoke formatting by Alt+Shift+F in VS Code). Any code issues should appear in the problems window inside the editor, as well as when running the command above. For a nice developer experience it is very convenient to have `eslint` and `prettier` installed in your favorite editor (such as VS Code) and use the "format on save" option (or invoke formatting by Alt+Shift+F in VS Code). Any code issues should appear in the problems window inside the editor, as well as when running the command above.
For partial type hinting you can run
- `npm install --global typings`
- `typings install`
When contributing, please do so by forking the repo and then using pull requests towards the dev branch. When contributing, please do so by forking the repo and then using pull requests towards the dev branch.
### Logs ### Logs

10
plejd/jsconfig.json Normal file
View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"baseUrl": ".",
"checkJs": true,
"module": "commonjs",
"moduleResolution": "node",
"target": "es6"
},
"exclude": ["node_modules", "rootfs"]
}

655
plejd/types/ApiSite.d.ts vendored Normal file
View file

@ -0,0 +1,655 @@
/* eslint-disable camelcase */
/* eslint-disable no-use-before-define */
export interface CachedSite {
siteId: string;
siteDetails: ApiSite;
sessionToken: string;
dtCache: string;
}
export interface ApiSite {
site: SiteDetailsSite;
plejdMesh: PlejdMesh;
rooms: Room[];
scenes: Scene[];
devices: Device[];
plejdDevices: PlejdDevice[];
gateways: Gateway[];
resourceSets: ResourceSet[];
timeEvents: TimeEvent[];
sceneSteps: SceneStep[];
astroEvents: AstroEvent[];
inputSettings: InputSetting[];
outputSettings: OutputSetting[];
stateTimers: StateTimers;
sitePermission: SitePermission;
inputAddress: { [key: string]: { [key: string]: number } };
outputAddress: { [key: string]: OutputAddress };
deviceAddress: { [key: string]: number };
outputGroups: { [key: string]: OutputGroup };
roomAddress: { [key: string]: number };
sceneIndex: { [key: string]: number };
images: Images;
deviceLimit: number;
}
export interface AstroEvent {
dirtyDevices?: any[];
dirtyRemovedDevices?: any[];
deviceId: string;
siteId: string;
sceneId: string;
fadeTime: number;
activated: boolean;
astroEventId: string;
index: number;
sunriseOffset: number;
sunsetOffset: number;
pauseStart: string;
pauseEnd: string;
createdAt: Date;
updatedAt: Date;
dirtyRemove?: boolean;
ACL: AstroEventACL;
targetDevices: AstroEventTargetDevice[];
objectId: string;
__type: AstroEventType;
className: string;
}
export interface AstroEventACL {}
export enum AstroEventType {
Object = 'Object',
}
export interface AstroEventTargetDevice {
deviceId: string;
index: number;
}
export interface Device {
deviceId: string;
siteId: string;
roomId: string;
title: string;
traits: number;
hardware?: Hardware;
hiddenFromRoomList: boolean;
createdAt: Date;
updatedAt: Date;
outputType: OutputType;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: DeviceClassName;
hiddenFromIntegrations?: boolean;
}
export enum DeviceClassName {
Device = 'Device',
}
export interface Hardware {
createdAt: Date;
updatedAt: Date;
name: Name;
hardwareId: string;
minSupportedFirmware: PlejdMeshClass;
latestFirmware: PlejdMeshClass;
brand: Brand;
type: Type;
image: Image;
requiredAccountType: RequiredAccountType[];
numberOfDevices: number;
predefinedLoad: PredefinedLoad;
supportedFirmware: PredefinedLoad;
ACL: AstroEventACL;
objectId: HardwareObjectID;
__type: AstroEventType;
className: HardwareClassName;
}
export enum Brand {
PlejdLight = 'Plejd Light',
}
export enum HardwareClassName {
Hardware = 'Hardware',
}
export interface Image {
__type: ImageType;
name: string;
url: string;
}
export enum ImageType {
File = 'File',
}
export interface PlejdMeshClass {
__type: InstallerType;
className: SiteClassName;
objectId: ObjectID;
}
export enum InstallerType {
Pointer = 'Pointer',
}
export enum SiteClassName {
DimCurve = 'DimCurve',
Firmware = 'Firmware',
PlejdMesh = 'PlejdMesh',
Site = 'Site',
User = '_User',
UserProfile = 'UserProfile',
}
export enum ObjectID {
BBBJO2Cufm = 'BBBJO2cufm',
D4Dw87Hq21 = 'D4DW87HQ21',
FCrrS1NJHH = 'FCrrS1nJHH',
GX1W4P06QS = 'gX1W4p06QS',
Ndlvzgh4Df = 'ndlvzgh4df',
UHoKQLuXqZ = 'uHoKQLuXqZ',
VfHiawBPA8 = 'vfHiawBPA8',
WgAFPloWjK = 'wgAfPloWjK',
YkyNDotBNa = 'YkyNDotBNa',
}
export enum Name {
Ctr01 = 'CTR-01',
Dim01 = 'DIM-01',
}
export enum HardwareObjectID {
R3Gfd6ACAu = 'R3gfd6ACAu',
XjslOltgvi = 'xjslOltgvi',
}
export interface PredefinedLoad {
__type: SupportedFirmwareType;
className: PredefinedLoadClassName;
}
export enum SupportedFirmwareType {
Relation = 'Relation',
}
export enum PredefinedLoadClassName {
DimCurve = 'DimCurve',
Firmware = 'Firmware',
PredefinedLoad = 'PredefinedLoad',
}
export enum RequiredAccountType {
Installer = 'installer',
}
export enum Type {
Controller = 'Controller',
LEDDimmer = 'LED Dimmer',
}
export enum OutputType {
Light = 'LIGHT',
Relay = 'RELAY',
}
export interface Gateway {
title: string;
deviceId: string;
siteId: string;
hardwareId: string;
installer: ObjectID;
firmware: number;
firmwareObject: Firmware;
dirtyInstall: boolean;
dirtyUpdate: boolean;
createdAt: Date;
updatedAt: Date;
factoryKey: string;
resourceSetId: string;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: string;
}
export interface Firmware {
notes: Notes;
createdAt: Date;
updatedAt: Date;
data: Image;
metaData: Image;
version: Version;
buildTime: number;
firmwareApi: string;
ACL: AstroEventACL;
objectId: FirmwareObjectObjectID;
__type: AstroEventType;
className: SiteClassName;
}
export enum Notes {
Ctr01 = 'CTR-01',
Ctr20ReleaseCandidate1 = 'Ctr 2.0 Release candidate 1',
Dim20ReleaseCandidate1 = 'Dim 2.0 Release candidate 1',
Dim221ReleaseCandidate = 'Dim 2.2.1 Release Candidate',
GWY10ReleaseCandidate = 'GWY 1.0 Release Candidate',
}
export enum FirmwareObjectObjectID {
BBBJO2Cufm = 'BBBJO2cufm',
E6YxfREDuF = 'E6yxfREDuF',
JYSZ0EvyCU = 'JYSZ0EvyCU',
Ndlvzgh4Df = 'ndlvzgh4df',
RlglTfVHDe = 'rlglTfVHDe',
}
export enum Version {
The12 = '1.2',
The20 = '2.0',
The221 = '2.2.1',
The304 = '3.0.4',
}
export interface Images {
'2afc6c6e-7a26-466a-b8ec-febbca90f5f7': string;
}
export interface InputSetting {
deviceId: string;
input: number;
siteId: string;
dimSpeed: number;
buttonType: ButtonType;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: InputSettingClassName;
doubleClick?: string;
singleClick?: null;
doubleSidedDirectionButton?: boolean;
}
export enum ButtonType {
PushButton = 'PushButton',
RotateMesh = 'RotateMesh',
Scene = 'Scene',
}
export enum InputSettingClassName {
PlejdDeviceInputSetting = 'PlejdDeviceInputSetting',
}
export interface OutputAddress {
'0': number;
}
export interface OutputGroup {
'0': number[];
}
export interface OutputSetting {
deviceId: string;
output: number;
deviceParseId: string;
siteId: string;
predefinedLoad: OutputSettingPredefinedLoad;
createdAt: Date;
updatedAt: Date;
dimMin: number;
dimMax: number;
dimStart: number;
outputStartTime: number;
outputSpeed: number;
bootState: BootState;
dimCurve: DimCurve;
curveLogarithm: number;
curveSinusCompensation: number;
curveRectification: boolean;
output_0_10V_Mode?: Output0_10_VMode;
zeroCrossing?: Output0_10_VMode;
minimumRelayOffTime?: number;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: OutputSettingClassName;
ledCurrent?: number;
ledVoltage?: number;
relayConfig?: Output0_10_VMode;
}
export enum BootState {
UseLast = 'UseLast',
}
export enum OutputSettingClassName {
PlejdDeviceOutputSetting = 'PlejdDeviceOutputSetting',
}
export enum DimCurve {
LinearLogarithmicSlidingProportion = 'LinearLogarithmicSlidingProportion',
NonDimmable = 'NonDimmable',
}
export enum Output0_10_VMode {
Unknown = 'Unknown',
}
export interface OutputSettingPredefinedLoad {
updatedAt: Date;
createdAt: Date;
loadType: string;
predefinedLoadData: string;
defaultDimCurve: PlejdMeshClass;
description_en?: DescriptionEn;
title_en?: TitleEn;
title_sv?: TitleSv;
description_sv?: DescriptionSv;
titleKey: string;
descriptionKey: string;
allowedDimCurves: PredefinedLoad;
ACL: PredefinedLoadACL;
objectId: string;
__type: AstroEventType;
className: PredefinedLoadClassName;
supportMessage?: SupportMessage;
filters?: Filters;
}
export interface PredefinedLoadACL {
'*': Empty;
}
export interface Empty {
read: boolean;
}
export enum DescriptionEn {
OnOff = 'On / Off',
OnlySwitchingOffOn = 'Only switching off/on',
The230VDimmableLEDLightSourceMax100VA = '230V dimmable LED light source - Max 100VA',
The230VIncandescentHalogenElectronicTransformatorMax300W = '230V Incandescent / Halogen, Electronic transformator - Max 300W',
WithoutRelay = 'Without relay',
}
export enum DescriptionSv {
EndastBrytningAVPå = 'Endast brytning av/på',
ReläbrytningAVPå = 'Reläbrytning av/på',
The230VDimbarLEDLjuskällaMax100VA = '230V dimbar LED ljuskälla - Max 100VA',
The230VDimbarLEDLjuskällaMax200VA = '230V dimbar LED ljuskälla - Max 200VA',
The230VHalogenGlödljusElektroniskTransformatorMax300W = '230V Halogen / Glödljus, Elektronisk transformator - Max 300W',
UtanReläbrytning = 'Utan reläbrytning',
}
export interface Filters {
allowedCountriesFilter: AllowedCountriesFilter;
}
export interface AllowedCountriesFilter {
countryCodes: CountryCode[];
}
export enum CountryCode {
Fi = 'FI',
No = 'NO',
SE = 'SE',
}
export enum SupportMessage {
PredefinedLoadNonDimmableSupportMessageHTML = 'PredefinedLoadNonDimmableSupportMessageHTML',
}
export enum TitleEn {
IncandescentHalogen = 'Incandescent / Halogen',
LEDTrailingEdgeCommon = 'LED Trailing Edge (Common)',
LeadingEdge = 'Leading edge',
NonDimmableLEDLightSourceMax200VA = 'Non-dimmable LED light source (Max 200VA)',
RelayOnly = 'Relay only',
The010V = '0-10V',
}
export enum TitleSv {
EjDimbarLEDLjuskällaMax200VA = 'Ej dimbar LED-ljuskälla (Max 200VA)',
HalogenGlödljus = 'Halogen / Glödljus',
LEDBakkantVanligast = 'LED Bakkant (Vanligast)',
LEDFramkant = 'LED Framkant',
Reläfunktion = 'Reläfunktion',
The010V = '0-10V',
}
export interface PlejdDevice {
deviceId: string;
installer: PlejdMeshClass;
dirtyInstall: boolean;
dirtyUpdate: boolean;
dirtyClock: boolean;
hardwareId: string;
faceplateId: string;
firmware: Firmware;
createdAt: Date;
updatedAt: Date;
coordinates: Coordinates;
dirtySettings: boolean;
diagnostics: string;
siteId: string;
predefinedLoad: OutputSettingPredefinedLoad;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: PlejdDeviceClassName;
}
export enum PlejdDeviceClassName {
PlejdDevice = 'PlejdDevice',
}
export interface Coordinates {
__type: CoordinatesType;
latitude: number;
longitude: number;
}
export enum CoordinatesType {
GeoPoint = 'GeoPoint',
}
export interface PlejdMesh {
siteId: string;
plejdMeshId: string;
meshKey: string;
cryptoKey: string;
createdAt: Date;
updatedAt: Date;
site: PlejdMeshClass;
ACL: AstroEventACL;
objectId: ObjectID;
__type: AstroEventType;
className: SiteClassName;
}
export interface ResourceSet {
scopes: string[];
remoteAccessUsers: string[];
name: string;
type: string;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: string;
}
export interface Room {
siteId: string;
roomId: string;
title: string;
category: string;
imageHash: number;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: RoomClassName;
}
export enum RoomClassName {
Room = 'Room',
}
export interface SceneStep {
sceneId: string;
siteId: string;
deviceId: string;
state: State;
value: number;
output: number;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: SceneStepClassName;
dirty?: boolean;
dirtyRemoved?: boolean;
}
export enum SceneStepClassName {
SceneStep = 'SceneStep',
}
export enum State {
Off = 'Off',
On = 'On',
}
export interface Scene {
title: string;
sceneId: string;
siteId: string;
hiddenFromSceneList: boolean;
settings: string;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: ButtonType;
}
export interface SiteDetailsSite {
installers: ObjectID[];
title: string;
siteId: string;
version: number;
createdAt: Date;
updatedAt: Date;
plejdMesh: PlejdMeshClass;
coordinates: Coordinates;
astroTable: AstroTable;
deviceAstroTable: DeviceAstroTable;
zipCode: string;
city: string;
country: string;
previousOwners: string[];
ACL: AstroEventACL;
objectId: ObjectID;
__type: AstroEventType;
className: SiteClassName;
}
export interface AstroTable {
sunrise: string[];
sunset: string[];
}
export interface DeviceAstroTable {
sunrise: number[];
sunset: number[];
}
export interface SitePermission {
siteId: string;
userId: ObjectID;
user: User;
isOwner: boolean;
isInstaller: boolean;
isUser: boolean;
site: SiteDetailsSite;
createdAt: Date;
updatedAt: Date;
ACL: AstroEventACL;
objectId: string;
__type: AstroEventType;
className: string;
}
export interface User {
profileName: string;
isInstaller: boolean;
email: string;
locale: string;
username: string;
emailVerified: boolean;
createdAt: Date;
updatedAt: Date;
profile: PlejdMeshClass;
_failed_login_count: number;
hasIntegration: boolean;
ACL: UserACL;
objectId: ObjectID;
__type: AstroEventType;
className: SiteClassName;
}
export interface UserACL {
gX1W4p06QS: GX1W4P06QS;
}
export interface GX1W4P06QS {
read: boolean;
write: boolean;
}
export interface StateTimers {
SafetyTimer: any[];
}
export interface TimeEvent {
dirtyDevices?: any[];
dirtyRemovedDevices?: any[];
scheduledDays: number[];
deviceId: string;
siteId: string;
sceneId: string;
fadeTime: number;
activated: boolean;
timeEventId: string;
startTimeIndex: number;
endTimeIndex: number;
startTime: string;
endTime: string;
createdAt: Date;
updatedAt: Date;
dirtyRemove?: boolean;
ACL: AstroEventACL;
targetDevices: TimeEventTargetDevice[];
objectId: string;
__type: AstroEventType;
className: string;
}
export interface TimeEventTargetDevice {
deviceId: string;
startTimeIndex: number;
endTimeIndex: number;
}

50
plejd/types/Configuration.d.ts vendored Normal file
View file

@ -0,0 +1,50 @@
/* eslint-disable no-use-before-define */
export interface AddonInfo {
name: string;
version: string;
slug: string;
description: string;
url: string;
arch: string[];
startup: string;
boot: string;
host_network: boolean;
host_dbus: boolean;
apparmor: boolean;
}
export interface Configuration extends AddonInfo {
options: Options;
schema: Schema;
}
export interface Options {
site: string;
username: string;
password: string;
mqttBroker: string;
mqttUsername: string;
mqttPassword: string;
includeRoomsAsLights: boolean;
preferCachedApiResponse: boolean;
updatePlejdClock: boolean;
logLevel: string;
connectionTimeout: number;
writeQueueWaitTime: number;
}
export interface Schema {
site: string;
username: string;
password: string;
mqttBroker: string;
mqttUsername: string;
mqttPassword: string;
includeRoomsAsLights: string;
preferCachedApiResponse: string;
updatePlejdClock: string;
logLevel: string;
connectionTimeout: string;
writeQueueWaitTime: string;
}

21
plejd/types/DeviceRegistry.d.ts vendored Normal file
View file

@ -0,0 +1,21 @@
/* eslint-disable no-use-before-define */
export type OutputDevices = { [deviceIdAndOutput: string]: OutputDevice };
export interface OutputDevice {
bleDeviceIndex: number;
deviceId: string;
dim?: number;
dimmable: boolean;
hiddenFromRoomList?: boolean;
hiddenFromIntegrations?: boolean;
hiddenFromSceneList?: boolean;
name: string;
output: number;
roomId: string;
state: number | undefined;
type: string;
typeName: string;
version: string;
uniqueId: string;
}

11
plejd/types/PlejdApi.d.ts vendored Normal file
View file

@ -0,0 +1,11 @@
/* eslint-disable no-use-before-define */
import { ApiSite } from './ApiSite';
export type PlejdApi = {
config: any;
deviceRegistry: any;
sessionToken: string;
siteId: string;
siteDetails: ApiSite;
};

5
plejd/typings.json Normal file
View file

@ -0,0 +1,5 @@
{
"globalDependencies": {
"node": "registry:dt/node#7.0.0+20170322231424"
}
}