diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 59f4f71..7faaf9d 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -28,7 +28,7 @@ module.exports = defineConfig(({ useVue, useNode, useTypeScript }) => { } }, { - files: ['src/renderer/**/*.ts', 'src/renderer/**/*.js', 'src/renderer/**/*.vue'], + files: ['src/renderer/**/*.ts', 'src/renderer/**/*.tsx', 'src/renderer/**/*.js', 'src/renderer/**/*.vue'], parserOptions: { project: './tsconfig.web.json' } diff --git a/PLAN.md b/PLAN.md index 5f1ee5f..52f9c63 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1,11 +1,6 @@ - Milestones - v2.1 - (#86) Add a means to select a not-in-use port for the tRPC channel. - - (#85) Attempt to secure `serialport` interactione. - - More drivers. - - (#88) Add means to mark and label experimental drivers. - - (#83) Shinybow - - (#84) TESmart - v2.2 - Move more modules to core. - tRPC over Electron IPC. @@ -24,9 +19,7 @@ - Need a means to identify it's URL via the local UI. - May need a way to disable the power-off button in the remote UI. - Drivers - - Shinybow - Monoprice Blackbird - J-Tech Digital -- Need to find actual command list. - ASHATA -- Now unable to find. - - TESmart -- Brand of Tesla Elec (like TelsaSmart) - No Hassle AV -- Need to contact. diff --git a/package.json b/package.json index 45fe349..f1aa0b6 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "@mdi/js": "^7.4.47", "@mdi/svg": "^7.4.47", "@sindresorhus/is": "^7.0.1", - "@sixxgate/lint": "^3.3.0", + "@sixxgate/lint": "^3.3.2", "@trpc/client": "^10.45.2", "@trpc/server": "^10.45.2", "@tsconfig/node20": "^20.1.4", @@ -74,7 +74,7 @@ "@types/ini": "^4.1.1", "@types/leveldown": "^4.0.6", "@types/levelup": "^5.1.5", - "@types/node": "^20.17.5", + "@types/node": "^20.17.6", "@types/pouchdb-core": "^7.0.15", "@types/pouchdb-find": "^7.3.3", "@types/ws": "^8.5.13", @@ -114,9 +114,9 @@ "js-base64": "^3.7.7", "levelup": "^5.1.1", "mime": "^4.0.4", - "npm-check-updates": "^17.1.9", + "npm-check-updates": "^17.1.10", "npm-run-all2": "^7.0.1", - "pinia": "^2.2.5", + "pinia": "^2.2.6", "pouchdb-adapter-leveldb-core": "^9.0.0", "pouchdb-core": "^9.0.0", "pouchdb-find": "^9.0.0", diff --git a/src/main/drivers/extron/sis.ts b/src/main/drivers/extron/sis.ts index 4d8b717..034bebe 100644 --- a/src/main/drivers/extron/sis.ts +++ b/src/main/drivers/extron/sis.ts @@ -1,6 +1,5 @@ -import Logger from 'electron-log' import { defineDriver, kDeviceCanDecoupleAudioOutput, kDeviceSupportsMultipleOutputs } from '../../services/drivers' -import { createCommandStream } from '../../services/stream' +import { useExtronSisProtocol } from '../../services/protocols/extronSis' const extronSisDriver = defineDriver({ enabled: true, @@ -14,54 +13,7 @@ const extronSisDriver = defineDriver({ } }, capabilities: kDeviceSupportsMultipleOutputs | kDeviceCanDecoupleAudioOutput, - setup: () => { - async function sendCommand(uri: string, command: string) { - const connection = await createCommandStream(uri, { - baudRate: 9600, - dataBits: 8, - stopBits: 1, - parity: 'none', - timeout: 5000, - keepAlive: true - }) - - // TODO: Other situation handlers... - connection.on('data', (data) => { - Logger.debug(`extronSisDriver: return: ${String(data)}`) - }) - connection.on('error', (error) => { - Logger.error(`extronSisDriver: ${error.message}`) - }) - - await connection.write(command) - await connection.close() - } - - async function activate(uri: string, input: number, videoOutput: number, audioOutput: number) { - Logger.log(`extronSisDriver.activate(${input}, ${videoOutput}, ${audioOutput})`) - const videoCommand = `${input}*${videoOutput}%` - const audioCommand = `${input}*${audioOutput}$` - await sendCommand(uri, `${videoCommand}\r\n${audioCommand}\r\n`) - } - - async function powerOn() { - Logger.log('extronSisDriver.powerOn') - Logger.debug('extronSisDriver.powerOn is a no-op') - await Promise.resolve() - } - - async function powerOff() { - Logger.log('extronSisDriver.powerOff') - Logger.debug('extronSisDriver.powerOff is a no-op') - await Promise.resolve() - } - - return { - activate, - powerOn, - powerOff - } - } + setup: useExtronSisProtocol }) export default extronSisDriver diff --git a/src/main/drivers/shinybow/v2.ts b/src/main/drivers/shinybow/v2.ts new file mode 100644 index 0000000..50c56da --- /dev/null +++ b/src/main/drivers/shinybow/v2.ts @@ -0,0 +1,19 @@ +import { defineDriver, kDeviceSupportsMultipleOutputs } from '../../services/drivers' +import { useShinybowV2Protocol } from '../../services/protocols/shinybow' + +const shinybowV2 = defineDriver({ + enabled: true, + experimental: true, + guid: '75FB7ED2-EE3A-46D5-B11F-7D8C3C208E7C', + localized: { + en: { + title: 'Shinybow v2.0 compatible matrix switch', + company: 'ShinybowUSA', + provider: 'BridgeCmdr contributors' + } + }, + capabilities: kDeviceSupportsMultipleOutputs, + setup: useShinybowV2Protocol +}) + +export default shinybowV2 diff --git a/src/main/drivers/shinybow/v3.ts b/src/main/drivers/shinybow/v3.ts new file mode 100644 index 0000000..c41a416 --- /dev/null +++ b/src/main/drivers/shinybow/v3.ts @@ -0,0 +1,19 @@ +import { defineDriver, kDeviceSupportsMultipleOutputs } from '../../services/drivers' +import { useShinybowV3Protocol } from '../../services/protocols/shinybow' + +const shinybowV3 = defineDriver({ + enabled: true, + experimental: true, + guid: 'BBED08A1-C749-4733-8F2E-96C9B56C0C41', + localized: { + en: { + title: 'Shinybow v3.0 compatible matrix switch', + company: 'ShinybowUSA', + provider: 'BridgeCmdr contributors' + } + }, + capabilities: kDeviceSupportsMultipleOutputs, + setup: useShinybowV3Protocol +}) + +export default shinybowV3 diff --git a/src/main/drivers/sony/rs485.ts b/src/main/drivers/sony/rs485.ts index 7117fad..8dcc32f 100644 --- a/src/main/drivers/sony/rs485.ts +++ b/src/main/drivers/sony/rs485.ts @@ -1,15 +1,5 @@ -import Logger from 'electron-log' import { defineDriver, kDeviceHasNoExtraCapabilities } from '../../services/drivers' -import { createCommandStream } from '../../services/stream' -import { - createAddress, - createCommand, - kAddressAll, - kPowerOff, - kPowerOn, - kSetChannel -} from '../../services/support/sonyRs485' -import type { Command, CommandArg } from '../../services/support/sonyRs485' +import { useSonyBvmProtocol } from '../../services/protocols/sonyBvm' const sonyRs485Driver = defineDriver({ enabled: true, @@ -23,54 +13,7 @@ const sonyRs485Driver = defineDriver({ } }, capabilities: kDeviceHasNoExtraCapabilities, - setup: () => { - async function sendCommand(uri: string, command: Command, arg0?: CommandArg, arg1?: CommandArg) { - const source = createAddress(kAddressAll, 0) - const destination = createAddress(kAddressAll, 0) - const packet = createCommand(destination, source, command, arg0, arg1) - - const connection = await createCommandStream(uri, { - baudRate: 38400, - dataBits: 8, - stopBits: 1, - parity: 'odd', - timeout: 5000, - keepAlive: true - }) - - // TODO: Other situation handlers... - connection.on('data', (data) => { - Logger.debug(`sonyRs485Driver: return: ${String(data)}`) - }) - connection.on('error', (error) => { - Logger.error(`sonyRs485Driver: ${error.message}`) - }) - - await connection.write(packet) - await connection.close() - } - - async function activate(uri: string, input: number) { - Logger.log(`sonyRs485Driver.activate(${input})`) - await sendCommand(uri, kSetChannel, 1, input) - } - - async function powerOn(uri: string) { - Logger.log('sonyRs485Driver.powerOn') - await sendCommand(uri, kPowerOn) - } - - async function powerOff(uri: string) { - Logger.log('sonyRs485Driver.powerOff') - await sendCommand(uri, kPowerOff) - } - - return { - activate, - powerOn, - powerOff - } - } + setup: useSonyBvmProtocol }) export default sonyRs485Driver diff --git a/src/main/drivers/tesla-smart/kvm.ts b/src/main/drivers/tesla-smart/kvm.ts index f04f85e..86e6796 100644 --- a/src/main/drivers/tesla-smart/kvm.ts +++ b/src/main/drivers/tesla-smart/kvm.ts @@ -1,6 +1,5 @@ -import Logger from 'electron-log' import { defineDriver, kDeviceHasNoExtraCapabilities } from '../../services/drivers' -import { createCommandStream } from '../../services/stream' +import { useTeslaElecKvmProtocol } from '../../services/protocols/teslaElec' const teslaSmartKvmDriver = defineDriver({ enabled: true, @@ -14,52 +13,7 @@ const teslaSmartKvmDriver = defineDriver({ } }, capabilities: kDeviceHasNoExtraCapabilities, - setup: () => { - async function sendCommand(uri: string, command: Buffer) { - const connection = await createCommandStream(uri, { - baudRate: 9600, - dataBits: 8, - stopBits: 1, - parity: 'none', - timeout: 5000, - keepAlive: true - }) - - // TODO: Other situation handlers... - connection.on('data', (data) => { - Logger.debug(`teslaSmartKvmDriver: return: ${String(data)}`) - }) - connection.on('error', (error) => { - Logger.error(`teslaSmartKvmDriver: ${error.message}`) - }) - - await connection.write(command) - await connection.close() - } - - async function activate(uri: string, input: number) { - Logger.log(`teslaSmartKvmDriver.activate(${input})`) - await sendCommand(uri, Buffer.of(0xaa, 0xbb, 0x03, 0x01, input, 0xee)) - } - - async function powerOn() { - Logger.log('teslaSmartKvmDriver.powerOn') - Logger.debug('teslaSmartKvmDriver.powerOn is a no-op') - await Promise.resolve() - } - - async function powerOff() { - Logger.log('teslaSmartKvmDriver.powerOff') - Logger.debug('teslaSmartKvmDriver.powerOff is a no-op') - await Promise.resolve() - } - - return { - activate, - powerOn, - powerOff - } - } + setup: useTeslaElecKvmProtocol }) export default teslaSmartKvmDriver diff --git a/src/main/drivers/tesla-smart/matrix.ts b/src/main/drivers/tesla-smart/matrix.ts index f34aa48..5f1c329 100644 --- a/src/main/drivers/tesla-smart/matrix.ts +++ b/src/main/drivers/tesla-smart/matrix.ts @@ -1,6 +1,5 @@ -import Logger from 'electron-log' import { defineDriver, kDeviceSupportsMultipleOutputs } from '../../services/drivers' -import { createCommandStream } from '../../services/stream' +import { useTeslaElecMatrixProtocol } from '../../services/protocols/teslaElec' const teslaSmartMatrixDriver = defineDriver({ enabled: true, @@ -14,57 +13,7 @@ const teslaSmartMatrixDriver = defineDriver({ } }, capabilities: kDeviceSupportsMultipleOutputs, - setup: () => { - const sendCommand = async (uri: string, command: Buffer) => { - const connection = await createCommandStream(uri, { - baudRate: 9600, - dataBits: 8, - stopBits: 1, - parity: 'none', - timeout: 5000, - keepAlive: true - }) - - // TODO: Other situation handlers... - connection.on('data', (data) => { - Logger.debug(`teslaSmartMatrixDriver: return: ${String(data)}`) - }) - connection.on('error', (error) => { - Logger.error(`teslaSmartMatrixDriver: ${error.message}`) - }) - - await connection.write(command) - await connection.close() - } - - const toChannel = (n: number) => String(n).padStart(2, '0') - - async function activate(uri: string, input: number, output: number) { - Logger.log(`teslaSmartMatrixDriver.activate(${input}, ${output})`) - const command = `MT00SW${toChannel(input)}${toChannel(output)}NT` - await sendCommand(uri, Buffer.from(command, 'ascii')) - - await Promise.resolve() - } - - async function powerOn() { - Logger.log('teslaSmartMatrixDriver.powerOn') - Logger.debug('teslaSmartMatrixDriver.powerOn is a no-op') - await Promise.resolve() - } - - async function powerOff() { - Logger.log('teslaSmartMatrixDriver.powerOff') - Logger.debug('teslaSmartMatrixDriver.powerOff is a no-op') - await Promise.resolve() - } - - return { - activate, - powerOn, - powerOff - } - } + setup: useTeslaElecMatrixProtocol }) export default teslaSmartMatrixDriver diff --git a/src/main/drivers/tesla-smart/sdi.ts b/src/main/drivers/tesla-smart/sdi.ts index 41181cd..a93e6b3 100644 --- a/src/main/drivers/tesla-smart/sdi.ts +++ b/src/main/drivers/tesla-smart/sdi.ts @@ -1,6 +1,5 @@ -import Logger from 'electron-log' import { defineDriver, kDeviceHasNoExtraCapabilities } from '../../services/drivers' -import { createCommandStream } from '../../services/stream' +import { useTeslaElecSdiProtocol } from '../../services/protocols/teslaElec' const teslaSmartSdiDriver = defineDriver({ enabled: true, @@ -14,52 +13,7 @@ const teslaSmartSdiDriver = defineDriver({ } }, capabilities: kDeviceHasNoExtraCapabilities, - setup: () => { - async function sendCommand(uri: string, command: Buffer) { - const connection = await createCommandStream(uri, { - baudRate: 9600, - dataBits: 8, - stopBits: 1, - parity: 'none', - timeout: 5000, - keepAlive: true - }) - - // TODO: Other situation handlers... - connection.on('data', (data) => { - Logger.debug(`teslaSmartSdiDriver: return: ${String(data)}`) - }) - connection.on('error', (error) => { - Logger.error(`teslaSmartSdiDriver: ${error.message}`) - }) - - await connection.write(command) - await connection.close() - } - - async function activate(uri: string, input: number) { - Logger.log(`teslaSmartSdiDriver.activate(${input})`) - await sendCommand(uri, Buffer.of(0xaa, 0xcc, 0x01, input)) - } - - async function powerOn() { - Logger.log('teslaSmartSdiDriver.powerOn') - Logger.debug('teslaSmartSdiDriver.powerOn is a no-op') - await Promise.resolve() - } - - async function powerOff() { - Logger.log('teslaSmartSdiDriver.powerOff') - Logger.debug('teslaSmartSdiDriver.powerOff is a no-op') - await Promise.resolve() - } - - return { - activate, - powerOn, - powerOff - } - } + setup: useTeslaElecSdiProtocol }) export default teslaSmartSdiDriver diff --git a/src/main/drivers/tesmart/kvm.ts b/src/main/drivers/tesmart/kvm.ts new file mode 100644 index 0000000..150a8c7 --- /dev/null +++ b/src/main/drivers/tesmart/kvm.ts @@ -0,0 +1,19 @@ +import { defineDriver, kDeviceHasNoExtraCapabilities } from '../../services/drivers' +import { useTeslaElecKvmProtocol } from '../../services/protocols/teslaElec' + +const tesmartKvmDriver = defineDriver({ + enabled: true, + experimental: true, + guid: '2B4EDB8E-D2D6-4809-BA18-D5B1785DA028', + localized: { + en: { + title: 'TESmart KVM-compatible switch', + company: 'Tesla Elec Technology Co.,Ltd', + provider: 'BridgeCmdr contributors' + } + }, + capabilities: kDeviceHasNoExtraCapabilities, + setup: useTeslaElecKvmProtocol +}) + +export default tesmartKvmDriver diff --git a/src/main/drivers/tesmart/matrix.ts b/src/main/drivers/tesmart/matrix.ts new file mode 100644 index 0000000..174fe92 --- /dev/null +++ b/src/main/drivers/tesmart/matrix.ts @@ -0,0 +1,19 @@ +import { defineDriver, kDeviceSupportsMultipleOutputs } from '../../services/drivers' +import { useTeslaElecMatrixProtocol } from '../../services/protocols/teslaElec' + +const tesmartMatrixDriver = defineDriver({ + enabled: true, + experimental: true, + guid: '01B8884C-1D7D-4451-883D-3C8F18E17B14', + localized: { + en: { + title: 'TESmart matrix-compatible switch', + company: 'Tesla Elec Technology Co.,Ltd', + provider: 'BridgeCmdr contributors' + } + }, + capabilities: kDeviceSupportsMultipleOutputs, + setup: useTeslaElecMatrixProtocol +}) + +export default tesmartMatrixDriver diff --git a/src/main/drivers/tesmart/sdi.ts b/src/main/drivers/tesmart/sdi.ts new file mode 100644 index 0000000..4901e54 --- /dev/null +++ b/src/main/drivers/tesmart/sdi.ts @@ -0,0 +1,19 @@ +import { defineDriver, kDeviceHasNoExtraCapabilities } from '../../services/drivers' +import { useTeslaElecSdiProtocol } from '../../services/protocols/teslaElec' + +const tesmartSdiDriver = defineDriver({ + enabled: true, + experimental: true, + guid: '8C524E65-83EF-4AEF-B0DA-29C4582AA4A0', + localized: { + en: { + title: 'TESmart SDI-compatible switch', + company: 'Tesla Elec Technology Co.,Ltd', + provider: 'BridgeCmdr contributors' + } + }, + capabilities: kDeviceHasNoExtraCapabilities, + setup: useTeslaElecSdiProtocol +}) + +export default tesmartSdiDriver diff --git a/src/main/services/protocols/extronSis.ts b/src/main/services/protocols/extronSis.ts new file mode 100644 index 0000000..23dfca4 --- /dev/null +++ b/src/main/services/protocols/extronSis.ts @@ -0,0 +1,32 @@ +import Logger from 'electron-log' +import { memo } from 'radash' +import { useProtocol } from './protocols' + +export const useExtronSisProtocol = memo(function useExtronSisProtocol() { + const kProtocol = 'extron/sis' + + const { sendCommand } = useProtocol(kProtocol) + + async function activate(uri: string, input: number, videoOutput: number, audioOutput: number) { + Logger.log(`${kProtocol}/tie(${input}, ${videoOutput}, ${audioOutput})`) + const videoCommand = `${input}*${videoOutput}%` + const audioCommand = `${input}*${audioOutput}$` + await sendCommand(uri, `${videoCommand}\r\n${audioCommand}\r\n`) + } + + async function powerOn() { + Logger.log(`${kProtocol}/powerOn; no-op`) + await Promise.resolve() + } + + async function powerOff() { + Logger.log(`${kProtocol}/powerOff; no-op`) + await Promise.resolve() + } + + return { + activate, + powerOn, + powerOff + } +}) diff --git a/src/main/services/protocols/protocols.ts b/src/main/services/protocols/protocols.ts new file mode 100644 index 0000000..571cba8 --- /dev/null +++ b/src/main/services/protocols/protocols.ts @@ -0,0 +1,48 @@ +import Logger from 'electron-log' +import { memo } from 'radash' +import { createCommandStream } from '../stream' + +interface ProtocolOptions { + baudRate?: number + dataBits?: 5 | 6 | 7 | 8 + stopBits?: 1 | 1.5 | 2 + parity?: 'none' | 'odd' | 'even' + timeout?: number + // TODO: onError? + // TODO: onData? + // TODO: Other situation handlers... +} + +export const useProtocol = memo(function useProtocol(name: string, options: ProtocolOptions = {}) { + // Options and defaults. + const { baudRate = 9600, dataBits = 8, stopBits = 1, parity = 'none', timeout = 5000 } = options + + async function sendCommand(uri: string, command: Buffer): Promise + async function sendCommand(uri: string, command: string, encoding?: BufferEncoding): Promise + async function sendCommand(uri: string, command: Buffer | string, encoding?: BufferEncoding) { + const connection = await createCommandStream(uri, { + baudRate, + dataBits, + stopBits, + parity, + timeout, + keepAlive: true + }) + + connection.on('data', (data) => { + Logger.debug(`${name}; returned ${String(data)}`) + }) + connection.on('error', (error) => { + Logger.error(`${name}; ${error.message}`) + }) + + if (typeof command === 'string') { + command = Buffer.from(command, encoding ?? 'ascii') + } + + await connection.write(command) + await connection.close() + } + + return { sendCommand } +}) diff --git a/src/main/services/protocols/shinybow.ts b/src/main/services/protocols/shinybow.ts new file mode 100644 index 0000000..9200530 --- /dev/null +++ b/src/main/services/protocols/shinybow.ts @@ -0,0 +1,59 @@ +import Logger from 'electron-log' +import { memo } from 'radash' +import { useProtocol } from './protocols' + +export const useShinybowV2Protocol = memo(function useShinybowV2Protocol() { + const kProtocol = 'shinybow/v2.0' + const { sendCommand } = useProtocol(kProtocol) + + const toChannel = (n: number) => String(n).padStart(2, '0') + + async function activate(uri: string, input: number, output: number) { + Logger.log(`${kProtocol}/tie(${input}, ${output})`) + await sendCommand(uri, `OUTPUT${toChannel(output)} ${toChannel(input)};\r\n`) + } + + async function powerOn(uri: string) { + Logger.log(`${kProtocol}/powerOn`) + await sendCommand(uri, 'POWER 01;\r\n') + } + + async function powerOff(uri: string) { + Logger.log(`${kProtocol}/powerOff`) + await sendCommand(uri, 'POWER 00;\r\n') + } + + return { + activate, + powerOn, + powerOff + } +}) + +export const useShinybowV3Protocol = memo(function useShinybowV3Protocol() { + const kProtocol = 'shinybow/v3.0' + const { sendCommand } = useProtocol(kProtocol) + + const toChannel = (n: number) => String(n).padStart(3, '0') + + async function activate(uri: string, input: number, output: number) { + Logger.log(`${kProtocol}/tie(${input}, ${output})`) + await sendCommand(uri, `OUTPUT${toChannel(output)} ${toChannel(input)};\r\n`) + } + + async function powerOn(uri: string) { + Logger.log(`${kProtocol}/powerOn`) + await sendCommand(uri, 'POWER 001;\r\n') + } + + async function powerOff(uri: string) { + Logger.log(`${kProtocol}/powerOff`) + await sendCommand(uri, 'POWER 000;\r\n') + } + + return { + activate, + powerOn, + powerOff + } +}) diff --git a/src/main/services/protocols/sonyBvm.ts b/src/main/services/protocols/sonyBvm.ts new file mode 100644 index 0000000..5719ab1 --- /dev/null +++ b/src/main/services/protocols/sonyBvm.ts @@ -0,0 +1,46 @@ +import Logger from 'electron-log' +import { memo } from 'radash' +import { useProtocol } from './protocols' +import { createAddress, createCommand, kAddressAll, kPowerOff, kPowerOn, kSetChannel } from './sonyRs485' +import type { Command, CommandArg } from './sonyRs485' + +export const useSonyBvmProtocol = memo(function useSonyBvmProtocol() { + const kProtocol = 'sony/bvm' + + const { sendCommand: sendRawCommand } = useProtocol(kProtocol, { + baudRate: 38400, + dataBits: 8, + stopBits: 1, + parity: 'odd', + timeout: 5000 + }) + + async function sendCommand(uri: string, command: Command, arg0?: CommandArg, arg1?: CommandArg) { + const source = createAddress(kAddressAll, 0) + const destination = createAddress(kAddressAll, 0) + const packet = createCommand(destination, source, command, arg0, arg1) + + await sendRawCommand(uri, packet) + } + + async function activate(uri: string, input: number) { + Logger.log(`${kProtocol}/channel(${input})`) + await sendCommand(uri, kSetChannel, 1, input) + } + + async function powerOn(uri: string) { + Logger.log(`${kProtocol}/powerOn`) + await sendCommand(uri, kPowerOn) + } + + async function powerOff(uri: string) { + Logger.log(`${kProtocol}/powerOff`) + await sendCommand(uri, kPowerOff) + } + + return { + activate, + powerOn, + powerOff + } +}) diff --git a/src/main/services/support/sonyRs485.ts b/src/main/services/protocols/sonyRs485.ts similarity index 100% rename from src/main/services/support/sonyRs485.ts rename to src/main/services/protocols/sonyRs485.ts diff --git a/src/main/services/protocols/teslaElec.ts b/src/main/services/protocols/teslaElec.ts new file mode 100644 index 0000000..867e931 --- /dev/null +++ b/src/main/services/protocols/teslaElec.ts @@ -0,0 +1,85 @@ +import Logger from 'electron-log' +import { memo } from 'radash' +import { useProtocol } from './protocols' + +export const useTeslaElecKvmProtocol = memo(function useTeslaElecKvmProtocol() { + const kProtocol = 'teslaElec/kvm' + const { sendCommand } = useProtocol(kProtocol) + + async function activate(uri: string, input: number) { + Logger.log(`${kProtocol} << channel(${input})`) + await sendCommand(uri, Buffer.of(0xaa, 0xbb, 0x03, 0x01, input, 0xee)) + } + + async function powerOn() { + Logger.log(`${kProtocol}/powerOn; no-op`) + await Promise.resolve() + } + + async function powerOff() { + Logger.log(`${kProtocol}/powerOff; no-op`) + await Promise.resolve() + } + + return { + activate, + powerOn, + powerOff + } +}) + +export const useTeslaElecMatrixProtocol = memo(function useTeslaElecMatrixProtocol() { + const kProtocol = 'teslaElec/matrix' + const { sendCommand } = useProtocol(kProtocol) + + const toChannel = (n: number) => String(n).padStart(2, '0') + + async function activate(uri: string, input: number, output: number) { + Logger.log(`${kProtocol} << tie(${input}, ${output})`) + await sendCommand(uri, `MT00SW${toChannel(input)}${toChannel(output)}NT\r\n`) + + await Promise.resolve() + } + + async function powerOn() { + Logger.log(`${kProtocol}/powerOn; no-op`) + await Promise.resolve() + } + + async function powerOff() { + Logger.log(`${kProtocol}/powerOff; no-op`) + await Promise.resolve() + } + + return { + activate, + powerOn, + powerOff + } +}) + +export const useTeslaElecSdiProtocol = memo(function useTeslaElecSdiProtocol() { + const kProtocol = 'teslaElec/sdi' + const { sendCommand } = useProtocol(kProtocol) + + async function activate(uri: string, input: number) { + Logger.log(`${kProtocol} << channel(${input})`) + await sendCommand(uri, Buffer.of(0xaa, 0xcc, 0x01, input)) + } + + async function powerOn() { + Logger.log(`${kProtocol}/powerOn; no-op`) + await Promise.resolve() + } + + async function powerOff() { + Logger.log(`${kProtocol}/powerOff; no-op`) + await Promise.resolve() + } + + return { + activate, + powerOn, + powerOff + } +}) diff --git a/src/renderer/components/Highlight.tsx b/src/renderer/components/Highlight.tsx new file mode 100644 index 0000000..7d6ebc9 --- /dev/null +++ b/src/renderer/components/Highlight.tsx @@ -0,0 +1,22 @@ +import { Comment, h, Text } from 'vue' + +interface HighlightProps { + text?: string + search?: string +} + +export function Highlight({ text, search }: HighlightProps) { + if (!text) return h(Comment, 'Nothing') + if (!search) return h(Text, text) + const start = text.indexOf(search) + if (start === -1) return h(Text, text) + const end = start + search.length + + return ( + <> + {text.substring(0, start)} + {text.substring(start, end)} + {text.substring(end)} + + ) +} diff --git a/src/renderer/modals/SwitchDialog.vue b/src/renderer/modals/SwitchDialog.vue index e073a36..57883b4 100644 --- a/src/renderer/modals/SwitchDialog.vue +++ b/src/renderer/modals/SwitchDialog.vue @@ -3,6 +3,7 @@ import { mdiClose, mdiFlask } from '@mdi/js' import { useVModel } from '@vueuse/core' import { computed, ref, reactive, onBeforeMount } from 'vue' import { useI18n } from 'vue-i18n' +import { Highlight } from '../components/Highlight' import { useLocation } from '../hooks/location' import { useRules, useValidation } from '../hooks/validation' import useDrivers from '../services/driver' @@ -52,6 +53,7 @@ const location = computed({ const { locationPath, pathTypes, pathType, path } = useLocation(location, () => ports.items) const driver = computed(() => drivers.items.find((d) => d.guid === target.value.driverId)) +const driverSerach = ref('') function confirm() { isVisible.value = false @@ -119,10 +121,12 @@ const isBusy = computed(() => drivers.isBusy || ports.isBusy) v-bind="getStatus(v$.title)" /> drivers.isBusy || ports.isBusy)