Skip to content

Commit

Permalink
feat(time): Add time node
Browse files Browse the repository at this point in the history
  • Loading branch information
zachowj committed Dec 31, 2020
1 parent 14878c4 commit 74d4415
Show file tree
Hide file tree
Showing 15 changed files with 748 additions and 18 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
haServer: 'readonly',
ifState: 'readonly',
nodeVersion: 'readonly',
ha: 'readonly',
},
plugins: ['sort-requires'],
};
68 changes: 68 additions & 0 deletions docs/node/time.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Time

A node that can be scheduled to trigger at a future date and time from a Home Assistant entity.

## Configuration

### Entity Id

- Type: `string`

A Home Assistant entity to be used when scheduling the node.

### Property

- Type: `string`

Which property of the entity to use to schedule the node.

The node will accept any date string that the javascript object accepts as a valid date. It will also accept a 24-hour time format with the seconds place optional.

examples:

- <code>2020-12-31T02:47:54.837Z</code>
- <code>1609382842709</code>
- <code>13:40</code>
- <code>23:59:02</code>

### Offset

- Type: `number`

A negative or positive number that will be added to the scheduled time.

### Randomize time within the offset

- Type: `boolean`

When selected the time to trigger will be random selected from the scheduled time to the +/- offset.

### Payload

- Type: `string | number | boolean | object`

The payload is fully customizable. The default will be a JSONata expression that outputs the entity state.

### Repeat Daily

- Type: `boolean`

If selected the node will only use the time portion of the date string to schedule the node and will trigger at that time each day. Otherwise, the node will only trigger once at the given day and time.

## Outputs

### topic

- Type: `string`

The entity id in the configuration.

### payload

- Type: `string | number | boolean | object`

### data

- Type: `object`

The entity object of the entity in the configuration.
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const nodeMap = {
'get-history': { doc: 'get-history', type: 'api-get-history' },
'poll-state': { doc: 'poll-state', type: 'poll-state' },
'render-template': { doc: 'get-template', type: 'api-render-template' },
time: { doc: 'time', type: 'ha-time' },
'trigger-state': { doc: 'trigger-state', type: 'trigger-state' },
'wait-until': { doc: 'wait-until', type: 'ha-wait-until' },
webhook: { doc: 'webhook', type: 'ha-webhook' },
Expand Down
18 changes: 11 additions & 7 deletions lib/base-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,23 +538,27 @@ const _internals = {
};

const _eventHandlers = {
preOnInput(message) {
preOnInput(message, send, done) {
try {
const parsedMessage = _internals.parseInputMessage.call(
this,
this.options.input,
message
);

this.onInput({
parsedMessage,
message,
});
this.onInput(
{
parsedMessage,
message,
},
send,
done
);
} catch (e) {
if (e && e.isJoi) {
this.node.warn(e.message);
this.node.setStatusFailed('Error');
return this.send(null);
done(e.message);
return;
}
throw e;
}
Expand Down
20 changes: 19 additions & 1 deletion lib/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,27 @@ module.exports = Object.freeze({
HA_EVENT_STATE_CHANGED: 'state_changed',
HA_EVENTS: 'ha_events',
INTEGRATION_EVENT: 'integration',
INTEGRATION_NOT_LOADED: 'notloaded',
INTEGRATION_LOADED: 'loaded',
INTEGRATION_NOT_LOADED: 'notloaded',
INTEGRATION_UNLOADED: 'unloaded',
STATUS_COLOR_BLUE: 'blue',
STATUS_COLOR_GREEN: 'green',
STATUS_COLOR_GREY: 'grey',
STATUS_COLOR_RED: 'red',
STATUS_COLOR_YELLOW: 'yellow',
STATUS_SHAPE_DOT: 'dot',
STATUS_SHAPE_RING: 'ring',
TYPEDINPUT_MSG: 'msg',
TYPEDINPUT_FLOW: 'flow',
TYPEDINPUT_GLOBAL: 'global',
TYPEDINPUT_DATE: 'date',
TYPEDINPUT_BOOL: 'bool',
TYPEDINPUT_ENV: 'env',
TYPEDINPUT_JSON: 'json',
TYPEDINPUT_JSONATA: 'jsonata',
TYPEDINPUT_NONE: 'none',
TYPEDINPUT_NUM: 'num',
TYPEDINPUT_STR: 'str',
ZONE_ENTER: 'enter',
ZONE_ENTER_OR_LEAVE: 'enter_leave',
ZONE_LEAVE: 'leave',
Expand Down
6 changes: 4 additions & 2 deletions lib/events-ha-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class EventsHaNode extends EventsNode {
}
}

async registerEntity() {
async registerEntity(status = true) {
if (super.registerEntity() === false) {
return;
}
Expand Down Expand Up @@ -125,7 +125,9 @@ class EventsHaNode extends EventsNode {
{ resubscribe: false }
);

this.setStatusSuccess('Registered');
if (status) {
this.setStatusSuccess('Registered');
}
this.registered = true;
}

Expand Down
15 changes: 15 additions & 0 deletions lib/ui/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// eslint-disable-next-line no-unused-vars, no-var
var ha = (function () {
const nodeColors = {
action: '#46B1EF',
alpha: '#E78BB9',
api: '#7CDFFD',
beta: '#77DD77',
data: '#5BCBF7',
event: '#399CDF',
};

return {
nodeColors,
};
})();
27 changes: 27 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,30 @@ const timeoutStatus = (milliseconds = 0) => {

return timeoutStr;
};

utils.isValidDate = (val) => {
const d = new Date(val);
return d instanceof Date && !isNaN(d);
};

utils.parseTime = (time) => {
const regex = /^(0?\d|1\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?$/;
const matches = time.match(regex);

if (!matches) return matches;

const [, hour, minutes, seconds = 0] = matches;

return {
hour: Number(hour),
minutes: Number(minutes),
seconds: Number(seconds),
};
};

utils.getEntitiesFromJsonata = (jsonata) => {
const regex = /\$entities\("([a-z_]+\.[a-z0-9_]+)"\)/g;
const matches = jsonata.matchAll(regex);

return new Set(Array.from(matches, (m) => m[1]));
};
32 changes: 32 additions & 0 deletions nodes/time/locales/en-US/time.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"ha-time": {
"errors": {
"invalid_jsonata_payload": "Invalid jsonata sending entity state as payload",
"jsonata_error": "JSONata Error: __message__",
"offset_nan": "Offset is not a number: __offset__"
},
"status": {
"in_the_past": "In the past",
"invalid_date": "Invalid date",
"invalid_property": "Invalid property",
"next_at": "Next at __nextTime__",
"sent": "Sent",
"sent_and_next": "Sent at __sentTime__ Next at __nextTime__",
"unavailable": "Unavailable",
"error": "Error"
},
"label": {
"name": "Name",
"server": "Server",
"entity_id": "Entity Id",
"property": "Property",
"offset": "Offset",
"seconds": "seconds",
"minutes": "minutes",
"hours": "hours",
"randomize_offset": "Randomize time within the offset",
"payload": "Payload",
"repeat_daily": "Repeat Daily"
}
}
}

0 comments on commit 74d4415

Please sign in to comment.