256 lines
6.7 KiB
JavaScript
256 lines
6.7 KiB
JavaScript
"use strict";
|
|
|
|
var util = require("util")
|
|
, utils = require("./utils")
|
|
, errors = require("./errors")
|
|
;
|
|
|
|
var patterns = {
|
|
time: "\\d{2}:\\d{2}:\\d{2}",
|
|
weekday: "W[0-9]{1,3}",
|
|
date: "\\d{4}-\\d{2}-\\d{2}"
|
|
},
|
|
regularExpressions = {
|
|
absolute: new RegExp(util.format("%sT%s", patterns.date, patterns.time)),
|
|
randomized: new RegExp(util.format("%sT%sA%s", patterns.date, patterns.time, patterns.time)),
|
|
recurring: new RegExp(util.format("%s\/T%s", patterns.weekday, patterns.time)),
|
|
recurringRandomized: new RegExp(util.format("%s\/T%sA%s", patterns.weekday, patterns.time, patterns.time)),
|
|
timer: new RegExp(util.format("PT%s", patterns.time)),
|
|
timerRandom: new RegExp(util.format("PT%sA%s", patterns.time, patterns.time)),
|
|
timerRecurringCount: new RegExp(util.format("R\\d{2}\/PT%s", patterns.time)),
|
|
timerRecurring: new RegExp(util.format("R\/PT%s", patterns.time)),
|
|
timerRecurringCountRandom: new RegExp(util.format("R\\d{2}\/PT%sA%s", patterns.time, patterns.time))
|
|
};
|
|
|
|
var Schedule = function () {
|
|
};
|
|
|
|
module.exports.create = function () {
|
|
var schedule,
|
|
arg;
|
|
|
|
if (arguments.length == 0) {
|
|
schedule = new Schedule();
|
|
} else {
|
|
arg = arguments[0];
|
|
if (arg instanceof Schedule) {
|
|
schedule = arg;
|
|
} else {
|
|
schedule = new Schedule();
|
|
|
|
// try to populate the new schedule using any values that match schedule properties
|
|
if (arg.name) {
|
|
schedule.withName(arg.name);
|
|
}
|
|
|
|
if (arg.description) {
|
|
schedule.withDescription(arg.description);
|
|
}
|
|
|
|
if (arg.time || arg.localtime) {
|
|
schedule.at(arg.time || arg.localtime);
|
|
}
|
|
|
|
if (arg.command) {
|
|
schedule.withCommand(arg.command);
|
|
}
|
|
|
|
if (arg.status) {
|
|
schedule.withEnabledState(arg.status);
|
|
}
|
|
}
|
|
}
|
|
|
|
return schedule;
|
|
};
|
|
|
|
Schedule.prototype.at = function (time) {
|
|
utils.combine(this, _getTimeValue(time));
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.on = function (time) {
|
|
utils.combine(this, _getTimeValue(time));
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.when = function (time) {
|
|
utils.combine(this, _getTimeValue(time));
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.atRandomizedTime = function(time) {
|
|
if (regularExpressions.randomized.test(time)) {
|
|
utils.combine(this, {localtime: time});
|
|
} else {
|
|
throw new errors.ApiError(util.format("Time '%s' is not correct for randomized time", time));
|
|
}
|
|
};
|
|
|
|
Schedule.prototype.atRecurringTime = function (time) {
|
|
if (regularExpressions.recurring.test(time)) {
|
|
utils.combine(this, {localtime: time});
|
|
} else {
|
|
throw new errors.ApiError(util.format("Time '%s' is not correct for recurring time", time));
|
|
}
|
|
};
|
|
|
|
Schedule.prototype.atRecurringRandomizedTime = function(time) {
|
|
if (regularExpressions.recurringRandomized.test(time)) {
|
|
utils.combine(this, {localtime: time});
|
|
} else {
|
|
throw new errors.ApiError(util.format("Time '%s' is not correct for recurring randomized time", time));
|
|
}
|
|
};
|
|
|
|
Schedule.prototype.withName = function (name) {
|
|
// The 1.0 API only accepts up to 32 characters for the name
|
|
var nameCharMax = 32;
|
|
|
|
utils.combine(this, {"name": utils.getStringValue(name, nameCharMax)});
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.withDescription = function (description) {
|
|
// The 1.0 API only accepts up to 64 characters for the description
|
|
utils.combine(this, {"description": utils.getStringValue(description, 64)});
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.withCommand = function (command) {
|
|
var type = typeof(command),
|
|
commandObject = null;
|
|
|
|
// The command is limited to 90 characters, so if a string is passed, convert it to an object and back into JSON.
|
|
|
|
if (type === "string") {
|
|
commandObject = JSON.parse(command);
|
|
} else {
|
|
commandObject = command;
|
|
}
|
|
|
|
_validateCommand(commandObject);
|
|
|
|
utils.combine(this, {"command": commandObject});
|
|
return this;
|
|
};
|
|
|
|
Schedule.prototype.withEnabledState = function (enabled) {
|
|
var state;
|
|
|
|
if (enabled === "enabled") {
|
|
state = "enabled";
|
|
} else if (enabled === "disabled") {
|
|
state = "disabled";
|
|
} else {
|
|
state = enabled ? "enabled" : "disabled";
|
|
}
|
|
|
|
utils.combine(this, {status: state});
|
|
};
|
|
|
|
function _getTimeValue(time) {
|
|
var result = {}
|
|
, type = typeof time
|
|
, timeValue = null
|
|
;
|
|
|
|
if (type === 'string') {
|
|
// Check the string against all known patterns
|
|
Object.keys(regularExpressions).forEach(function (regex) {
|
|
if (!timeValue && regularExpressions[regex].test(time)) {
|
|
timeValue = time;
|
|
}
|
|
});
|
|
|
|
if (!timeValue) {
|
|
// We don't have a match, but it may still be a valid time, so attempt to parse it
|
|
timeValue = _convertToDate(time);
|
|
}
|
|
} else if (type === 'number') {
|
|
timeValue = _convertNumberToHueTime(time);
|
|
} else if (type === 'object') {
|
|
if (time instanceof Date) {
|
|
timeValue = _convertNumberToHueTime(time.getTime())
|
|
}
|
|
}
|
|
|
|
if (timeValue === null) {
|
|
throw new errors.ApiError("Invalid time value, '" + time + "'");
|
|
}
|
|
|
|
result.localtime = timeValue;
|
|
return result;
|
|
}
|
|
|
|
function _convertNumberToHueTime(number) {
|
|
var result = null;
|
|
|
|
if (!isNaN(number)) {
|
|
result = _convertDateToHueTime(new Date(number));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function _convertDateToHueTime(date) {
|
|
var result = null
|
|
, str
|
|
;
|
|
|
|
if (date) {
|
|
str = date.toJSON();
|
|
result = str.substring(0, str.lastIndexOf("."))
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function _convertToDate(str) {
|
|
var result = null
|
|
, time = Date.parse(str)
|
|
;
|
|
|
|
if (!isNaN(time)) {
|
|
result = _convertNumberToHueTime(time);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Perform validation on a command object to verify it can be considered valid.
|
|
* @param commandObject the object representing the command to be validated.
|
|
* @throws {ApiError} if a problem is encountered with the command
|
|
* @private
|
|
*/
|
|
function _validateCommand(commandObject) {
|
|
var address,
|
|
method,
|
|
body;
|
|
|
|
if (commandObject) {
|
|
address = commandObject.address;
|
|
if (address) {
|
|
//TODO expand the regex to match proper end points valid for schedules
|
|
var addressPattern = /^\/api\/\.*\/\.*/;
|
|
if (addressPattern.test(address)) {
|
|
throw new errors.ApiError("The 'address' property must begin with '/api' to be a valid endpoint");
|
|
}
|
|
} else {
|
|
throw new errors.ApiError("The 'address' property must be specified.");
|
|
}
|
|
|
|
//TODO link this with the valid endpoints in the address
|
|
method = commandObject.method;
|
|
if (!commandObject.method) {
|
|
throw new errors.ApiError("The 'method' must be specified.");
|
|
}
|
|
|
|
body = commandObject.body;
|
|
if (!commandObject.body) {
|
|
throw new errors.ApiError("The 'body' property must be specified.");
|
|
}
|
|
} else {
|
|
throw new errors.ApiError("Command is not defined");
|
|
}
|
|
} |