Friday, January 29, 2016

12 Factor Config for .Net on Mono in a Docker

Recently I've been thinking about how to run a .Net application using Mono inside a Docker, along with this we'd like to use Twelve Factor config.

Whilst it is possible to use some library to access environment variables instead of using appSettings it becomes difficult for database and message broker URLs which other libraries may expect to find within the App.config or Web.config file.

The solution I came up with follows:

Build the application without an App.config moving the existing configuration file renaming it App.config.template

Substitute any environment variables you want with ${}.  E.g:

<amqp> <connections> <connection name="rabbit" server="${RABBITMQ_URL}" password="${RABBITMQ_PASSWORD}" /> </connections> </amqp>

Include within the Docker image a script named sub.sh similar to this and add it to /conf:

#!/bin/sh
while read line
do
    eval echo "$line"
done
Add your config template to /conf

Then in the DockerFile, if your CMD is:

CMD ["mono", "/app/foo.exe" ]
Change it to:

CMD /conf/sub.sh /conf/App.config.template > /app/App.config; mono /app/foo.exe
Now when you run your Docker image, pass in your environment variables as usual. In this case, I'd set the RABBITMQ_URL and the RABBITMQ_PASSWORD

You can also configure these in a file and pass it into the docker run command using --env-file

Thursday, January 21, 2016

Howto: Node-RED Change Hue Lights Temporarily On Door Open

We fitted a LightwaveRF magnetic sensor to a door to detect whether it is open or closed. The main driver behind this was to increase the level of the hallway lights for a predetermined period of time whenever the door was opened. Since we’re using coloured lights it makes sense to put the light back to how it was once the time period as elapsed. 

Node-RED does not offer a node as a means of storing state between, but it does offer functions which have access to a context object which can be used to store state between flows. 

I’ve created a flow which listens to the `domoticz/out` MQTT topic filters messages based on their Domoticz IDX value and furthers filters on the door switches `nvalue` where 1 indicates door open and 0 indicates door closed. 


On Door Open:
  1. Retrieve state of current light and if nothing already stored, store the current bulb state in the context. 
  2. Change the state of the bulb to a bright white. 
  3. Reset the timer in place if a door close event was received whilst the light is already bright. This would occur if the door is opened again whilst the light is in a brightened state. By not replacing the stored light state, we also avoid overwriting the original colour with the temporary brighter state. 

On Door Close:
  1. Instruct the ‘Record or Despatch’ node to restore the original state which sends the original light colour to the timer. 
  2. If the timer has expired, the original state is sent onto the hallway bulb
  3. A reset context message sent to the ‘Record or Despatch’ node to clear any saved light state. 

The ‘Record or Despatch’ node is a function with the following code:

if (msg.restore) {
    node.send({payload: context.previousState});
} if (msg.reset) {
    delete context.previousState;  
} else {
    if (!context.previousState) {
        context.previousState = msg.payload;
    }
}


Feel free to download the full flow here: 

Howto: Node Red Subflow for Hue Bulbs

When writing some flows for Node-RED controlling my Philips Hue bulbs; I wanted to read from a bulb do some work then write that same colour back to the bulb. When you perform a GET on a bulb, you get all of the information, whilst good this means it is a bit more inconvenient to PUT that back into a bulb as that API has a slightly different resource shape where the colour mode is determined by which values are submitted.

After using a group of nodes in one flow which did exactly this, I needed the same block in another flow. So I created a sub flow by selected those nodes, clicking the hamburger menu in the top right and choosing 'Subflows > Selection to Subflow'. This replaces the selected nodes with a single node which you can edit in a 'subflows' menu group in the left pane.

Download this selection and make your own subflow:
https://dl.dropboxusercontent.com/u/174818/HueInputToOutput.json?dl=1

Wednesday, January 20, 2016

Automatic Kitchen Lights



We recently purchased Hue bulbs for our Kitchen they’re great, but since we already have an RFXCom 433 unit (as per my blog on automating hifi), we wanted to automate the lights and invested in a Lightwave PIR motion sensor. 


I downloaded Domoticz [http://domoticz.com/] on an SD Card for my Raspberry PI and also installed node-red [http://nodered.org/] a tool for filtering and processing MQTT messages. 

Domoticz is used to store the state of the motion sensor and is configured to emit an MQTT message whenever the state changes. 

We also wanted the lights to have a different colour depending on the time of day we enter the kitchen, for example during the evening we might want a relaxing light, meal times a white light above the dining table and during the day some multi coloured lights, but not change them if they've already on. 

For each of the time slots of the day, a template has been created containing the settings of each of the main and dining lights and will send these on to the relevant light bulbs. 

When motion is triggered, the node-red flow decides which template to use and as an additional requirement, switches the lights off after a configurable delay once no motion has been detected. 

The flow is pictured below (click to download):



Download the flow!

No Motion:

The PIR will send an 'off' signal when it detects no motion, a switch on the back can be used to configure this and I've set it to 2 seconds. If Domoticz receives an 'off' signal, then an MQTT message is sent and all messages received on ‘domoticz/out’ are received by this flow. The messages are filtered by the IDX value of the switch in Domoticz and a filter detecting motion indicated by the payload.nvalue. When the nvalue is 1, the message is directed to a trigger node which will delay it for 5 minutes. After 5 minutes, the trigger node will emit the same message to a 'turn light off' template the result of which is sent to both the dining table and main kitchen light.

Motion:

The PIR will send an 'on' signal when it detects motion. If Domoticz receives an 'on' signal, then an MQTT message is sent and received by this flow filtered by the IDX value of the kitchen sensor in Domoticz and a filter detecting motion indicated by the payload.nvalue. When the nvalue is 0; this does 2 things.

1: The message is directed to the 'Reset Timer' template node which generates a new message with a 'reset' attribute set to true, this is passed into the trigger node cancelling any timeout in process. This is useful if someone leaves the kitchen, the timer will start a countdown to switching the lights off after 5 minutes, but then cancel that countdown if someone walks back in before the lights have switched off. 

2: The message is also directed to the 'Scene Chooser' which runs a function evaluating the current time and emitting a message on each of the applicable channels to template nodes which will generate some JSON to control the relavant dummy switches in Domoticz switching them off. The function has 5 outputs representing each scene we want:

00 - 06: Evening
06 - 09: Breakfast
09 - 12: Coloured
12 - 14: Lunch
14 - 17: Coloured
17 - 20: Dinner
20 - 22: Evening
22 - 00: Coloured

I've made the flow available to download from here:
https://dl.dropboxusercontent.com/u/174818/TimedKitchenLights.json

Resources: