Last active
July 17, 2022 01:44
-
-
Save josiahbryan/961dcf86147527ed23fa4ed976304970 to your computer and use it in GitHub Desktop.
Simple controller for use with the Wangdd22 Ethernet Relay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Simple controller for use with the Wangdd22 Ethernet Relay, available on Amazon for ~$35 | |
// | |
// See https://www.amazon.com/dp/B01MRQTFMJ?psc=1&ref=ppx_yo2ov_dt_b_product_details | |
// | |
// Special thanks to commentors on the product listing: | |
// Python Client: https://www.amazon.com/gp/customer-reviews/RAEHN60VSX3LV/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&ASIN=B01MRQTFMJ | |
// Config format: https://www.amazon.com/gp/customer-reviews/R19ZMADG7S2GX2/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&ASIN=B01MRQTFMJ | |
// | |
// This client just turns on/off the relays, doesn't handle config, but could easily be added thanks to the info | |
// in the linked comments above. | |
// | |
// Author: Josiah Bryan <josiahbryan@gmail.com> | |
// | |
import EventEmitter from 'events'; | |
import net from 'net'; | |
const PatchedLogger = global.console; | |
PatchedLogger.debug = global.console.log; | |
const NUM_RELAYS = 2; | |
const RELAY_ON = '1'; | |
const RELAY_OFF = '2'; | |
export class Wangdd22RelayClient extends EventEmitter { | |
/** | |
* Create an instance of the client and immediately connect. Will automatically reconnect | |
* if disconnected. | |
* | |
* @param {string} opts.host [default: 192.168.1.100] IP of the relay, defaults to factory-default setting | |
* @param {number} opts.port [default: 6722] Control port of the relay, probably won't need to change | |
* @param {bool} opts.reconnect [default: true] If true, will reconnect after `reconnectTimeout` ms when socket disconnects (unless you call '.end' on the client, which will disable reconnection) | |
* @param {number} opts.reconnectTimeout [default: 1000] Reconnection delay | |
* @param {string} opts.logger [default: console] Logger to use for debugging info (expects .debug and .info methods) | |
* @param {string} opts.name [default: 'Wangdd22RelayClient'] Name to print when logging for this client | |
*/ | |
constructor({ | |
host = '192.168.1.100', | |
port = 6722, | |
reconnect = true, | |
reconnectTimeout = 1000, | |
logger = PatchedLogger, | |
name = Wangdd22RelayClient.name, | |
} = {}) { | |
super(); | |
Object.assign(this, { | |
name, | |
host, | |
port, | |
logger, | |
reconnect, | |
reconnectTimeout, | |
connected: false, | |
}); | |
this.connect(); | |
} | |
/** | |
* Connect the socket - called internally by the constructor | |
*/ | |
connect() { | |
const { name, host, port, reconnect, reconnectTimeout, logger } = this; | |
logger.debug(`${name} connecting to ${host}:${port} ... `); | |
const client = new net.Socket(); | |
this.client = client; | |
client.connect({ host, port }, () => { | |
logger.info(`${name} connected successfully to ${host}:${port}`); | |
this.connected = true; | |
this.emit('connected'); | |
}); | |
client.on('data', (chunk) => { | |
const data = chunk.toString(); | |
logger.debug(`${name} received data from ${host}:${port}:`, data); | |
this.emit('data', data); | |
}); | |
client.on('end', () => { | |
logger.debug(`${name} disconnected from ${host}:${port}`); | |
this.connected = false; | |
this.emit('disconnected'); | |
}); | |
client.on('close', () => { | |
this.connected = false; | |
if (reconnect) { | |
this.timer = setTimeout(() => this.connect(), reconnectTimeout); | |
} | |
}); | |
} | |
/** | |
* Disconnect the socket manually, will not reconnect | |
*/ | |
end() { | |
const { name, host, port, client, connected, logger } = this; | |
if (client && connected) { | |
client.end(); | |
this.reconnect = false; | |
client.destroy(); | |
logger.warn( | |
`${name} shut down and destroyed connection to ${host}:${port}`, | |
); | |
} | |
} | |
/** | |
* Primary API method - turns the specified relay on or off | |
* | |
* @param {number} relayNum Relay number, must be between `1` and `2`, inclusive | |
* @param {boolean} on [default: `true`] If `true`, turns relay on, if `false`, turns relay off. Any other value (undefined/null/empty string) does nothing (returns immediately) | |
*/ | |
setRelayState(relayNum = 1, on = true) { | |
const { name, host, port, logger, client, connected } = this; | |
if (on === undefined || on === null) { | |
return; | |
} | |
if (!connected) { | |
logger.warn( | |
`${name} not connected to ${host}:${port} yet, cannot send relay command`, | |
); | |
} | |
if (relayNum < 1 || relayNum > NUM_RELAYS) { | |
logger.warn( | |
`${name}: Invalid relay number ${relayNum} for ${host}:${port}`, | |
); | |
return; | |
} | |
logger.debug( | |
`${name} setting relay ${relayNum} to ${ | |
on ? 'ON' : 'OFF' | |
} on ${host}:${port}`, | |
); | |
client.write(`${on ? RELAY_ON : RELAY_OFF}${relayNum}`); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example Usage: