Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-switch support #2

Merged
merged 5 commits into from Nov 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 26 additions & 1 deletion config.json.sample
Expand Up @@ -4,5 +4,30 @@
"topic": "tuya/",
"mqtt_user": "",
"mqtt_pass": "",
"qos": 2
"qos": 2,
"defaultDeviceType": "SimpleSwitch",
"defaultDeviceProperties": {
"SimpleSwitch": {
"template": {
"state": {
"key": 1,
"type": "bool"
}
}
},
"SimpleDimmer": {
"state": {
"key": 1,
"type": "bool"
},
"brightness_state": {
"key": 2,
"type": "int",
"topicMin": 1,
"topicMax": 100,
"stateMath": "/2.55",
"commandMath": "*2.55"
}
}
}
}
28 changes: 28 additions & 0 deletions devices.conf.sample
@@ -0,0 +1,28 @@
[
{
name: "Kitchen Table",
id: "11110123456789abcdef",
key: "1abcdef012345678",
mdl: "Light Switch"
},
{
name: "Bedroom Smart Controller",
id: "22220123456789abcdef",
key: "2abcdef012345678",
type: "SimpleSwitch",
dpsPower: [ 1, 2 ],
subNames: [ "Bedroom Light", "Bedroom Ceiling Fan" ]
},
{
name: "Living Room Ceiling Fan",
id: "22220123456789abcdef",
key: "2abcdef012345678",
mdl: "Fan Switch"
},
{
name: "Disabled Plug",
id: "33330123456789abcdef",
key: "3abcdef012345678",
enabled: false
}
]
2 changes: 1 addition & 1 deletion devices/generic-device.js
Expand Up @@ -4,7 +4,7 @@ const utils = require('../lib/utils')

