Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ module.exports = {
singleQuote: true,
trailingComma: 'es5',
arrowParens: 'always',
printWidth: 80,
printWidth: 100,
}
5 changes: 4 additions & 1 deletion examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ const Util = {
}

const blyncConnector = new BlyncConnector()
const device = blyncConnector.getDevice(0)
const device = blyncConnector.getDeviceByProductName(
BlyncLightProductsEnum.BLYNCLIGHT_MINI
)

/* Turn light and sound off on exit */
;['exit', 'uncaughtException', 'SIGQUIT', 'SIGINT'].forEach((signal) =>
Expand Down Expand Up @@ -99,5 +101,6 @@ for (var i = 0; i < colorCycleSize; i++) {
Util.wait(1, 500)
}

/* Cycle through colors */
device.setLightBrightness(BlyncLightLevelEnum.DIM)
Util.wait(5)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"postinstall": "husky install",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"run": "npm run build && npm run run:example",
"start": "npm run build && npm run run:example",
"run:example": "node examples/index.js",
"test": "jest --no-cache --runInBand",
"watch": "webpack",
Expand Down
104 changes: 80 additions & 24 deletions src/classes/BlyncConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,102 @@ export class BlyncConnector {
blyncProducts: BlyncProduct[] = [
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '0009', BlyncLightProductsEnum.BLYNCLIGHT_EMBRAVA_EMBEDDED, 12),
new BlyncProduct('0e53', '2519', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 7),
new BlyncProduct('2c0d', '0003', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 7),
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '000a', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 13),
new BlyncProduct('2c0d', '000a', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 13), // BLYNCLIGHT_MINI
new BlyncProduct('0e53', '2519', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 7), // BLYNCLIGHT_MINI
new BlyncProduct('2c0d', '0003', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 7), // BLYNCLIGHT_MINI
new BlyncProduct('1130', '0001', BlyncLightProductsEnum.BLYNCLIGHT, 1), // BLYNCUSB10 DEVICE
new BlyncProduct('1130', '0002', BlyncLightProductsEnum.BLYNCLIGHT, 1), // BLYNCUSB10 DEVICE
new BlyncProduct('0e53', '2516', BlyncLightProductsEnum.BLYNCLIGHT, 3), // BLYNCUSB30 DEVICE
new BlyncProduct('2c0d', '0001', BlyncLightProductsEnum.BLYNCLIGHT, 3), // BLYNCUSB30 DEVICE
new BlyncProduct('0e53', '2517', BlyncLightProductsEnum.BLYNCLIGHT, 4), // BLYNCUSB30S DEVICE
new BlyncProduct('2c0d', '0002', BlyncLightProductsEnum.BLYNCLIGHT, 4), // BLYNCUSB30S DEVICE
new BlyncProduct('2c0d', '000c', BlyncLightProductsEnum.BLYNCLIGHT_IPE, 15), // BLYNCUSB40 DEVICE
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '0010', BlyncLightProductsEnum.BLYNCLIGHT_PLUS, 16), // BLYNCUSB40S DEVICE
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '0006', BlyncLightProductsEnum.BLYNCLIGHT_WIRELESS, 6),
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '000b', BlyncLightProductsEnum.BLYNCLIGHT_WIRELESS, 14),
// eslint-disable-next-line prettier/prettier
new BlyncProduct('2c0d', '000f', BlyncLightProductsEnum.BLYNCLIGHT_NAMEPLATE, 17),
]

