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.
