Stream Deck and Homekit update.

I mentioned previously using HomeBridge to help control a fan with the Elgato Stream Deck. It felt like overkill and I later found a much more stable solution for this that I'll talk about below. However, Robert Hawdon sent me an update to the original code I was using that saves the current state of the switch so that it can restore the state through a HomeBridge restart or crash.


const port = 3000;

const express = require('express');
const bodyParser = require('body-parser');
const stateFile = './state.json';
var fs = require('fs');
let app = express();
app.use(bodyParser.text({ type: 'text/*' }))

var switches = {};

function saveState() {

	var data = JSON.stringify(switches);

	fs.writeFile(stateFile, data, function (err) {
		if (err) {
			console.log('There has been an error saving the switch state.');
			console.log(err.message);
			return;
		}
		console.log('State saved successfully.')
	});
}

function loadState() {

	if (fs.existsSync(stateFile)) {

		var data = fs.readFileSync(stateFile);

		try {
			switches = JSON.parse(data);
		}
		catch (err) {
			console.log('There has been an error reading the switch state.');
			console.log(err);
		}

	}
}

function getSwitchValue(switchName, trueValue, falseValue) {

	let value = switches[switchName];

	if (trueValue === undefined) {

		trueValue = true;
	} 

	if (falseValue == undefined) {

		falseValue = false;
	}

	if (value === undefined || value == false) {

		return falseValue;

	} else {
		
		return trueValue;
	}
}

function setSwitchValue(switchName, valueAsBoolean) {

	// Don't care about current state of switch - or if it exists or not at this point.
	switches[switchName] = valueAsBoolean;
	saveState();
}

// ==================
// General purpose getter to show the state of all switches in the browser.

app.get('/', (request, response) => {
	
	// return current state of all known switches
	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify(switches, null, 4));	
});


// HomeBridge http switch end points.
app.get('/switches/:switchName/on', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchOn called for switch: ", switchName);
	setSwitchValue(switchName, true);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});

app.get('/switches/:switchName/off', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchOff called for switch: ", switchName);

	setSwitchValue(switchName, false);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});

app.get('/switches/:switchName/status', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("switchStatus called for switch: ", switchName);

	let switchValue = getSwitchValue(switchName, "1", "0");
	response.setHeader('Content-Type', 'text/plain');
	response.send(switchValue);	
});


// ==================
// Stream Deck MCControl endpoints.

app.get('/switches/:switchName', (request, response) => {

	let switchName = request.params.switchName;

	//console.log("got status request for switch: ", switchName);

	let switchValue = getSwitchValue(switchName, "ON", "OFF");

	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify({ state: switchValue }));
});


app.post('/switches/:switchName', (request, response) => {
	
	let switchName = request.params.switchName;

	//console.log("switch set post called for switch: ", switchName);

	var data = request.body;
	console.log("Data: ", data);

	if (data == "ON") {

		switchState = true;

	} else if (data == "OFF") {

		switchState = false;
	}

	setSwitchValue(switchName, switchState);

	let switchValue = getSwitchValue(switchName, "ON", "OFF");
	response.setHeader('Content-Type', 'application/json');
	response.send(JSON.stringify({ state: switchValue }));
});



app.listen(port, (err) => {
	if (err) {
		return console.log('something bad happened', err)
	}

	loadState();
	console.log(`server is listening on ${port}`)
});


These days I'm not using HomeBridge at all. But, I still use the fan and turn it on and off with the StreamDeck. I do this with HomeControl for the Mac. This app lets you control all of your home kit devices and scenes with a menu on your mac. It also lets you use control devices with callback urls via the command line. You can create a script and execute that script with a button on the StreamDeck. However, It doesn't show the current state of the devine on the StreamDeck button with this technique.


#!/bin/bash

open -g "homecontrol://x-callback-url/run-action?action-type=switch-device-status&item-type=device&item-name=Fan&home-name=Home&activation-mode=toggle&authentication-token=1234"

You need to get the url to use here with the HomeControl app. There is an auth token that will be unique to your computer. I hope this update helps anyone trying to do something simmilar.

Hello Computer

"Thinking about Bailey"
2022/10/24 11:35 AM

Saying Goodbye to Bailey

We got Bailey when she was about 1 year old in October, 2008. We lost our first cat Trill the next year. Hard to believe that was 14 years ago. It doesn't feel like it's been that long.

Bailey

We let Bailey rest today. I miss her sitting in my lap every morning. She was such a sweet kitty.

Newer Posts Older Posts