getDevices(): BlyncDevice[] {
const hidDevices = hid.devices() || []
private indexCheck = (index: number, devices: BlyncDevice[]) => {
if (index < 0) {
throw new Error('Invalid device index')
}
if (index > devices.length) {
throw new Error('Device index #' + index + ' not found')
}
}

return hidDevices
.filter((hidDevice: hid.Device) => {
private getDevicesByVendorIdProductId(): BlyncDevice[] {
const hidDevices = hid.devices() || []
try {
const devices = hidDevices.filter((hidDevice: hid.Device) => {
// Check if hid device matches any blync devices
return (
hidDevice.path &&
this.blyncProducts.some((blyncProduct: BlyncProduct) => {
return blyncProduct.isBlyncMatch(
hidDevice.vendorId,
hidDevice.productId
)
// eslint-disable-next-line prettier/prettier
return blyncProduct.isVendorIdProductIdMatch(hidDevice.vendorId, hidDevice.productId)
})
)
// TODO: Test on Linux and OSX
// on macOS/Windows, dev.interface === -1, but on Raspbian shows as 0, so removing for now:
// && dev.interface === -1;
})
.map((blyncDevice: hid.Device) => {

const blyncDevices = devices.map((blyncDevice: hid.Device) => {
return new BlyncDevice(new hid.HID(blyncDevice.path || ''))
})
}
getDevice(index: number): BlyncDevice {
index = +index || 0

const devices = this.getDevices()
if (index < 0) {
throw new Error('Invalid device index')
if (!blyncDevices || blyncDevices.length === 0) {
throw Error(`No Blync devices found for known hardware ids.`)
}

return blyncDevices
} catch (err: any) {
throw Error(err)
}
if (index >= devices.length) {
throw new Error('Device index #' + index + ' not found')
}

// eslint-disable-next-line prettier/prettier
private getDevicesByProductName(productName: BlyncLightProductsEnum): BlyncDevice[] {
const hidDevices = hid.devices() || []
try {
const devices = hidDevices.filter((hidDevice: hid.Device) => {
return (
hidDevice.path &&
this.blyncProducts.some((blyncProduct: BlyncProduct) => {
return (
blyncProduct.isProductNameMatch(productName) &&
// eslint-disable-next-line prettier/prettier
blyncProduct.isVendorIdProductIdMatch(hidDevice.vendorId, hidDevice.productId)
)
})
)
})
const blyncDevices = devices.map((blyncDevice: hid.Device) => {
return new BlyncDevice(new hid.HID(blyncDevice.path || ''))
})
if (!blyncDevices || blyncDevices.length === 0) {
throw Error(`No Blync devices found for product name: '${productName}'`)
}
return blyncDevices
} catch (err: any) {
throw Error(err)
}
}

getDevice(index = 0): BlyncDevice {
const devicesByVendorIdProductId = this.getDevicesByVendorIdProductId()
this.indexCheck(index, devicesByVendorIdProductId)
return devicesByVendorIdProductId[index]
}

return devices[index]
// eslint-disable-next-line prettier/prettier
getDeviceByProductName(productName: BlyncLightProductsEnum, index = 0): BlyncDevice {
const devicesByProductName = this.getDevicesByProductName(productName)
this.indexCheck(index, devicesByProductName)
return devicesByProductName[index]
}
}
12 changes: 8 additions & 4 deletions src/classes/BlyncProduct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ export class BlyncProduct {
this.deviceType = deviceType
}

// TODO: Rename
isBlyncMatch(givenVendorId: number, givenProductId: number): boolean {
// eslint-disable-next-line prettier/prettier
isVendorIdProductIdMatch(givenVendorId: number, givenProductId: number): boolean {
try {
return (
toInt(this.vendorId, 16) == givenVendorId &&
toInt(this.productId, 16) == givenProductId
// eslint-disable-next-line prettier/prettier
toInt(this.vendorId, 16) == givenVendorId && toInt(this.productId, 16) == givenProductId
)
} catch (err) {
return false
}
}

isProductNameMatch(productName: BlyncLightProductsEnum): boolean {
return this.deviceName == productName
}
}
4 changes: 4 additions & 0 deletions src/enums/BlyncLightProductsEnum.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export enum BlyncLightProductsEnum {
BLYNCLIGHT = 'BLYNCLIGHT',
BLYNCLIGHT_EMBRAVA_EMBEDDED = 'BLYNCLIGHT_EMBRAVA_EMBEDDED',
BLYNCLIGHT_IPE = 'BLYNCLIGHT_IPE',
BLYNCLIGHT_MINI = 'BLYNCLIGHT_MINI',
BLYNCLIGHT_NAMEPLATE = 'BLYNCLIGHT_NAMEPLATE',
BLYNCLIGHT_PLUS = 'BLYNCLIGHT_PLUS',
BLYNCLIGHT_WIRELESS = 'BLYNCLIGHT_WIRELESS',
}
14 changes: 12 additions & 2 deletions test/classes/BlyncProduct.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ describe('BlyncProduct', () => {
BlyncLightProductsEnum.BLYNCLIGHT_MINI,
13
)
expect(myBlyncProduct.isBlyncMatch(11277, 10)).toBe(true)
expect(myBlyncProduct.isVendorIdProductIdMatch(11277, 10)).toBe(true)
})

test('should match valid given product name', () => {
const myBlyncProduct = new BlyncProduct('', '', BlyncLightProductsEnum.BLYNCLIGHT_MINI, 1)
expect(myBlyncProduct.isProductNameMatch(BlyncLightProductsEnum.BLYNCLIGHT_MINI)).toBe(true)
})

test('shouldnt match invalid given vendor and product id', () => {
Expand All @@ -19,6 +24,11 @@ describe('BlyncProduct', () => {
BlyncLightProductsEnum.BLYNCLIGHT_WIRELESS,
13
)
expect(myBlyncProduct.isBlyncMatch(11277, 9)).toBe(false)
expect(myBlyncProduct.isVendorIdProductIdMatch(11277, 9)).toBe(false)
})

test('shouldnt match invalid given product name', () => {
const myBlyncProduct = new BlyncProduct('', '', BlyncLightProductsEnum.BLYNCLIGHT_WIRELESS, 1)
expect(myBlyncProduct.isProductNameMatch(BlyncLightProductsEnum.BLYNCLIGHT_MINI)).toBe(false)
})
})