Hey all!
This is nothing spectacular but it solves a first world problem that has been bugging us as a family with three kids for a while now. And I thought I’d share my copy & paste solution!
Like most kids, ours get pocket money. So every week (mostly on weekends) we’d have the same discussion: “Mummy & daddy, you need to give us our pocket money!” Of course, more often than not mummy & daddy would not currently have suitable change. So the matter would be postponed. Again. And again. And again. Until no one really remembered when and how much money was owed or paid.
Enter: Banking a la openHAB!
First I created a couple of .items:
/* Pocket Money */
// Just for neatness
Group PocketMoney "Taschengeld"
// Spoilt brat #1
Number PocketMoneyKid1 "Taschengeld Kind 1 [%.2f EUR]" (PocketMoney)
Switch PocketMoneyKid1Withdraw5 "5 EUR abheben" (PocketMoney) { expire="1s,command=OFF" }
Switch PocketMoneyKid1Withdraw10 "10 EUR abheben" (PocketMoney) { expire="1s,command=OFF" }
// Spoilt brat #2
Number PocketMoneyKid2 "Taschengeld Kind 2 [%.2f EUR]" (PocketMoney)
Switch PocketMoneyKid2Withdraw5 "5 EUR abheben" (PocketMoney) { expire="1s,command=OFF" }
Switch PocketMoneyKid2Withdraw10 "10 EUR abheben" (PocketMoney) { expire="1s,command=OFF" }
// etc...
This basically creates (in this case) two virtual bank accounts and two push buttons for each account to “withdraw” money every time we hand cash to the kids. Note that in order to turn the switches into push buttons I use the expire binding. This must simply be activated via Paper UI. In most installations this is probably already in use anyway.
Second, we need some basic .rules logic to power our poor man’s ATM.
/*
Sugar function that just subtracts the given amount. The Bank of Mum and Dad does
not give out loans, so we make sure the amount stays equal to or above zero.
*/
val Functions$Function2<NumberItem, Integer, Number> withdraw = [ item, amount |
val oldAmount = item.state as Number
if (oldAmount < amount) {
// not enough money
return oldAmount
} else {
return oldAmount - amount
}
]
/*
Optional:
It makes sense to use the persistence service so the bank does not crash
along with openHAB. A simple mapdb persistence is sufficient. I use a "Switch"
item named PersistenceLoaded that is ON or NULL at the start of the system and
switches to OFF after a couple of seconds to give persistence time to restore
the item values.
After this time has passed I do some initializations should the items still be
initial. In this case I initialize the "bank accounts" with zeroes. Time to start
saving, kids!
*/
rule "Persistence Loaded"
when
Item PersistenceLoaded changed to OFF
then
if (PocketMoneyKid1.state == NULL || PocketMoneyKid1.state == UNDEF) {
PocketMoneyKid1.sendCommand(0)
}
// etc.
end
/*
Let's put some money in the bank! I do this every Friday at noon. As for
the initial amount (should there be any): Just use a temporary rule with a
simple postUpdate() one-liner to get things going.
*/
rule "Increment Pocket Money"
when
Time cron "0 0 12 ? * FRI" //Every Friday at 12
then
// EUR 2.50 every week
PocketMoneyKid1.postUpdate((PocketMoneyKid1.state as DecimalType) + 2.5)
// etc.
end
/*
Our ATM needs push buttons. I know this is a very basic solution. But it serves our purposes.
Feel free to be creative. :-)
*/
rule "Withdraw 5 EUR Kid 1"
when
Item PocketMoneyKid1Withdraw5 changed to ON
then
PocketMoneyKid1.postUpdate(
withdraw.apply(PocketMoneyKid1, 5)
)
end
rule "Withdraw 10 EUR Kid 1"
when
Item PocketMoneyKid1Withdraw10 changed to ON
then
PocketMoneyKid1.postUpdate(
withdraw.apply(PocketMoneyKid1, 10)
)
end
The last step is visualisation. I use HABPanel although it is just a matter of exposing the items by some means. My solution looks like this. For every “account” I use one dummy control to display the amount and two button controls to “withdraw” money in either 5 or 10 EUR tiers.
That’s it! No more discussions on how much money is owed. Just keep the item change log files in case the kids decide to take legal action because they feel they weren’t given enough.