Skip to content

Commit

Permalink
fix: exported type fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
plasticrake committed Nov 15, 2023
1 parent 248e2d1 commit fd336b2
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 166 deletions.
71 changes: 39 additions & 32 deletions examples/events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import util from 'util';
import {
Bulb,
Client,
Plug,
type Device,
type LightState,
type RealtimeNormalized,
Expand Down Expand Up @@ -44,40 +46,45 @@ client.on('device-new', (device: Device) => {
logEvent('emeter-realtime-update', device, emeterRealtime);
});

// Plug Events
device.on('power-on', () => {
logEvent('power-on', device);
});
device.on('power-off', () => {
logEvent('power-off', device);
});
device.on('power-update', (powerOn: boolean) => {
logEvent('power-update', device, powerOn);
});
device.on('in-use', () => {
logEvent('in-use', device);
});
device.on('not-in-use', () => {
logEvent('not-in-use', device);
});
device.on('in-use-update', (inUse: boolean) => {
logEvent('in-use-update', device, inUse);
});
if (device instanceof Plug) {
// Plug Events
device.on('power-on', () => {
logEvent('power-on', device);
});
device.on('power-off', () => {
logEvent('power-off', device);
});
device.on('power-update', (powerOn: boolean) => {
logEvent('power-update', device, powerOn);
});
device.on('in-use', () => {
logEvent('in-use', device);
});
device.on('not-in-use', () => {
logEvent('not-in-use', device);
});
device.on('in-use-update', (inUse: boolean) => {
logEvent('in-use-update', device, inUse);
});
}

// Bulb Events
device.on('lightstate-on', (lightstate: LightState) => {
logEvent('lightstate-on', device, lightstate);
});
device.on('lightstate-off', (lightstate: LightState) => {
logEvent('lightstate-off', device, lightstate);
});
device.on('lightstate-change', (lightstate: LightState) => {
logEvent('lightstate-change', device, lightstate);
});
device.on('lightstate-update', (lightstate: LightState) => {
logEvent('lightstate-update', device, lightstate);
});
if (device instanceof Bulb) {
// Bulb Events
device.on('lightstate-on', (lightstate: LightState) => {
logEvent('lightstate-on', device, lightstate);
});
device.on('lightstate-off', (lightstate: LightState) => {
logEvent('lightstate-off', device, lightstate);
});
device.on('lightstate-change', (lightstate: LightState) => {
logEvent('lightstate-change', device, lightstate);
});
device.on('lightstate-update', (lightstate: LightState) => {
logEvent('lightstate-update', device, lightstate);
});
}
});

client.on('device-online', (device: Device) => {
logEvent('device-online', device);
});
Expand Down
42 changes: 22 additions & 20 deletions examples/multi-plug.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import util from 'util';
import { Client, Device } from '..'; // 'tplink-smarthome-api'
import { Client, Device, Plug } from '..'; // 'tplink-smarthome-api'

