This is very much a work in process. Not everything is complete or stable. The HASS support provided by hass-scripts is not nearly as clean or as complete as the MQTT support provided by mqtt-scripts and included in this package.
Many of the mqtt methods work with HASS as well, however, these are still being tested and corrected.
Below you will find the README for mqtt-scripts. hass-scripts is largely unchanged, however, includes support for Home Assistant. Home Assistant can be used in a script in the following way:
hass.on('state:input_boolean.test1', (state) => {
var service;
if(state.new_state.state == 'off') {
service = 'turn_off';
} else {
service = 'turn_on';
}
hass.call({
domain: 'input_boolean',
service: service,
service_data: {
entity_id: 'input_boolean.test2',
},
});
});
Recommended Setup is to make a config file (copy sample-myconfig.js as a starting point) that looks like the following:
const config = {
url: 'mqtt://127.0.0.1',
latitude: 48.7408,
longitude: 9.1778,
name: 'logic',
'variable-prefix': 'var',
verbosity: 'info',
'disable-variables': false,
'disable-watch': false,
hass: {
host: '127.0.0.1',
protocol: 'ws', // "ws" (default) or "wss" for SSL
retryTimeout: 5000, // in ms, default is 5000
retryCount: -1, // default is 10, values < 0 mean unlimited
token: 'YOUR_LONG_LIVED_TOKEN_HERE',
port: 8123
}
};
module.exports = config;
Then, run hass-scripts like this:
./index.js -c ./myconfig.js -d ./scripts/
BELOW IS THE README for mqtt-scripts. This has not been edited.
mqtt-scripts is a Node.js based script runner for use in mqtt based smart home environments.
It's intentended to be used as the "logic layer" in your smart home, and offers a zero-boilerplate, straight forward scripting environment.
It follows the mqtt-smarthome architecture. Mqtt-scripts could be seen as something like "Node-RED without GUI"
Prerequisites: mqtt-scripts needs Node.js >= 6.0.
- Install mqtt-scripts globally:
sudo npm install -g mqtt-scripts
- Create a folder from where mqtt-scripts will load the scripts:
mkdir -p /opt/mqtt-smarthome/scripts
- Create a folder to install node modules that can be used in the scripts:
mkdir /opt/mqtt-smarthome/scripts/node_modules
(You can then just use npm install in the directory /opt/mqtt-smarthome/scripts)
- Put some files in you script dir:
echo "log.info('my first script!')" > /opt/mqtt-smarthome/scripts/test1.js
echo "log.info 'get ma a coffee' > /opt/mqtt-smarthome/scripts/test1.coffee
- Start mqtt-scripts
mqtt-scripts -d /opt/mqtt-smarthome/scripts
To run with Docker, use either a pre-build image or build one your own. Either way, just substitude the node-command you would have used by the Docker command, for e.g.:
mqtt-scripts --help
becomes
docker run dersimn/mqtt-scripts --help
An example for a productive configuration would be:
docker run -d --restart=always --name=logic \
-e "TZ=Europe/Berlin" \
-v /opt/hma/etc/scripts:/scripts:ro \
dersimn/mqtt-scripts \
--url mqtt://10.1.1.50 \
--dir /scripts
Configure via MQTTSCRIPTS_
env variables when using Docker Compose.
To build a Docker image yourself use the following workflow:
git clone https://github.com/hobbyquaker/mqtt-scripts.git
cd mqtt-scripts
docker build -t mqtt-scripts .
To build for the Raspberry Pi, run:
docker build -t mqtt-scripts:armhf -f Dockerfile.armhf .
Usage: mqtt-scripts [options] Options: --version Show version number [boolean] -c, --config Path to JSON config file -d, --dir directory to scan for .js and .coffee files. can be used multiple times. -h, --help Show help [boolean] -s, --variable-prefix topic prefix for $ substitution (shorthand for variables, see docs) [default: "var"] -t, --disable-variables disable variable feedback (see docs) [default: false] -n, --name instance name. used as mqtt client id and as prefix for connected topic [default: "logic"] -u, --url mqtt broker url. See https://github.com/mqttjs/MQTT.js#connect-using-a-url [default: "mqtt://127.0.0.1"] -v, --verbosity possible values: "error", "warn", "info", "debug" [default: "info"] -w, --disable-watch disable file watching (don't exit process on file changes) [default: false] -l, --latitude [default: 48.7408] -m, --longitude [default: 9.1778]
If you're running multiple instances of mqtt-scripts you have to decide which one should handle variables and disable the variables on all other instances with the --disable-variable option.
link('hm//RC4:1/PRESS_CONT', 'hue//lights/Hobbyraum/bri_inc', -16);
subscribe('hm//RC4:2/PRESS_CONT', function () {
if (!getValue('hue//lights/Hobbyraum')) {
setValue('hue//lights/Hobbyraum', 1);
} else {
setValue('hue//lights/Hobbyraum/bri_inc', 16);
}
});
link('hm//RC4:1/PRESS_SHORT', 'hue//lights/Hobbyraum', 0);
link('hm//RC4:2/PRESS_SHORT', 'hue//lights/Hobbyraum', 254);
link('hm//RC4:3/PRESS_CONT', 'hue//lights/Hobbyraum/ct_inc', -16);
link('hm//RC4:4/PRESS_CONT', 'hue//lights/Hobbyraum/ct_inc', 16);
link('hm//RC4:3/PRESS_SHORT', 'hue//lights/Hobbyraum/ct', 153);
link('hm//RC4:4/PRESS_SHORT', 'hue//lights/Hobbyraum/ct', 500);
var request = require('request');
var cred = require('./lib/credentials.js');
var url = 'https://creativecommons.tankerkoenig.de/json/detail.php';
var tankstellen = {
'OMV': 'cb1f0588-d517-40f0-8ce3-3edadebea40d',
'Shell': '4267c196-eea1-47be-96b7-d790b2fbd17a'
};
schedule('0/12 * * * *', function () {
for (var topic in tankstellen) {
getData(topic, tankstellen[topic]);
}
});
function getData(topic, id) {
request.get(url + '?id=' + id + '&apikey=' + cred.tankerkoenig.apikey, function (err, res) {
if (err) {
log.error(err);
return;
}
var data = JSON.parse(res.body).station;
setValue('$Tankstelle/' + topic + '/Diesel', data.diesel);
setValue('$Tankstelle/' + topic + '/E5', data.e5);
setValue('$Tankstelle/' + topic + '/Offen', data.isOpen);
});
}
var cred = require('./lib/credentials.js');
var pushoverNotifications = require('pushover-notifications');
var push = new pushoverNotifications( {
user: cred.pushover.user,
token: cred.pushover.token,
onerror: function (error) {
log.error(error);
}
});
function pushover(msg) {
if (typeof msg !== 'object' || typeof msg.message !== 'string') msg = {message: '' + msg};
msg.title = msg.title || "Smart Home";
msg.priority = msg.priority || 0;
msg.device = msg.device || 'iphone5';
push.send(msg, function(err, result) {
if (err) {
log.error(err);
}
});
}
subscribe('$Anwesenheit', {change: true}, function () {
pushover({
title:'Anwesenheit',
message: getProp($Anwesenheit, 'logic_textual'),
priority: -1
});
});
- log
Log to stdout/stderr. Messages are prefixed with a timestamp and the calling scripts path.
- subscribe(topic, [options], callback)
Subscribe to MQTT topic(s)
- schedule(pattern, [options], callback)
Schedule recurring and one-shot events
- sunSchedule(pattern, [options], callback)
Schedule a recurring event based on sun position
- publish(topic, payload, [options])
Publish a MQTT message
- setValue(topic, val)
Set a value on one or more topics
- getValue(topic) ⇒
mixed
- getProp(topic, [...property]) ⇒
mixed
Get a specific property of a topic
- now() ⇒
number
- age(topic) ⇒
number
- link(source, target, [value])
Link topic(s) to other topic(s)
- combineBool(srcs, targets)
Combine topics through boolean or
- combineMax(srcs, targets)
Publish maximum of combined topics
- timer(src, target, time)
Publishes 1 on target for specific time after src changed to true
- subscribeCallback :
function
Log to stdout/stderr. Messages are prefixed with a timestamp and the calling scripts path.
Kind: global class
Log a debug message
Kind: static method of log
Type |
---|
* |
Log an info message
Kind: static method of log
Type |
---|
* |
Log a warning message
Kind: static method of log
Type |
---|
* |
Log an error message
Kind: static method of log
Type |
---|
* |
Subscribe to MQTT topic(s)
Kind: global function
Param | Type | Description |
---|---|---|
topic | string | Array.<string> |
topic or array of topics to subscribe |
[options] | Object | string | function |
Options object or as shorthand to options.condition a function or string |
[options.shift] | number |
delay execution in seconds. Has to be positive |
[options.random] | number |
random delay execution in seconds. Has to be positive |
[options.change] | boolean |
if set to true callback is only called if val changed |
[options.retain] | boolean |
if set to true callback is also called on retained messages |
[options.condition] | string | function |
conditional function or condition string |
callback | subscribeCallback |
Schedule recurring and one-shot events
Kind: global function
See: sunSchedule for scheduling based on sun position.
Param | Type | Description |
---|---|---|
pattern | string | Date | Object | Array.<mixed> |
pattern or array of patterns. May be cron style string, Date object or node-schedule object literal. See https://github.com/tejasmanohar/node-schedule/wiki |
[options] | Object |
|
[options.random] | number |
random delay execution in seconds. Has to be positive |
callback | function |
is called with no arguments |
Example
// every full Hour.
schedule('0 * * * *', callback);
// Monday till friday, random between 7:30am an 8:00am
schedule('30 7 * * 1-5', {random: 30 * 60}, callback);
// once on 21. December 2018 at 5:30am
schedule(new Date(2018, 12, 21, 5, 30, 0), callback);
// every Sunday at 2:30pm
schedule({hour: 14, minute: 30, dayOfWeek: 0}, callback);
Schedule a recurring event based on sun position
Kind: global function
See: schedule for time based scheduling.
Param | Type | Description |
---|---|---|
pattern | string | Array.<string> |
a suncalc event or an array of suncalc events. See https://github.com/mourner/suncalc |
[options] | Object |
|
[options.shift] | number |
delay execution in seconds. Allowed Range: -86400...86400 (+/- 24h) |
[options.random] | number |
random delay execution in seconds. |
callback | function |
is called with no arguments |
Example
// Call callback 15 minutes before sunrise
sunSchedule('sunrise', {shift: -900}, callback);
// Call callback random 0-15 minutes after sunset
sunSchedule('sunset', {random: 900}, callback);
Publish a MQTT message
Kind: global function
Param | Type | Default | Description |
---|---|---|---|
topic | string | Array.<string> |
topic or array of topics to publish to | |
payload | string | Object |
the payload string. If an object is given it will be JSON.stringified | |
[options] | Object |
the options to publish with | |
[options.qos] | number |
0 |
QoS Level |
[options.retain] | boolean |
false |
retain flag |
Set a value on one or more topics
Kind: global function
Param | Type | Description |
---|---|---|
topic | string | Array.<string> |
topic or array of topics to set value on |
val | mixed |
Kind: global function
Returns: mixed
- the topics value
Param | Type |
---|---|
topic | string |
Get a specific property of a topic
Kind: global function
Returns: mixed
- the topics properties value
Param | Type | Description |
---|---|---|
topic | string |
|
[...property] | string |
the property to retrieve. May be repeated for nested properties. If omitted the whole topic object is returned. |
Example
// returns the timestamp of a given topic
getProp('hm//Bewegungsmelder Keller/MOTION', 'ts');
Kind: global function
Returns: number
- ms since epoch
Kind: global function
Returns: number
- seconds since last change
Param | Type |
---|---|
topic | string |
Link topic(s) to other topic(s)
Kind: global function
Param | Type | Description |
---|---|---|
source | string | Array.<string> |
topic or array of topics to subscribe |
target | string | Array.<string> |
topic or array of topics to publish |
[value] | mixed |
value to publish. If omitted the sources value is published. A function can be used to transform the value. |
Combine topics through boolean or
Kind: global function
Param | Type | Description |
---|---|---|
srcs | Array.<string> |
array of topics to subscribe |
targets | string |
topic to publish |
Publish maximum of combined topics
Kind: global function
Param | Type | Description |
---|---|---|
srcs | Array.<string> |
array of topics to subscribe |
targets | string |
topic to publish |
Publishes 1 on target for specific time after src changed to true
Kind: global function
Param | Type | Description |
---|---|---|
src | string | Array.<string> |
topic or array of topics to subscribe |
target | string |
topic to publish |
time | number |
timeout in milliseconds |
Kind: global typedef
Param | Type | Description |
---|---|---|
topic | string |
the topic that triggered this callback. +/status/# will be replaced by +//# |
val | mixed |
the val property of the new state |
obj | object |
new state - the whole state object (e.g. {"val": true, "ts": 12346345, "lc": 12346345} ) |
objPrev | object |
previous state - the whole state object |
msg | object |
the mqtt message as received from MQTT.js |
MIT © Sebastian Raff