Defining a home automation DSL

I've barely toyed with SwiftUI, but has gotten me thinking about declarative languages, and I'd like to try to make a home automation language as a Swift-based DSL. Thing is, I don't really know how Swift does its magic, with the bindings and such. But I think that's what I need.

I spent the last half-hour just spitballing some potential language constructs, and I've gotten something that sort-of compiles (but is nowhere near being an operable product). But the last little bit I've run into is, I think, where I'd want some sort of binding.

There may not be enough here to understand what I'm driving at, but maybe there is. Imagine defining a set of rules like this:

//	Create devices so we can set up rules for them.

//	Some switches that can be turned on or off, and queried for their current on/off state…

let overheadLights = Device(serviceID: "urn:upnp-org:serviceId:SwitchPower1", number: 5)
let deskLight = Device(serviceID: "urn:upnp-org:serviceId:SwitchPower1", number: 34)
let waterHeater = Device(serviceID: "urn:upnp-org:serviceId:SwitchPower1", number: 25)

//	We want a lot of our rules to depend on whether or not someone is present.
//	This defines occupancy by whether or not the overhead lights are on. An
//	alternative occupancy might be "Rick’s iPhone is present."

let occupied = overheadLights.on

//	Schedule periods can be defined…

let summer = June...September
let winter = October...May

let onPeak = summer.weekdays(1600...2100)
let midPeak = summer.weekends(1600...2100) || winter.daily(1600...2100)
let offPeak = summer.weekdays(2100...1600) || winter.daily(2100...0800)
let superOffPeak = winter.daily(0800...1600)

//	Create a rule that turns on the water heater any time the place is
//	occupied, except during peak electricity rate ToU periods…

waterHeater.on = occupied && !onPeak    //  This is probably a binding, no?

The result of executing this swift code once should be to set up some internal data structures that the controller code can then use to keep all the devices in sync according to the rules. A quick stab at making that code compile looks like this. Note that Daily will probably be some kind of data structure that holds a set of periods of time.

struct
TimeOfYear
{
	let			month			:	Int?
	let			day				:	Int?
	let			hour			:	Int?
	let			minute			:	Int?
	let			second			:	Int?
	
	
	init(month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil, second: Int? = nil)
	{
		self.month = month
		self.day = day
		self.hour = hour
		self.minute = minute
		self.second = second
	}
}

extension
TimeOfYear : Comparable
{
	static
	func < (lhs: TimeOfYear, rhs: TimeOfYear)
		-> Bool
	{
		return true
	}
	
}

struct
Period
{
	let	start			:	TimeOfYear
	let	end				:	TimeOfYear
}

let January			=	TimeOfYear(month: 1)
let February		=	TimeOfYear(month: 2)
let May				=	TimeOfYear(month: 5)
let June			=	TimeOfYear(month: 6)
let September		=	TimeOfYear(month: 9)
let October			=	TimeOfYear(month: 10)

let foo = June...September



struct
Device
{
	init(serviceID inServiceID: String, number inNumber: Int)
	{
	}
	
	var		on			:	Bool
}

struct
Daily
{
	func
	weekdays(_ timeRange: ClosedRange<Int>)
		-> Daily
	{
		return Daily()
	}
	
	func
	weekends(_ timeRange: ClosedRange<Int>)
		-> Daily
	{
		return Daily()
	}
	
	func
	daily(_ timeRange: ClosedRange<Int>)
		-> Daily
	{
		return Daily()
	}
}

func
||(lhs: Daily, rhs: Daily)
	-> Daily
{
}

func
...(lhs: TimeOfYear, rhs: TimeOfYear)
	-> Daily
{
}

This declarative approach to home automation should bring the same benefits that it does to wiring up UI elements. Any advice or suggestions for how to make the rule implementation “really nice,” even at the expense of complex support infrastructure, would be much appreciated.

Thanks!

Yeah, I knew that much, but I don't really know how to use them, you know? But I'll take a look at the Plot example, maybe that'll help. Thanks!

Maybe this collection on Swift DSLs might be helpful for you.

1 Like