class GenericDevice extends TuyaDevice {
async init() {
this.deviceData.mdl = 'Generic Device'
this.deviceData.mdl = this.config.mdl || 'Generic Device'
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test

Copy link
Owner Author

@dkrahmer dkrahmer Apr 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test 123

Copy link
Owner Author

@dkrahmer dkrahmer Apr 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test 456


// Check if custom template in device config
if (this.config.hasOwnProperty('template')) {
Expand Down
2 changes: 1 addition & 1 deletion devices/rgbtw-light.js
Expand Up @@ -28,7 +28,7 @@ class RGBTWLight extends TuyaDevice {
this.config.dpsColor = this.config.dpsColor ? this.config.dpsColor : this.guess.dpsColor
this.config.colorType = this.config.colorType ? this.config.colorType : this.guess.colorType

this.deviceData.mdl = 'RGBTW Light'
this.deviceData.mdl = this.config.mdl || 'RGBTW Light'
this.isRgbtwLight = true

// Set white value transform math
Expand Down
10 changes: 6 additions & 4 deletions devices/simple-dimmer.js
Expand Up @@ -6,11 +6,13 @@ const utils = require('../lib/utils')
class SimpleDimmer extends TuyaDevice {
async init() {
// Set device specific variables
this.config.dpsPower = this.config.dpsPower ? this.config.dpsPower : 1
this.config.dpsBrightness = this.config.dpsBrightness ? this.config.dpsBrightness : 2
this.config.brightnessScale = this.config.brightnessScale ? this.config.brightnessScale : 255
if (typeof this.config.dpsPower === 'undefined')
this.config.dpsPower = 1
if (typeof this.config.dpsBrightness === 'undefined')
this.config.dpsBrightness = 1
this.config.brightnessScale = this.config.brightnessScale || 255

this.deviceData.mdl = 'Dimmer Switch'
this.deviceData.mdl = this.config.mdl || 'Dimmer Switch'

// Set white value transform math
let brightnessStateMath
Expand Down
121 changes: 99 additions & 22 deletions devices/simple-switch.js
Expand Up @@ -6,18 +6,30 @@ const utils = require('../lib/utils')
class SimpleSwitch extends TuyaDevice {
async init() {
// Set device specific variables
this.config.dpsPower = this.config.dpsPower ? this.config.dpsPower : 1
if (typeof this.config.dpsPower === 'undefined')
this.config.dpsPower = 1

this.deviceData.mdl = 'Switch/Socket'
if (!Array.isArray(this.config.dpsPower))
this.config.dpsPower = [ this.config.dpsPower ]

// Map generic DPS topics to device specific topic names
this.deviceTopics = {
state: {
key: this.config.dpsPower,
this.deviceType = this.config.deviceType || this.guessDeviceType(this.config.name, 'switch');
this.deviceData.mdl = this.config.mdl || this.guessDeviceMdl(this.config.name, this.deviceType, 'Switch/Socket')

// get all states for multi-switches
const states = this.config.dpsPower.map(dpsPower => {
return {
key: dpsPower,
type: 'bool'
}
})

// Map generic DPS topics to device specific topic names
this.deviceTopics = {
state: states
}

this.subNames = this.config.subNames

// Send home assistant discovery data and give it a second before sending state updates
this.initDiscovery()
await utils.sleep(1)
Expand All @@ -27,22 +39,87 @@ class SimpleSwitch extends TuyaDevice {
}

initDiscovery() {
const configTopic = 'homeassistant/switch/'+this.config.id+'/config'

const discoveryData = {
name: (this.config.name) ? this.config.name : this.config.id,
state_topic: this.baseTopic+'state',
command_topic: this.baseTopic+'command',
availability_topic: this.baseTopic+'status',
payload_available: 'online',
payload_not_available: 'offline',
unique_id: this.config.id,
device: this.deviceData
}

debugDiscovery('Home Assistant config topic: '+configTopic)
debugDiscovery(discoveryData)
this.publishMqtt(configTopic, JSON.stringify(discoveryData))
let states = this.deviceTopics.state
if (!Array.isArray(states)) {
states = [states]
}

let stateIndex = -1
for (const state of states) {
stateIndex++;
const uniqueId = `${this.config.id}${states.length == 1 ? '' : '_' + state.key}`
const configTopic = `homeassistant/${this.deviceType}/${uniqueId}/config`
let name = (this.subNames ? this.subNames[stateIndex] : null)
|| (this.config.name ? (this.config.name + (states.length == 1 ? '' : ' - ' + state.key)) : uniqueId)
const baseDpsTopic = `${this.baseTopic}${states.length == 1 ? '' : ('dps/' + state.key + '/')}`

const discoveryData = {
name: name,
state_topic: baseDpsTopic + 'state',
command_topic: baseDpsTopic + 'command',
availability_topic: this.baseTopic + 'status',
payload_available: 'online',
payload_not_available: 'offline',
unique_id: uniqueId,
device: this.deviceData
}

debugDiscovery('Home Assistant config topic: ' + configTopic)
debugDiscovery(discoveryData)
this.publishMqtt(configTopic, JSON.stringify(discoveryData))
}
}

guessDeviceType(deviceName, defaultDeviceType) {
let deviceType = defaultDeviceType;
if (!deviceName)
return deviceType

deviceName = deviceName.toLowerCase();

if (deviceName.includes('controller')) {
deviceType = 'switch'
}
else if (deviceName.includes('light') || deviceName.includes('lamp')) {
deviceType = 'light'
}
else if (deviceName.includes('fan')) {
deviceType = 'fan'
}

return deviceType
}

guessDeviceMdl(deviceName, deviceType, defaultMdl) {
let mdl = defaultMdl;
if (!deviceType)
return mdl

deviceType = deviceType.toLowerCase();
deviceName = deviceName.toLowerCase();

if (deviceName.includes('controller')) {
mdl = 'Switch'
}
else if (deviceType === 'light') {
mdl = 'Light Switch'
}
else if (deviceType === 'fan') {
mdl = 'Fan Switch'
}
else if (deviceType === 'switch') {
if (deviceName.includes('plug')) {
mdl = 'Switchable Plug'
}
else if (deviceName.includes('socket')) {
mdl = 'Switchable Socket'
}
else if (deviceName.includes('switch')) {
mdl = 'Switch'
}
}

return mdl;
}
}

Expand Down