const client = new Client({
defaultSendOptions: { timeout: 20000, transport: 'tcp' },
Expand All @@ -24,25 +24,27 @@ const monitorEvents = function monitorEvents(device: Device) {
logEvent('emeter-realtime-update', device, emeterRealtime);
});

// Plug Events
device.on('power-on', () => {
logEvent('power-on', device);
});
device.on('power-off', () => {
logEvent('power-off', device);
});
device.on('power-update', (powerOn) => {
logEvent('power-update', device, powerOn);
});
device.on('in-use', () => {
logEvent('in-use', device);
});
device.on('not-in-use', () => {
logEvent('not-in-use', device);
});
device.on('in-use-update', (inUse) => {
logEvent('in-use-update', device, inUse);
});
if (device instanceof Plug) {
// Plug Events
device.on('power-on', () => {
logEvent('power-on', device);
});
device.on('power-off', () => {
logEvent('power-off', device);
});
device.on('power-update', (powerOn) => {
logEvent('power-update', device, powerOn);
});
device.on('in-use', () => {
logEvent('in-use', device);
});
device.on('not-in-use', () => {
logEvent('not-in-use', device);
});
device.on('in-use-update', (inUse) => {
logEvent('in-use-update', device, inUse);
});
}

// Poll device every 5 seconds
setTimeout(function pollDevice() {
Expand Down
4 changes: 1 addition & 3 deletions src/bulb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export interface BulbConstructorOptions extends DeviceConstructorOptions {
sysInfo: BulbSysinfo;
}

interface BulbEvents {
export interface BulbEvents {
'emeter-realtime-update': (value: RealtimeNormalized) => void;
/**
* Bulb was turned on (`lightstate.on_off`).
Expand Down Expand Up @@ -147,7 +147,6 @@ interface BulbEvents {
'lightstate-sysinfo-update': (value: BulbSysinfoLightState) => void;
}

// TODO: Fix this
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
declare interface Bulb {
on<U extends keyof BulbEvents>(event: U, listener: BulbEvents[U]): this;
Expand All @@ -171,7 +170,6 @@ declare interface Bulb {
* @fires Bulb#lightstate-sysinfo-change
* @fires Bulb#lightstate-sysinfo-update
*/
// TODO: Fix this
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class Bulb extends Device {
emitEventsEnabled = true;
Expand Down
87 changes: 34 additions & 53 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const discoveryMsgBuf = encrypt('{"system":{"get_sysinfo":{}}}');

export type AnyDevice = Bulb | Plug;

type DeviceDiscovery = { status: string; seenOnDiscovery: number };
type AnyDeviceDiscovery = (Bulb | Plug) & Partial<DeviceDiscovery>;
export type DeviceDiscovery = { status: string; seenOnDiscovery: number };
export type AnyDeviceDiscovery = (Bulb | Plug) & Partial<DeviceDiscovery>;

type SysinfoResponse = { system: { get_sysinfo: Sysinfo } };
type EmeterResponse = PlugEmeterResponse | BulbEmeterResponse;
Expand All @@ -38,11 +38,11 @@ type AnyDeviceOptions =
| ConstructorParameters<typeof Bulb>[0]
| ConstructorParameters<typeof Plug>[0];

type AnyDeviceOptionsCon =
export type AnyDeviceOptionsConstructable =
| MarkOptional<ConstructorParameters<typeof Plug>[0], 'client' | 'sysInfo'>
| MarkOptional<ConstructorParameters<typeof Bulb>[0], 'client' | 'sysInfo'>;

type DeviceOptionsDiscovery =
export type DeviceOptionsDiscovery =
| MarkOptional<
ConstructorParameters<typeof Plug>[0],
'client' | 'sysInfo' | 'host'
Expand Down Expand Up @@ -159,101 +159,80 @@ export type SendOptions = {
sharedSocketTimeout?: number;
};

/* eslint-disable @typescript-eslint/unified-signatures -- for jsdoc we don't want to combine signatures */
export interface ClientEventEmitter {
export interface ClientEvents {
/**
* First response from device.
*/
on(
event: 'device-new',
listener: (device: Device | Bulb | Plug) => void,
): this;
'device-new': (device: Bulb | Plug) => void;
/**
* Follow up response from device.
*/
on(
event: 'device-online',
listener: (device: Device | Bulb | Plug) => void,
): this;
'device-online': (device: Bulb | Plug) => void;
/**
* No response from device.
*/
on(
event: 'device-offline',
listener: (device: Device | Bulb | Plug) => void,
): this;
'device-offline': (device: Bulb | Plug) => void;
/**
* First response from Bulb.
*/
on(event: 'bulb-new', listener: (device: Bulb) => void): this;
'bulb-new': (device: Bulb) => void;
/**
* Follow up response from Bulb.
*/
on(event: 'bulb-online', listener: (device: Bulb) => void): this;
'bulb-online': (device: Bulb) => void;
/**
* No response from Bulb.
*/
on(event: 'bulb-offline', listener: (device: Bulb) => void): this;
'bulb-offline': (device: Bulb) => void;
/**
* First response from Plug.
*/
on(event: 'plug-new', listener: (device: Plug) => void): this;
'plug-new': (device: Plug) => void;
/**
* Follow up response from Plug.
*/
on(event: 'plug-online', listener: (device: Plug) => void): this;
'plug-online': (device: Plug) => void;
/**
* No response from Plug.
*/
on(event: 'plug-offline', listener: (device: Plug) => void): this;
'plug-offline': (device: Plug) => void;
/**
* Invalid/Unknown response from device.
*/
on(
event: 'discovery-invalid',
listener: ({
'discovery-invalid': ({
rinfo,
response,
decryptedResponse,
}: {
rinfo: RemoteInfo;
response: Buffer;
decryptedResponse: Buffer;
}) => void,
): this;
}) => void;

/**
* Error during discovery.
*/
on(event: 'error', listener: (error: Error) => void): this;

emit(event: 'device-new', device: Device | Bulb | Plug): boolean;
emit(event: 'device-online', device: Device | Bulb | Plug): boolean;
emit(event: 'device-offline', device: Device | Bulb | Plug): boolean;
emit(event: 'bulb-new', device: Bulb): boolean;
emit(event: 'bulb-online', device: Bulb): boolean;
emit(event: 'bulb-offline', device: Bulb): boolean;
emit(event: 'plug-new', device: Plug): boolean;
emit(event: 'plug-online', device: Plug): boolean;
emit(event: 'plug-offline', device: Plug): boolean;
emit(
event: 'discovery-invalid',
{
rinfo,
response,
decryptedResponse,
}: { rinfo: RemoteInfo; response: Buffer; decryptedResponse: Buffer },
error: (error: Error) => void;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
declare interface Client {
on<U extends keyof ClientEvents>(event: U, listener: ClientEvents[U]): this;

emit<U extends keyof ClientEvents>(
event: U,
...args: Parameters<ClientEvents[U]>
): boolean;
emit(event: 'error', error: Error): boolean;
}
/* eslint-enable @typescript-eslint/unified-signatures */

/**
* Client that sends commands to specified devices or discover devices on the local subnet.
* - Contains factory methods to create devices.
* - Events are emitted after {@link #startDiscovery} is called.
* @noInheritDoc
*/
export default class Client extends EventEmitter implements ClientEventEmitter {
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class Client extends EventEmitter {
defaultSendOptions: Required<SendOptions> = {
timeout: 10000,
transport: 'tcp',
Expand Down Expand Up @@ -451,7 +430,7 @@ export default class Client extends EventEmitter implements ClientEventEmitter {
* @throws {@link ResponseError}
*/
async getDevice(
deviceOptions: AnyDeviceOptionsCon,
deviceOptions: AnyDeviceOptionsConstructable,
sendOptions?: SendOptions,
): Promise<AnyDevice> {
this.log.debug('client.getDevice(%j)', { deviceOptions, sendOptions });
Expand Down Expand Up @@ -482,7 +461,7 @@ export default class Client extends EventEmitter implements ClientEventEmitter {
*/
getDeviceFromSysInfo(
sysInfo: Sysinfo,
deviceOptions: AnyDeviceOptionsCon,
deviceOptions: AnyDeviceOptionsConstructable,
): AnyDevice {
if (isPlugSysinfo(sysInfo)) {
return this.getPlug({ ...deviceOptions, sysInfo });
Expand Down Expand Up @@ -751,7 +730,7 @@ export default class Client extends EventEmitter implements ClientEventEmitter {
device.seenOnDiscovery = this.discoveryPacketSequence;
this.emit('online', device);
} else {
const opts: AnyDeviceOptionsCon = {
const opts: AnyDeviceOptionsConstructable = {
...options,
client: this,
host,
Expand Down Expand Up @@ -846,3 +825,5 @@ export default class Client extends EventEmitter implements ClientEventEmitter {
}
}
}

export default Client;
Loading

0 comments on commit fd336b2

Please sign in to comment.