node-red-contrib-sun-position
Advanced tools
Comparing version 2.1.1 to 2.2.0-beta
@@ -0,0 +0,0 @@ --- |
@@ -17,2 +17,26 @@ # node-red-contrib-sun-position | ||
This can be also used to go back to an older Version. | ||
### 2.2.0-beta: enhancement | ||
- general | ||
- first implementation of tests with `mocha` and some changes due to the test implementation (inject enhance and delay-until) | ||
- revised error handling and output messages if the configuration of nodes is not correct (missing config node, missing latitude/longitude). | ||
- added type checking | ||
- inject enhance (time-inject) | ||
- added repletely inject with CRON expression | ||
- added automatic test case | ||
- basic inject | ||
- time based inject | ||
- within-time-switch | ||
- changed state output in case time span is over midnight, because the shown times could be not correct #416 | ||
- added automatic test case | ||
- basic test for configuration | ||
- test for message passing is for later | ||
- new Node `delay-until` which allows to delay messages until defined time | ||
- blind-control | ||
- fix #421 | ||
### 2.1.1: bug fixes | ||
@@ -27,3 +51,3 @@ | ||
- fix bug of handling not time constrained rules be first to last evaluated | ||
### 2.0.13: bug fixes | ||
@@ -30,0 +54,0 @@ |
@@ -0,0 +0,0 @@ [ |
@@ -0,0 +0,0 @@ [ |
@@ -0,0 +0,0 @@ [ |
@@ -0,0 +0,0 @@ [ |
@@ -0,0 +0,0 @@ [ |
@@ -0,1 +1,2 @@ | ||
// @ts-check | ||
/* | ||
@@ -27,8 +28,200 @@ * This code is licensed under the Apache License Version 2.0. | ||
'use strict'; | ||
const path = require('path'); | ||
/** --- Type Defs --- | ||
* @typedef {import('../types/typedefs.js').runtimeRED} runtimeRED | ||
* @typedef {import('../types/typedefs.js').runtimeNode} runtimeNode | ||
* @typedef {import('../types/typedefs.js').runtimeNodeConfig} runtimeNodeConfig | ||
* @typedef {import("./dateTimeHelper.js").ITimeObject} ITimeObject | ||
* @typedef {import("./dateTimeHelper.js").ILimitationsObj} ILimitationsObj | ||
* @typedef {import("../10-position-config.js").IPositionConfigNode} IPositionConfigNode | ||
* @typedef {import("../10-position-config.js").ITimePropertyResult} ITimePropertyResult | ||
*/ | ||
/** | ||
* @typedef {Object} IAutoTrigger object for sore autotrigger data | ||
* @property {number} defaultTime - default next autotriggering time | ||
* @property {(0|1|2|3|4|5|6|7|8|9)} type - type of next autotriggering | ||
* @property {number} time - next autotrigger in milliseconds | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleCondition object for a rule condition | ||
* | ||
* @property {number} condition - position of the condition | ||
* @property {string} [conditionText] - description of the condition | ||
* @property {string|number} value - first operand | ||
* @property {string} valueType - first operand type | ||
* @property {function} [valueExpr] - JSONATA expression | ||
* @property {string} [valueName] - first operand description | ||
* @property {string} [valueNameShort] - first operand description (short version) | ||
* @property {string} [valueWorth] - opCallback value | ||
* @property {string} operator - operator | ||
* @property {string} [operatorText] - operator description | ||
* @property {string} [operatorDescription] - operator description enhanced | ||
* @property {string} threshold - second operand | ||
* @property {string} thresholdType - second operand type | ||
* @property {function} [thresholdExpr] - JSONATA expression | ||
* @property {string} [thresholdName] - second operand description | ||
* @property {string} [thresholdNameShort] - second operand description (short version) | ||
* @property {string} [thresholdWorth] - opCallback value | ||
* @property {string} [text] - comparision text | ||
* @property {string} [textShort] - comparision text (short version) | ||
* @property {boolean} result - result of the condition evaluation | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleConditionResult object for a rule condition | ||
* | ||
* @property {number} index - selected condition index | ||
* @property {string} [text] - comparision text | ||
* @property {string} [textShort] - comparision text (short version) | ||
* @property {boolean} result - result of the condition evaluation | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleTimeDefSingle object for a rule time definition | ||
* | ||
* @property {string} value - time value | ||
* @property {string} type - type of the time | ||
* @property {string|number} offset - time offset value | ||
* @property {string} offsetType - time offset type | ||
* @property {number} multiplier - time offset value | ||
* @property {boolean} next - time offset value | ||
* @property {Date} [now] - start time definition | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleTimeDef object for a rule time definition | ||
* | ||
* @property {string} value - time value | ||
* @property {string} type - type of the time | ||
* @property {string|number} offset - time offset value | ||
* @property {string} offsetType - time offset type | ||
* @property {number} multiplier - time offset value | ||
* @property {boolean} next - time offset value | ||
* @property {Date} [now] - start time definition | ||
* | ||
* @property {(0|1)} [operator] - time operator | ||
* @property {(0|1)} [operatorText] - time operator text | ||
* | ||
* @property {IRuleTimeDefSingle} [min] - minimum limitation to the time | ||
* @property {IRuleTimeDefSingle} [max] - maximum limitation to the time | ||
*/ | ||
/** | ||
* @typedef {ILimitationsObj & IRuleTimeDef} IRuleTimesDef object for a rule time definition | ||
*/ | ||
/** | ||
* @typedef {Object} ITimePropertyResultInt object for a rule time definition | ||
* | ||
* @property {number} ts - time in milliseconds | ||
* @property {number} dayId - day id of the date | ||
* @property {string} [timeLocal] - time representation | ||
* @property {string} [timeLocalDate] - time representation | ||
* @property {string} [dateISO] - time representation | ||
* @property {string} [dateUTC] - time representation | ||
* @property {('default'|'min'|'max')} [source] - source of the data if it comes from minimum or maximum limitation | ||
* @property {number} [now] - start time definition | ||
*/ | ||
/** | ||
* @typedef {ITimePropertyResultInt & ITimePropertyResult} ITimePropResult object for a rule time definition | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleData object for a rule | ||
* @property {boolean} enabled - defines if a rle is enabled or disabled | ||
* @property {number} pos - rule position | ||
* @property {string} name - name of the rule | ||
* @property {number} exec - executuion type of a rule which is defined | ||
* @property {number} execUse - executuion type of a rule which is used | ||
* @property {boolean} resetOverwrite - overwrites reset | ||
* @property {number} importance - importance of the rule | ||
* @property {boolean} conditional - defines if the rule has conditions | ||
* @property {Array.<IRuleCondition>} conditions - conditions for a rule | ||
* @property {IRuleConditionResult} conditon - condition resule | ||
* @property {IRuleTimesDef} [time] - rule time Data | ||
* @property {IRuleTimesDef} [timeMin] - rule time Data | ||
* @property {IRuleTimesDef} [timeMax] - rule time Data | ||
* @property {ITimePropResult} [timeData] - object for storing time Data | ||
* @property {ITimePropResult} [timeDataMin] - object for storing time Data | ||
* @property {ITimePropResult} [timeDataMax] - object for storing time Data | ||
* @property {Object} [payload] - rule time Data | ||
* @property {Object} [level] - rule time Data | ||
* @property {Object} [slat] - rule time Data | ||
* @property {string} topic - rule time Data | ||
* @property {Object} [outputValue] - rule time Data | ||
* @property {string} [outputType] - rule time Data | ||
*/ | ||
/** | ||
* @typedef {Object} IRuleResultData object for a rule result | ||
* @property {number} ruleindex - index of selected rule | ||
* @property {IRuleData} [ruleSel] - selected rule | ||
* @property {IRuleData} [ruleSlatOvs] - selected rule | ||
* @property {IRuleData} [ruleTopicOvs] - selected rule | ||
* @property {IRuleData} [ruleSelMin] - selected rule | ||
* @property {IRuleData} [ruleSelMax] - selected rule | ||
* @property {IRuleTimesDef} [timeResult] - object for storing time Data | ||
* @property {IRuleTimesDef} [timeResultMin] - object for storing time Data | ||
* @property {IRuleTimesDef} [timeResultMax] - object for storing time Data | ||
*/ | ||
/** | ||
* @typedef {Object} IRulesData object for a rule | ||
* @property {Array.<IRuleData>} data - the rules itself | ||
* @property {number} count - executuion type of a rule which is defined | ||
* @property {number} lastUntil - last rule for first evaluation loop | ||
* @property {number} firstFrom - first from rule | ||
* @property {number} firstTimeLimited - first from rule with time limitation | ||
* @property {number} maxImportance - maximum inportance of all rules | ||
* @property {boolean} canResetOverwrite - __true__ if any rule can overwrite reset | ||
*/ | ||
/** | ||
* @typedef {Object} ISunData object for a rule | ||
* @property {(0|1|3|16)} mode - mode of the sun | ||
* @property {(0|1|3|16)} modeMax - maximum mode | ||
* @property {string} floorLength - floorLength value | ||
* @property {string} floorLengthType - type of the floorLength | ||
* @property {number} changeAgain - timestamp of the next change | ||
* @property {number} minDelta - minimum delta | ||
* @property {Object} [level] - rule time Data | ||
* @property {Object} [slat] - rule time Data | ||
* @property {string} topic - rule time Data | ||
*/ | ||
/** | ||
* @typedef {Object} ITimeControlNodeInstance Extensions for the nodeInstance object type | ||
* @property {IPositionConfigNode} positionConfig - tbd | ||
* @property {string} addId internal used additional id | ||
* @property {Object} nodeData get/set generic Data of the node | ||
* @property {Object} reason - tbd | ||
* @property {string} contextStore - used context store | ||
* @property {IRulesData} rules - definition of the rule Data | ||
* | ||
* @property {boolean} [levelReverse] - indicator if the Level is in reverse order | ||
* @property {ISunData} [sunData] - the sun data Object | ||
* @property {Object} nowarn - tbd | ||
* | ||
* @property {Array.<Object>} results - tbd | ||
* | ||
* @property {IAutoTrigger} autoTrigger autotrigger options | ||
* @property {NodeJS.Timeout} [autoTriggerObj] - autotrigger TimeOut Object | ||
* | ||
* @property {Object} startDelayTimeOut - tbd | ||
* @property {NodeJS.Timeout} startDelayTimeOutObj - tbd | ||
* @property {NodeJS.Timeout} timeOutObj - Overwrite Reset TimeOut Object | ||
* ... obviously there are more ... | ||
*/ | ||
/** | ||
* @typedef {ITimeControlNodeInstance & runtimeNode} ITimeControlNode Combine nodeInstance with additional, optional functions | ||
*/ | ||
const util = require('util'); | ||
const hlp = require( path.resolve( __dirname, './dateTimeHelper.js') ); | ||
const hlp = require( './dateTimeHelper.js' ); | ||
module.exports = { | ||
isNullOrUndefined, | ||
evalTempData, | ||
@@ -55,9 +248,28 @@ posOverwriteReset, | ||
let RED = null; | ||
/******************************************************************************************/ | ||
/** | ||
* Timestamp compare function | ||
* @callback ICompareTimeStamp | ||
* @param {number} timeStamp The timestamp which should be compared | ||
* @returns {Boolean} return true if if the timestamp is valid, otherwise false | ||
*/ | ||
/******************************************************************************************/ | ||
/** | ||
* Returns true if the given object is null or undefined. Otherwise, returns false. | ||
* @param {*} object object to check | ||
* @returns {boolean} true if the given object is null or undefined. Otherwise, returns false. | ||
*/ | ||
function isNullOrUndefined(object) { | ||
return (object === null || typeof object === 'undefined'); // isNullOrUndefined(object) | ||
} | ||
/** | ||
* evaluate temporary Data | ||
* @param {*} node node Data | ||
* @param {ITimeControlNode} node node Data | ||
* @param {string} type type of type input | ||
* @param {string} value value of typeinput | ||
* @param {*} data data to cache | ||
* @param {Object} tempData object which holding the chached data | ||
* @returns {*} data which was cached | ||
@@ -68,3 +280,3 @@ */ | ||
const name = `${type}.${value}`; | ||
if (data === null || typeof data === 'undefined') { | ||
if (isNullOrUndefined(data)) { | ||
if (typeof tempData[name] !== 'undefined') { | ||
@@ -89,3 +301,3 @@ if (type !== 'PlT') { | ||
* clears expire object properties | ||
* @param {*} node node data | ||
* @param {ITimeControlNode} node node data | ||
*/ | ||
@@ -104,3 +316,3 @@ function deleteExpireProp(node) { | ||
* reset any existing override | ||
* @param {*} node node data | ||
* @param {ITimeControlNode} node node data | ||
*/ | ||
@@ -123,3 +335,3 @@ function posOverwriteReset(node) { | ||
* setup the expiring of n override or update an existing expiring | ||
* @param {*} node node data | ||
* @param {ITimeControlNode} node node data | ||
* @param {ITimeObject} oNow the *current* date Object | ||
@@ -166,4 +378,4 @@ * @param {number} dExpire the expiring time, (if it is NaN, default time will be tried to use) if it is not used, nor a Number or less than 1 no expiring activated | ||
* check if an override can be reset | ||
* @param {*} node node data | ||
* @param {*} msg message object | ||
* @param {ITimeControlNode} node node data | ||
* @param {Object} msg message object | ||
* @param {ITimeObject} oNow the *current* date Object | ||
@@ -181,3 +393,3 @@ */ | ||
val => { | ||
node.debug(`reset val="${util.inspect(val, { colors: true, compact: 10, breakLength: Infinity }) }"`); | ||
node.debug(`reset val="${util.inspect(val, { colors: true, compact: 5, breakLength: Infinity, depth: 10 }) }"`); | ||
if (val) { | ||
@@ -194,3 +406,3 @@ if (node.nodeData.overwrite && node.nodeData.overwrite.active) { | ||
* setting the reason for override | ||
* @param {*} node node data | ||
* @param {ITimeControlNode} node node data | ||
*/ | ||
@@ -224,5 +436,6 @@ function setOverwriteReason(node) { | ||
* pre-checking conditions to may be able to store temp data | ||
* @param {*} node node data | ||
* @param {*} msg the message object | ||
* @param {*} tempData the temporary storage object | ||
* @param {ITimeControlNode} node node data | ||
* @param {Object} msg the message object | ||
* @param {Object} tempData the temporary storage object | ||
* @param {Date} dNow simple Date Object | ||
*/ | ||
@@ -234,2 +447,3 @@ function prepareRules(node, msg, tempData, dNow) { | ||
rule.conditon = { | ||
index : -1, | ||
result : false | ||
@@ -253,2 +467,3 @@ }; | ||
type: el.valueType, | ||
// @ts-ignore | ||
expr: el.valueExpr, | ||
@@ -288,6 +503,6 @@ callback: (result, _obj) => { // opCallback | ||
* get time constrainty of a rule | ||
* @param {*} node node data | ||
* @param {*} msg the message object | ||
* @param {*} rule the rule data | ||
* @return {number} timestamp of the rule | ||
* @param {ITimeControlNode} node node data | ||
* @param {Object} msg the message object | ||
* @param {IRuleData} rule the rule data | ||
* @param {Date} dNow base timestamp | ||
*/ | ||
@@ -303,3 +518,3 @@ function getRuleTimeData(node, msg, rule, dNow) { | ||
} | ||
rule.timeData.source = 'Default'; | ||
rule.timeData.source = 'default'; | ||
rule.timeData.ts = rule.timeData.value.getTime(); | ||
@@ -312,5 +527,5 @@ // node.debug(`time=${rule.timeData.value} -> ${new Date(rule.timeData.value)}`); | ||
const numMin = rule.timeDataMin.value.getTime(); | ||
rule.timeDataMin.source = 'Min'; | ||
rule.timeDataMin.source = 'min'; | ||
if (rule.timeDataMin.error) { | ||
hlp.handleError(node, RED._('node-red-contrib-sun-position/position-config:errors.error-time', { message: rule.timeDataMin.error }), undefined, rule.timeDataAlt.error); | ||
hlp.handleError(node, RED._('node-red-contrib-sun-position/position-config:errors.error-time', { message: rule.timeDataMin.error }), undefined, rule.timeDataMin.error); | ||
} else if (!rule.timeDataMin.value) { | ||
@@ -330,5 +545,5 @@ throw new Error('Error can not calc Alt time!'); | ||
const numMax = rule.timeDataMax.value.getTime(); | ||
rule.timeDataMax.source = 'Max'; | ||
rule.timeDataMax.source = 'max'; | ||
if (rule.timeDataMax.error) { | ||
hlp.handleError(node, RED._('node-red-contrib-sun-position/position-config:errors.error-time', { message: rule.timeDataMax.error }), undefined, rule.timeDataAlt.error); | ||
hlp.handleError(node, RED._('node-red-contrib-sun-position/position-config:errors.error-time', { message: rule.timeDataMax.error }), undefined, rule.timeDataMax.error); | ||
} else if (!rule.timeDataMax.value) { | ||
@@ -349,32 +564,12 @@ throw new Error('Error can not calc Alt time!'); | ||
/** | ||
* Timestamp compare function | ||
* @name ICompareTimeStamp | ||
* @function | ||
* @param {number} timeStamp The timestamp which should be compared | ||
* @returns {Boolean} return true if if the timestamp is valid, otherwise false | ||
*/ | ||
/** | ||
* support timeData | ||
* @name ITimeObject Data | ||
* @param {Date} now | ||
* @param {number} nowNr | ||
* @param {number} dayNr | ||
* @param {number} monthNr | ||
* @param {number} dateNr | ||
* @param {number} yearNr | ||
* @param {number} dayId | ||
*/ | ||
/** | ||
* function to check a rule | ||
* @param {Object} node the node object | ||
* @param {ITimeControlNode} node the node object | ||
* @param {Object} msg the message object | ||
* @param {Object} rule a rule object to test | ||
* @param {IRuleData} rule a rule object to test | ||
* @param {ICompareTimeStamp} cmp a function to compare two timestamps. | ||
* @param {ITimeObject} data Now time object | ||
* @returns {Object|null} returns the rule if rule is valid, otherwhise null | ||
* @param {ITimeObject} tData Now time object | ||
* @returns {IRuleData|null} returns the rule if rule is valid, otherwhise null | ||
*/ | ||
function compareRules(node, msg, rule, cmp, data) { | ||
// node.debug(`compareRules rule ${rule.name} (${rule.pos}) data=${util.inspect(rule, {colors:true, compact:10})}`); | ||
function compareRules(node, msg, rule, cmp, tData) { | ||
// node.debug(`compareRules rule ${rule.name} (${rule.pos}) rule=${util.inspect(rule, {colors:true, compact:10})}`); | ||
if (rule.conditional) { | ||
@@ -388,3 +583,3 @@ try { | ||
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.getPropertyData', err)); | ||
node.debug(util.inspect(err, Object.getOwnPropertyNames(err))); | ||
node.debug(util.inspect(err)); | ||
return null; | ||
@@ -397,23 +592,25 @@ } | ||
if (rule.time.days && !rule.time.days.includes(data.dayNr)) { | ||
// @ts-ignore | ||
if (rule.time.days && !rule.time.days.includes(tData.dayNr)) { | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid days`); | ||
return null; | ||
} | ||
if (rule.time.months && !rule.time.months.includes(data.monthNr)) { | ||
// @ts-ignore | ||
if (rule.time.months && !rule.time.months.includes(tData.monthNr)) { | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid month`); | ||
return null; | ||
} | ||
if (rule.time.onlyOddDays && (data.dateNr % 2 === 0)) { // even | ||
if (rule.time.onlyOddDays && (tData.dateNr % 2 === 0)) { // even | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid even days`); | ||
return null; | ||
} | ||
if (rule.time.onlyEvenDays && (data.dateNr % 2 !== 0)) { // odd | ||
if (rule.time.onlyEvenDays && (tData.dateNr % 2 !== 0)) { // odd | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid odd days`); | ||
return null; | ||
} | ||
if (rule.time.onlyOddWeeks && (data.weekNr % 2 === 0)) { // even | ||
if (rule.time.onlyOddWeeks && (tData.weekNr % 2 === 0)) { // even | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid even week`); | ||
return null; | ||
} | ||
if (rule.time.onlyEvenWeeks && (data.weekNr % 2 !== 0)) { // odd | ||
if (rule.time.onlyEvenWeeks && (tData.weekNr % 2 !== 0)) { // odd | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid odd week`); | ||
@@ -423,7 +620,7 @@ return null; | ||
if (rule.time.dateStart || rule.time.dateEnd) { | ||
rule.time.dateStart.setFullYear(data.yearNr); | ||
rule.time.dateEnd.setFullYear(data.yearNr); | ||
rule.time.dateStart.setFullYear(tData.yearNr); | ||
rule.time.dateEnd.setFullYear(tData.yearNr); | ||
if (rule.time.dateEnd > rule.time.dateStart) { | ||
// in the current year | ||
if (data.now < rule.time.dateStart || data.now > rule.time.dateEnd) { | ||
if (tData.now < rule.time.dateStart || tData.now > rule.time.dateEnd) { | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid date range within year`); | ||
@@ -434,3 +631,3 @@ return null; | ||
// switch between year from end to start | ||
if (data.now < rule.time.dateStart && data.now > rule.time.dateEnd) { | ||
if (tData.now < rule.time.dateStart && tData.now > rule.time.dateEnd) { | ||
node.debug(`compareRules rule ${rule.name} (${rule.pos}) invalid date range over year`); | ||
@@ -441,8 +638,8 @@ return null; | ||
} | ||
const num = getRuleTimeData(node, msg, rule, data.now); | ||
const num = getRuleTimeData(node, msg, rule, tData.now); | ||
// node.debug(`compareRules ${rule.name} (${rule.pos}) type=${rule.time.operatorText} - ${rule.time.value} - num=${num} - rule.timeData = ${ util.inspect(rule.timeData, { colors: true, compact: 40, breakLength: Infinity }) }`); | ||
if (data.dayId === rule.timeData.dayId && num >=0 && (cmp(num) === true)) { | ||
if (tData.dayId === rule.timeData.dayId && num >=0 && (cmp(num) === true)) { | ||
return rule; | ||
} | ||
// node.debug(`compareRules rule ${rule.name} (${rule.pos}) dayId=${data.dayId} rule-DayID=${rule.timeData.dayId} num=${num} cmp=${cmp(num)} invalid time`); | ||
// node.debug(`compareRules rule ${rule.name} (${rule.pos}) dayId=${tData.dayId} rule-DayID=${rule.timeData.dayId} num=${num} cmp=${cmp(num)} invalid time`); | ||
return null; | ||
@@ -453,3 +650,3 @@ } | ||
* check if a level has a valid value | ||
* @param {*} node the node data | ||
* @param {ITimeControlNode} node the node data | ||
* @param {number} level the level to check | ||
@@ -460,10 +657,6 @@ * @returns {boolean} true if the level is valid, otherwise false | ||
// node.debug('validPosition level='+level); | ||
if (level === '' || level === null || typeof level === 'undefined') { | ||
node.warn(`Position is empty!`); | ||
if (typeof level !== 'number' || level === null || typeof level === 'undefined' || isNaN(level)) { | ||
node.warn(`Position: "${String(level)}" is empty or not a valid number!`); | ||
return false; | ||
} | ||
if (isNaN(level)) { | ||
node.warn(`Position: "${level}" is NaN!`); | ||
return false; | ||
} | ||
@@ -502,2 +695,5 @@ if (level < node.nodeData.levelBottom) { | ||
* initializes the node | ||
* @param {runtimeRED} REDLib the level to check | ||
* @param {ITimeControlNode} node the node data | ||
* @param {Object} config the level to check | ||
*/ | ||
@@ -578,2 +774,3 @@ function initializeCtrl(REDLib, node, config) { | ||
rule.conditions = []; | ||
// @ts-ignore | ||
if (rule.validOperandAType && rule.validOperandAType !== 'none') { | ||
@@ -583,75 +780,112 @@ rule.conditions.push({ | ||
conditionText : '', | ||
// @ts-ignore | ||
value : rule.validOperandAValue, | ||
// @ts-ignore | ||
valueType : rule.validOperandAType, | ||
// @ts-ignore | ||
operator : rule.validOperator, | ||
// @ts-ignore | ||
operatorText : rule.validOperatorText, | ||
// @ts-ignore | ||
threshold : rule.validOperandBValue, | ||
thresholdType : (rule.validOperandBType || 'num') | ||
// @ts-ignore | ||
thresholdType : (rule.validOperandBType || 'num'), | ||
result : false | ||
}); | ||
// @ts-ignore | ||
const conditionValue = parseInt(rule.valid2LogOperator); | ||
// @ts-ignore | ||
if (conditionValue > 0 && rule.valid2OperandAType) { | ||
rule.conditions.push({ | ||
// @ts-ignore | ||
condition : conditionValue, | ||
// @ts-ignore | ||
conditionText : rule.valid2LogOperatorText, | ||
// @ts-ignore | ||
value : rule.valid2OperandAValue, | ||
// @ts-ignore | ||
valueType : (rule.valid2OperandAType || 'msg'), | ||
// @ts-ignore | ||
operator : rule.valid2Operator, | ||
// @ts-ignore | ||
operatorText : rule.valid2OperatorText, | ||
// @ts-ignore | ||
threshold : rule.valid2OperandBValue, | ||
thresholdType : (rule.valid2OperandBType || 'num') | ||
// @ts-ignore | ||
thresholdType : (rule.valid2OperandBType || 'num'), | ||
result : false | ||
}); | ||
} | ||
} | ||
delete rule.validOperandAValue; | ||
delete rule.validOperandAType; | ||
delete rule.validOperator; | ||
delete rule.validOperatorText; | ||
delete rule.validOperandBValue; | ||
delete rule.validOperandBType; | ||
delete rule.valid2LogOperator; | ||
delete rule.valid2LogOperatorText; | ||
delete rule.valid2OperandAValue; | ||
delete rule.valid2OperandAType; | ||
delete rule.valid2Operator; | ||
delete rule.valid2OperatorText; | ||
delete rule.valid2OperandBValue; | ||
delete rule.valid2OperandBType; | ||
// @ts-ignore | ||
delete rule.validOperandAValue; // @ts-ignore | ||
delete rule.validOperandAType; // @ts-ignore | ||
delete rule.validOperator; // @ts-ignore | ||
delete rule.validOperatorText; // @ts-ignore | ||
delete rule.validOperandBValue; // @ts-ignore | ||
delete rule.validOperandBType; // @ts-ignore | ||
delete rule.valid2LogOperator; // @ts-ignore | ||
delete rule.valid2LogOperatorText; // @ts-ignore | ||
delete rule.valid2OperandAValue; // @ts-ignore | ||
delete rule.valid2OperandAType; // @ts-ignore | ||
delete rule.valid2Operator; // @ts-ignore | ||
delete rule.valid2OperatorText; // @ts-ignore | ||
delete rule.valid2OperandBValue; // @ts-ignore | ||
delete rule.valid2OperandBType; // @ts-ignore | ||
} | ||
// @ts-ignore | ||
if(rule.timeType) { | ||
// @ts-ignore | ||
if (!rule.time && rule.timeType !== 'none') { | ||
// @ts-ignore | ||
rule.time = { | ||
// @ts-ignore | ||
type : rule.timeType, | ||
// @ts-ignore | ||
value : (rule.timeValue || ''), | ||
// @ts-ignore | ||
operator : (parseInt(rule.timeOp) || cRuleUntil), | ||
// @ts-ignore | ||
offsetType : (rule.offsetType || 'none'), | ||
// @ts-ignore | ||
offset : (rule.offsetValue || 1), | ||
// @ts-ignore | ||
multiplier : (parseInt(rule.multiplier) || 60000), | ||
// @ts-ignore | ||
days : (rule.timeDays || '*'), | ||
// @ts-ignore | ||
months : (rule.timeMonths || '*') | ||
}; | ||
if (rule.timeOnlyOddDays) rule.time.onlyOddDays = rule.timeOnlyOddDays; | ||
if (rule.timeOnlyEvenDays) rule.time.onlyEvenDays = rule.timeOnlyEvenDays; | ||
if (rule.timeDateStart) rule.time.dateStart = rule.timeDateStart; | ||
if (rule.timeDateEnd) rule.time.dateEnd = rule.timeDateEnd; | ||
if (rule.timeOpText) rule.time.operatorText = rule.timeOpText; | ||
// @ts-ignore | ||
if (rule.timeOnlyOddDays) rule.time.onlyOddDays = rule.timeOnlyOddDays; // @ts-ignore | ||
if (rule.timeOnlyEvenDays) rule.time.onlyEvenDays = rule.timeOnlyEvenDays; // @ts-ignore | ||
if (rule.timeDateStart) rule.time.dateStart = rule.timeDateStart; // @ts-ignore | ||
if (rule.timeDateEnd) rule.time.dateEnd = rule.timeDateEnd; // @ts-ignore | ||
if (rule.timeOpText) rule.time.operatorText = rule.timeOpText; // @ts-ignore | ||
if (rule.timeMinType) { | ||
// @ts-ignore | ||
if (!rule.timeMin && rule.timeMinType !== 'none') { | ||
rule.timeMin = { | ||
type : rule.timeMinType, | ||
value : (rule.timeMinValue || ''), | ||
offsetType : (rule.offsetMinType || 'none'), | ||
offset : (rule.offsetMinValue || 1), | ||
multiplier : (parseInt(rule.multiplierMin) || 60000) | ||
// @ts-ignore | ||
type : rule.timeMinType, // @ts-ignore | ||
value : (rule.timeMinValue || ''), // @ts-ignore | ||
offsetType : (rule.offsetMinType || 'none'), // @ts-ignore | ||
offset : (rule.offsetMinValue || 1), // @ts-ignore | ||
multiplier : (parseInt(rule.multiplierMin) || 60000), | ||
next : false | ||
}; | ||
} | ||
} | ||
// @ts-ignore | ||
if (rule.timeMaxType) { | ||
// @ts-ignore | ||
if (!rule.timeMax && rule.timeMaxType !== 'none') { | ||
rule.timeMax = { | ||
type : rule.timeMaxType, | ||
value : (rule.timeMaxValue || ''), | ||
offsetType : (rule.offsetMaxType || 'none'), | ||
offset : (rule.offsetMaxValue || 1), | ||
multiplier : (parseInt(rule.multiplierMax) || 60000) | ||
// @ts-ignore | ||
type : rule.timeMaxType, // @ts-ignore | ||
value : (rule.timeMaxValue || ''), // @ts-ignore | ||
offsetType : (rule.offsetMaxType || 'none'), // @ts-ignore | ||
offset : (rule.offsetMaxValue || 1), // @ts-ignore | ||
multiplier : (parseInt(rule.multiplierMax) || 60000), | ||
next : false | ||
}; | ||
@@ -661,34 +895,40 @@ } | ||
} | ||
delete rule.timeType; | ||
delete rule.timeValue; | ||
delete rule.timeOp; | ||
delete rule.offsetType; | ||
delete rule.offsetValue; | ||
delete rule.multiplier; | ||
delete rule.timeDays; | ||
delete rule.timeMonths; | ||
delete rule.timeOnlyOddDays; | ||
delete rule.timeOnlyEvenDays; | ||
delete rule.timeDateStart; | ||
delete rule.timeDateEnd; | ||
delete rule.timeOpText; | ||
delete rule.timeMinType; | ||
delete rule.timeMinValue; | ||
delete rule.offsetMinType; | ||
delete rule.offsetMinValue; | ||
delete rule.multiplierMin; | ||
delete rule.timeMinOp; | ||
delete rule.timeMaxType; | ||
delete rule.timeMaxValue; | ||
delete rule.offsetMaxType; | ||
delete rule.offsetMaxValue; | ||
delete rule.multiplierMax; | ||
// @ts-ignore | ||
delete rule.timeType; // @ts-ignore | ||
delete rule.timeValue; // @ts-ignore | ||
delete rule.timeOp; // @ts-ignore | ||
delete rule.offsetType; // @ts-ignore | ||
delete rule.offsetValue; // @ts-ignore | ||
delete rule.multiplier; // @ts-ignore | ||
delete rule.timeDays; // @ts-ignore | ||
delete rule.timeMonths; // @ts-ignore | ||
delete rule.timeOnlyOddDays; // @ts-ignore | ||
delete rule.timeOnlyEvenDays; // @ts-ignore | ||
delete rule.timeDateStart; // @ts-ignore | ||
delete rule.timeDateEnd; // @ts-ignore | ||
delete rule.timeOpText; // @ts-ignore | ||
delete rule.timeMinType; // @ts-ignore | ||
delete rule.timeMinValue; // @ts-ignore | ||
delete rule.offsetMinType; // @ts-ignore | ||
delete rule.offsetMinValue; // @ts-ignore | ||
delete rule.multiplierMin; // @ts-ignore | ||
delete rule.timeMinOp; // @ts-ignore | ||
delete rule.timeMaxType; // @ts-ignore | ||
delete rule.timeMaxValue; // @ts-ignore | ||
delete rule.offsetMaxType; // @ts-ignore | ||
delete rule.offsetMaxValue; // @ts-ignore | ||
delete rule.multiplierMax; // @ts-ignore | ||
delete rule.timeMaxOp; | ||
} | ||
// @ts-ignore | ||
if (rule.levelType) { | ||
if (!rule.level) { | ||
rule.level = { | ||
// @ts-ignore | ||
type : (rule.levelType || 'levelFixed'), | ||
// @ts-ignore | ||
value : (rule.levelValue || 'closed (min)'), | ||
// @ts-ignore | ||
operator : (parseInt(rule.levelOp) || cRuleAbsolute), | ||
// @ts-ignore | ||
operatorText : rule.levelOpText || RED._('node-red-contrib-sun-position/position-config:ruleCtrl.label.ruleLevelAbs') | ||
@@ -704,27 +944,37 @@ }; | ||
if ((rule.level.operator === 3) || (rule.level.operator === 4)) { // 3 -> ⭳✋ reset minimum; 4 -> ⭱️✋ reset maximum | ||
rule.level.operator.type = 'levelND'; | ||
rule.level.operator.value = ''; | ||
rule.level.type = 'levelND'; | ||
rule.level.value = ''; | ||
rule.level.operator = rule.level.operator - 2; | ||
} | ||
delete rule.levelType; | ||
delete rule.levelValue; | ||
delete rule.levelOp; | ||
// @ts-ignore | ||
delete rule.levelType; // @ts-ignore | ||
delete rule.levelValue; // @ts-ignore | ||
delete rule.levelOp; // @ts-ignore | ||
delete rule.levelOpText; | ||
} | ||
// @ts-ignore | ||
if (rule.payloadType) { | ||
// @ts-ignore | ||
if (!rule.payload && rule.payloadType !== 'none') { | ||
rule.payload = { | ||
// @ts-ignore | ||
type : rule.payloadType, | ||
// @ts-ignore | ||
value : (rule.payloadValue || ''), | ||
// @ts-ignore | ||
offsetType : (rule.payloadOffsetType || 'none'), | ||
// @ts-ignore | ||
offset : (rule.payloadOffsetValue || '1'), | ||
// @ts-ignore | ||
multiplier : (parseInt(rule.payloadOffsetMultiplier) || 60000), | ||
// @ts-ignore | ||
format : (parseInt(rule.payloadFormat) || 99) | ||
}; | ||
} | ||
delete rule.payloadType; | ||
delete rule.payloadValue; | ||
delete rule.payloadOffsetType; | ||
delete rule.payloadOffsetValue; | ||
delete rule.payloadOffsetMultiplier; | ||
// @ts-ignore | ||
delete rule.payloadType; // @ts-ignore | ||
delete rule.payloadValue; // @ts-ignore | ||
delete rule.payloadOffsetType; // @ts-ignore | ||
delete rule.payloadOffsetValue; // @ts-ignore | ||
delete rule.payloadOffsetMultiplier; // @ts-ignore | ||
delete rule.payloadFormat; | ||
@@ -737,2 +987,3 @@ } | ||
rule.name = rule.name || 'rule ' + rule.pos; | ||
// @ts-ignore | ||
rule.enabled = !(rule.enabled === false || rule.enabled === 'false'); | ||
@@ -760,3 +1011,5 @@ rule.resetOverwrite = hlp.isTrue(rule.resetOverwrite === true) ? true : false; | ||
} else { | ||
// @ts-ignore | ||
rule.time.days = rule.time.days.split(','); | ||
// @ts-ignore | ||
rule.time.days = rule.time.days.map( e => parseInt(e) ); | ||
@@ -767,3 +1020,5 @@ } | ||
} else { | ||
// @ts-ignore | ||
rule.time.months = rule.time.months.split(','); | ||
// @ts-ignore | ||
rule.time.months = rule.time.months.map( e => parseInt(e) ); | ||
@@ -797,4 +1052,6 @@ } | ||
if (cond.valueType === 'sunControlMode') { | ||
// @ts-ignore | ||
if (cond.value === 'off' || cond.value.charAt(0) === '0') { | ||
cond.value = 0; | ||
// @ts-ignore | ||
} else if (cond.value === 'maximize' || cond.value.charAt(0) === '1') { | ||
@@ -801,0 +1058,0 @@ cond.value = 1; |
{ | ||
"name": "node-red-contrib-sun-position", | ||
"version": "2.1.1", | ||
"version": "2.2.0-beta", | ||
"description": "NodeRED nodes to get sun and moon position", | ||
@@ -56,3 +56,5 @@ "keywords": [ | ||
"scripts": { | ||
"test": "eslint \"./**/*.js\" \"./**/*.html\" && node-red-dev validate", | ||
"test": "eslint \"./**/*.js\" \"./**/*.html\" && node-red-dev validate && mocha \"test/**/*_spec.js\"", | ||
"testnode": "mocha \"test/**/*_spec.js\"", | ||
"testnodes": "mocha \"test/**/*_spec.js\"", | ||
"lintfix": "eslint --fix \"./**/*.js\" \"./**/*.html\"", | ||
@@ -62,3 +64,3 @@ "lint": "eslint \"./**/*.js\" \"./**/*.html\"", | ||
"dev": "node-red -v", | ||
"prepublishOnly": "eslint \"./**/*.js\" \"./**/*.html\"" | ||
"prepublishOnly": "eslint \"./**/*.js\" \"./**/*.html\" && node-red-dev validate && mocha \"test/**/*_spec.js\"" | ||
}, | ||
@@ -100,30 +102,37 @@ "repository": { | ||
"nodes": { | ||
"position-config": "nodes/position-config.js", | ||
"time-inject": "nodes/time-inject.js", | ||
"within-time-switch": "nodes/within-time-switch.js", | ||
"clock-timer": "nodes/clock-timer.js", | ||
"time-comp": "nodes/time-comp.js", | ||
"time-span": "nodes/time-span.js", | ||
"blind-control": "nodes/blind-control.js", | ||
"sun-position": "nodes/sun-position.js", | ||
"moon-position": "nodes/moon-position.js" | ||
"position-config": "nodes/10-position-config.js", | ||
"time-inject": "nodes/20-time-inject.js", | ||
"within-time-switch": "nodes/21-within-time-switch.js", | ||
"delay-until": "nodes/22-delay-until.js", | ||
"sun-position": "nodes/30-sun-position.js", | ||
"moon-position": "nodes/31-moon-position.js", | ||
"time-comp": "nodes/60-time-comp.js", | ||
"time-span": "nodes/61-time-span.js", | ||
"blind-control": "nodes/80-blind-control.js", | ||
"clock-timer": "nodes/81-clock-timer.js" | ||
} | ||
}, | ||
"dependencies": { | ||
"suncalc3": "^2.0.1", | ||
"lodash.clonedeep": "^4.5.0", | ||
"lodash.isequal": "^4.5.0" | ||
"lodash.isequal": "^4.5.0", | ||
"cronosjs": "^1.7.1" | ||
}, | ||
"devDependencies": { | ||
"eslint": ">=8.9.0", | ||
"eslint": ">=8.11.0", | ||
"eslint-plugin-html": ">=6.2.0", | ||
"eslint-plugin-jsdoc": ">=37.9.1", | ||
"eslint-plugin-json": ">=3.1.0", | ||
"eslint-plugin-node": ">=11.1.0", | ||
"node-red-dev": "^0.1.5" | ||
"@types/express": "^4.17.13", | ||
"@types/jquery": "^3.5.14", | ||
"@types/node-red": "^1.2.0", | ||
"jsonata": "^1.8.6", | ||
"mocha": "^8.4.0", | ||
"node-red": ">=2.0.0", | ||
"node-red-dev": "^0.1.5", | ||
"node-red-node-test-helper": "^0.2.7", | ||
"should": "^13.2.3", | ||
"should-sinon": "^0.0.6", | ||
"sinon": "^13.0.1" | ||
}, | ||
"disabledSettings": { | ||
"plugins-disabled": [ | ||
"jsdoc" | ||
] | ||
}, | ||
"eslintConfig": { | ||
@@ -130,0 +139,0 @@ "env": { |
@@ -0,0 +0,0 @@ # node-red-contrib-sun-position for NodeRED |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unpublished package
Supply chain riskPackage version was not found on the registry. It may exist on a different registry and need to be configured to pull from that registry.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unpopular package
QualityThis package is not very popular.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
2487622
155
22373
0
2
4
15
1
1
+ Addedcronosjs@^1.7.1
+ Addedsuncalc3@^2.0.1
+ Addedcronosjs@1.7.1(transitive)
+ Addedsuncalc3@2.0.5(transitive)