Skip to content

Commit

Permalink
feat: Much more typing and docs, and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
EntraptaJ committed Jun 10, 2020
1 parent 586a3d9 commit b1f5cb7
Show file tree
Hide file tree
Showing 25 changed files with 907 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@

// https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-invalid-this.md
"no-invalid-this": "off",
"@typescript-eslint/no-invalid-this": ["error"],
"@typescript-eslint/no-invalid-this": ["off"],

// https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-this-alias.md
"@typescript-eslint/no-this-alias": [
Expand Down
67 changes: 25 additions & 42 deletions src/Lab/Devices/CoreLight/index.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
// src/Lab/Devices/CoreLight/index.ts
import { BaseDevice } from '../../../Modules/Device/BaseDevice';
import { DeviceType } from '../../../Modules/Device/Device';
import { CommandType } from '@k-foss/ts-gactions/Modules/Command/BaseCommand';
import {
OnOffTrait,
BrightnessTrait,
AppSelectorTrait,
BrightnessTrait,
OnOffTrait,
} from '@k-foss/ts-gactions/Modules/Trait';
import { BaseDevice } from '../../../Modules/Device/BaseDevice';
import { DeviceType } from '../../../Modules/Device/Device';
import { DeviceInfo } from '../../../Modules/Device/DeviceInfo';
import { CommandType } from '@k-foss/ts-gactions/Modules/Command/BaseCommand';
import { Application } from '@k-foss/ts-gactions/Modules/Trait/Traits/AppSelectorTrait';

let onStatus = true;
let brightness = 50;
const availableApplications: Application[] = [
{
key: 'youtube',
names: [
{
name_synonym: ['Youtube', 'YouTube US'],
lang: 'en',
},
{
name_synonym: ['Youtube', 'YouTube DE'],
lang: 'de',
},
],
},
];
interface CustomData {
brightness: number;

on: boolean;
}

export class CoreLight extends BaseDevice<CoreLight['traits']> {
public id = '544845';
Expand All @@ -44,9 +31,17 @@ export class CoreLight extends BaseDevice<CoreLight['traits']> {
nicknames: ['test'],
};

public type = DeviceType.LIGHT;
public type = DeviceType.Light;

public attributes = {
public customData: CustomData = {
brightness: 50,
on: false,
};

public attributes: BaseDevice<CoreLight['traits']>['attributes'] = {
commandOnlyOnOff: false,
commandOnlyBrightness: false,
queryOnlyOnOff: false,
availableApplications: [
{
key: 'youtube',
Expand All @@ -64,6 +59,8 @@ export class CoreLight extends BaseDevice<CoreLight['traits']> {
],
};

public willReportState = true;

public traits = [
new OnOffTrait(),
new BrightnessTrait(),
Expand All @@ -72,20 +69,8 @@ export class CoreLight extends BaseDevice<CoreLight['traits']> {

public getStatus: BaseDevice<CoreLight['traits']>['getStatus'] = async () => {
return {
on: onStatus,
brightness,
...this.customData,
currentApplication: '',

attributes: {
availableApplications,
commandOnlyBrightness: false,
commandOnlyOnOff: false,
},
/*
attributes: {
commandOnlyBrightness: true,
commandOnlyOnOff: false,
}, */
};
};

Expand All @@ -94,12 +79,10 @@ export class CoreLight extends BaseDevice<CoreLight['traits']> {
>['executeCommand'] = async (command) => {
switch (command.type) {
case CommandType.BrightnessAbsolute:
console.log('Brightness', command);
brightness = command.brightness;
this.customData.brightness = command.brightness;
break;
case CommandType.OnOff:
console.log('OnOff: ', command);
onStatus = command.on;
this.customData.on = command.on;
break;
case CommandType.appInstall:
console.log('Install Application ', command);
Expand Down
168 changes: 168 additions & 0 deletions src/Lab/Devices/Jumper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// src/Lab/Devices/Jumper/index.ts
import { BaseDevice } from '../../../Modules/Device/BaseDevice';
import { DeviceType } from '../../../Modules/Device/Device';
import { DeviceInfo } from '../../../Modules/Device/DeviceInfo';
import { TimerTrait } from '@k-foss/ts-gactions/Modules/Trait/Traits/TimerTrait';
import { CommandType } from '@k-foss/ts-gactions/Modules/Command/BaseCommand';
import { ModesTrait } from '@k-foss/ts-gactions/Modules/Trait/Traits/ModeTrait';
import { OnOffTrait } from '@k-foss/ts-gactions/Modules/Trait';

interface CustomData {
timer?: NodeJS.Timeout;
timerPaused: boolean;

timerRemainingSec: number;

modeSetting: ObjectGet<Record<string, unknown>>;

on: boolean;
}

export class Jumper extends BaseDevice<Jumper['traits']> {
public id = '123';

public deviceInfo: DeviceInfo = {
hwVersion: '0.0.1',
manufacturer: 'KJDev',
model: '0.0.1',
swVersion: '0.0.1',
};

public name: BaseDevice<Jumper['traits']>['name'] = {
name: 'Jumper',
defaultNames: ['Jumper'],
nicknames: ['Jumper'],
};

public type = DeviceType.Switch;

public attributes: BaseDevice<Jumper['traits']>['attributes'] = {
availableModes: [
{
name: 'range',
name_values: [
{
name_synonym: ['Distance'],
lang: 'en',
},
],
settings: [
{
setting_name: '1h',
setting_values: [
{
setting_synonym: ['1 Hour', '1', '1h'],
lang: 'en',
},
],
},
{
setting_name: '2h',
setting_values: [
{
setting_synonym: ['2 Hours', '2 hour', '2', '2h'],
lang: 'en',
},
],
},
],
ordered: true,
},
],
commandOnlyTimer: false,
maxTimerLimitSec: 60000,
commandOnlyModes: false,
commandOnlyOnOff: false,
queryOnlyOnOff: false,
};

public traits = [
new TimerTrait(),
new ModesTrait(),
new OnOffTrait(),
] as const;

public customData: CustomData = {
timerPaused: false,
timer: undefined,
timerRemainingSec: -1,
modeSetting: {
distance: '1h',
},
on: false,
};

public startInterval(): void {
this.customData.timer = setInterval(() => {
this.customData.timerRemainingSec -= 1;

if (this.customData.timerRemainingSec <= -1) {
if (!this.customData.timer) {
return;
}

clearInterval(this.customData.timer);
}
}, 1000);
}

public startTimer(timerTimeSec: number): void {
this.customData.timerRemainingSec = timerTimeSec;

this.startInterval();
}

public stopTimer(): void {
if (!this.customData.timer) {
return;
}

clearInterval(this.customData.timer);
this.customData.timerPaused = false;
}

public pauseTimer(): void {
if (!this.customData.timer) {
return;
}

clearInterval(this.customData.timer);
this.customData.timerPaused = true;
}

public getStatus: BaseDevice<Jumper['traits']>['getStatus'] = async () => {
return {
timerPaused: this.customData.timerPaused,
timerRemainingSec: this.customData.timerRemainingSec,
currentModeSettings: this.customData.modeSetting,
on: this.customData.on,
};
};

public executeCommand: BaseDevice<
Jumper['traits']
>['executeCommand'] = async (command) => {
switch (command.type) {
case CommandType.TimerStart:
break;
case CommandType.TimerCancel:
this.stopTimer();
break;
case CommandType.TimerPause:
this.pauseTimer();
break;
case CommandType.TimerResume:
this.startInterval();
this.customData.timerPaused = false;
break;
case CommandType.TimerAdjust:
break;
case CommandType.SetMode:
this.customData.modeSetting = command.updateModeSettings;
break;
case CommandType.OnOff:
this.customData.on = command.on;
break;
}
};
}
3 changes: 2 additions & 1 deletion src/Lab/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { CoreLight } from './Devices/CoreLight';
import express from 'express';
import bodyParser from 'body-parser';
import { registerAuthEndpoints } from './Auth';
import { Jumper } from './Devices/Jumper';

const webServer = express();
webServer.use(bodyParser.json());
webServer.use(bodyParser.urlencoded({ extended: true }));

const smartHomeController = await SmartHomeController.createController({
devices: [new CoreLight()],
devices: [new CoreLight(), new Jumper()],
});

webServer.post('/fulfillment', smartHomeController.smartHome);
Expand Down
14 changes: 14 additions & 0 deletions src/Modules/Command/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ export enum CommandType {
appInstall = 'action.devices.commands.appInstall',
appSearch = 'action.devices.commands.appSearch',
appSelect = 'action.devices.commands.appSelect',

/**
* https://developers.google.com/assistant/smarthome/traits/timer#device-commands
*/
TimerStart = 'action.devices.commands.TimerStart',
TimerAdjust = 'action.devices.commands.TimerAdjust',
TimerPause = 'action.devices.commands.TimerPause',
TimerResume = 'action.devices.commands.TimerResume',
TimerCancel = 'action.devices.commands.TimerCancel',

/**
* https://developers.google.com/assistant/smarthome/traits/modes#device-commands
*/
SetMode = 'action.devices.commands.SetModes',
}

export abstract class BaseComamnd {
Expand Down
14 changes: 13 additions & 1 deletion src/Modules/Command/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@ import { OnOffCommand } from './Commands/OnOffCommand';
import { BrightnessAbsoluteCommand } from './Commands/BrightnessAbsoluteCommand';
import { AppInstallCommand } from './Commands/AppInstallCommand';
import { AppSelectCommand } from './Commands/AppSelectCommand';
import { TimerStartCommand } from './Commands/TimerStartCommand';
import { TimerPauseCommand } from './Commands/TimerPauseCommand';
import { TimerResumeCommand } from './Commands/TimerResumeCommand';
import { TimerCancelCommand } from './Commands/TimerCancelCommand';
import { SetModesCommand } from './Commands/SetModesCommand';
import { TimerAdjustCommand } from './Commands/TimerAdjustCommand';

export type Commands =
| OnOffCommand
| BrightnessAbsoluteCommand
| AppInstallCommand
| AppSelectCommand;
| AppSelectCommand
| TimerStartCommand
| TimerPauseCommand
| TimerResumeCommand
| TimerCancelCommand
| TimerAdjustCommand
| SetModesCommand;
16 changes: 16 additions & 0 deletions src/Modules/Command/Commands/SetModesCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// src/Modules/Command/Commands/SetModeCommand.ts
import { BaseComamnd, CommandType } from '../BaseCommand';
import { ObjectGet } from '@k-foss/ts-gactions/Utils/types';

/**
*
* https://developers.google.com/assistant/smarthome/traits/modes#device-commands
*/
export class SetModesCommand extends BaseComamnd {
public type = CommandType.SetMode as const;

/**
* Object containing the new string value (setting_name) for each mode that's being set.
*/
public updateModeSettings: ObjectGet<Record<string, unknown>>;
}
18 changes: 18 additions & 0 deletions src/Modules/Command/Commands/TimerAdjustCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// src/Modules/Command/Commands/TimerAdjustCommand.ts
import { BaseComamnd, CommandType } from '../BaseCommand';

/**
* Adjust a running timer.
* https://developers.google.com/assistant/smarthome/traits/timer#device-commands
*/
export class TimerAdjustCommand extends BaseComamnd {
public type = CommandType.TimerAdjust as const;

/**
* Positive or negative integer in seconds [-maxTimerLimitSec, maxTimerLimitSec].
* Agent may return valueOutOfRange error if remaining seconds is smaller than the
* absolute value of the specified timerTimeSec. For instance, agent may return a
* valueOutOfRange error if remaining seconds is 20 but timerTimeSec is -30.
*/
public timerTimeSec: number;
}
10 changes: 10 additions & 0 deletions src/Modules/Command/Commands/TimerCancelCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// src/Modules/Command/Commands/TimerCancelCommand.ts
import { BaseComamnd, CommandType } from '../BaseCommand';

/**
* Stop and delete the currently running or paused timer.
* https://developers.google.com/assistant/smarthome/traits/timer#device-commands
*/
export class TimerCancelCommand extends BaseComamnd {
public type = CommandType.TimerCancel as const;
}
Loading

0 comments on commit b1f5cb7

Please sign in to comment.