Socket
Socket
Sign inDemoInstall

node-red-contrib-sun-position

Package Overview
Dependencies
Maintainers
1
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-sun-position - npm Package Compare versions

Comparing version 0.3.2 to 0.3.3

14

nodes/blind-control.js

@@ -290,4 +290,5 @@ /********************************************

node.blindData.overwrite.expireDateUTC = node.blindData.overwrite.expireDate.toUTCString();
node.blindData.overwrite.expireDateLocal = node.blindData.overwrite.expireDate.toLocaleString();
node.blindData.overwrite.expireTimeLocal = node.blindData.overwrite.expireDate.toLocaleTimeString();
node.blindData.overwrite.expireDateLocal = node.positionConfig.toDateString(node.blindData.overwrite.expireDate);
node.blindData.overwrite.expireTimeLocal = node.positionConfig.toTimeString(node.blindData.overwrite.expireDate);
node.debug(`expires in ${expire}ms = ${node.blindData.overwrite.expireDate}`);

@@ -539,3 +540,3 @@ node.timeOutObj = setTimeout(() => {

const livingRuleData = {};
const nowNr = hlp.getTimeNumber(now);
const nowNr = now.getTime();
// node.debug(`checkRules nowNr=${nowNr}, node.rulesCount=${node.rulesCount}`); // {colors:true, compact:10}

@@ -594,4 +595,4 @@ // pre-checking conditions to may be able to store temp data

}
rule.timeData.num = hlp.getTimeNumber(rule.timeData.value);
rule.timeData.num = rule.timeData.value.getTime();
node.debug('rule.timeData=' + util.inspect(rule.timeData));
if (cmp(rule.timeData.num, nowNr)) {

@@ -652,3 +653,4 @@ return rule;

livingRuleData.time = ruleSel.timeData;
livingRuleData.time.timeLocal = ruleSel.timeData.value.toLocaleTimeString();
livingRuleData.time.timeLocal = node.positionConfig.toTimeString(ruleSel.timeData.value);
livingRuleData.time.timeLocalDate = node.positionConfig.toDateString(ruleSel.timeData.value);
livingRuleData.time.dateISO= ruleSel.timeData.value.toISOString();

@@ -655,0 +657,0 @@ livingRuleData.time.dateUTC= ruleSel.timeData.value.toUTCString();

@@ -138,9 +138,10 @@ /*

const H = siderealTime(d, lw) - c.ra;
return {
azimuth: azimuth(H, phi, c.dec),
altitude: altitude(H, phi, c.dec)
altitude: altitude(H, phi, c.dec),
declination: c.dec
};
};
/**

@@ -309,4 +310,2 @@ * @typedef {Object} suntime

result.solarNoon.ts = result.solarNoon.value.getTime();
result.nadir.ts = result.nadir.value.getTime();
for (let i = 0, len = sunTimes.length; i < len; i += 1) {

@@ -351,4 +350,2 @@ const time = sunTimes[i];

};
result[time[2]].ts = result[time[2]].value.getTime();
result[time[1]].ts = result[time[1]].value.getTime();
}

@@ -367,2 +364,54 @@

/**
* calculates sun times for a given date and latitude/longitude
* @param {Date} date Date object with the for calculating sun-times
* @param {number} lat latitude for calculating sun-times
* @param {number} lng longitude for calculating sun-times
* @param {number} sunAngle sun angle for calculating sun-time
* @param {boolean} [inUTC] defines if the calculation should be in utc or local time (default is UTC)
* @return {suntimes} result object of sunTime
*/
SunCalc.getSunTime = function (date, lat, lng, sunAngle, inUTC) {
if (isNaN(lat)) {
throw new Error('latitude missing');
}
if (isNaN(lng)) {
throw new Error('longitude missing');
}
if (isNaN(sunAngle)) {
throw new Error('angle missing');
}
const lw = rad * -lng;
const phi = rad * lat;
const d = toDays(date, inUTC);
const n = julianCycle(d, lw);
const ds = approxTransit(0, lw, n);
const M = solarMeanAnomaly(ds);
const L = eclipticLongitude(M);
const dec = declination(L, 0);
const Jnoon = solarTransitJ(ds, M, L);
const Jset = getSetJ(sunAngle * rad, lw, phi, dec, n, M, L);
const Jrise = Jnoon - (Jset - Jnoon);
const v1 = fromJulianDay(Jset);
const v2 = fromJulianDay(Jrise);
return {
set: {
value: v1,
ts: v1.getTime(),
angle: sunAngle,
julian: Jset
},
rise: {
value: v2,
ts: v2.getTime(),
angle: (180 + (sunAngle * -1)),
julian: Jrise
}
};
};
// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas

@@ -369,0 +418,0 @@

@@ -69,10 +69,6 @@ {

"YYYYMMDD.HHMMSS",
"ECMA-262",
"UTC Datum und Zeit",
"lokale Datum und Zeit",
"lokale Datum und Zeit erweitert",
"lokale Zeit",
"lokale Zeit erw.",
"lokales Datum",
"lokales Datum lang",
"UTC Datum und Zeit",
"ISO Datum und Zeit UTC",

@@ -89,24 +85,2 @@ "ISO Datum und Zeit Lokal",

],
"outputFormatsName": [
"UNIX",
"YYYYMMDDHHMMSS",
"YYYYMMDD_HHMMSS",
"ECMA262",
"local",
"localLong",
"localTime",
"localTimeLong",
"localDate",
"localDateLong",
"UTC",
"ISO",
"ms",
"sec",
"min",
"hour",
"ISO",
"ISO",
"object",
"other"
],
"outputTSFormatsGroups": [

@@ -260,3 +234,8 @@ "Zeitpunkt (Zahl)",

"stateDateFormat": "Status-Datums Format",
"stateTimeFormat": "Status-Zeit Format"
"stateTimeFormat": "Status-Zeit Format",
"OSStandard": "Standard vom Betriebssystem",
"timeZoneDST": "Sommerzeit",
"noDST": "keine Sommerzeit",
"addDST1Hour": "Sommerzeit 1 Stunde hinzufügen",
"addDST2Hour": "Sommerzeit 2 Stunden hinzufügen"
},

@@ -276,3 +255,3 @@ "placeholder": {

"sunPosControl": "Here you can specify the upper and lower limits for the solar radiation so that you can evaluate the sunshine on 4 sides of an object.",
"stateFormat":"Änderungen am Format können einige zeit dauern, bis diese Auswirkung zeigen."
"timeZoneOffset":"Änderungen am Format können einige zeit dauern, bis diese Auswirkung zeigen."
},

@@ -279,0 +258,0 @@ "errors": {

@@ -69,12 +69,8 @@ {

"YYYYMMDD.HHMMSS",
"ECMA-262 - JSON Date representation",
"UTC date and time",
"local date and time",
"local date and time enh.",
"local time",
"local time enh.",
"local date",
"local date long",
"UTC date and time",
"ISO date and time UTC",
"ISO date and time local",
"ISO date and time local",
"milliseconds",

@@ -89,24 +85,2 @@ "seconds",

],
"outputFormatsName": [
"UNIX",
"YYYYMMDDHHMMSS",
"YYYYMMDD_HHMMSS",
"ECMA262",
"local",
"localLong",
"localTime",
"localTimeLong",
"localDate",
"localDateLong",
"UTC",
"ISO",
"ms",
"sec",
"min",
"hour",
"ISO",
"ISO",
"object",
"other"
],
"outputTSFormatsGroups": [

@@ -274,3 +248,8 @@ "timestamp (number)",

"stateDateFormat": "State Date Format",
"stateTimeFormat": "State Time Format"
"stateTimeFormat": "State Time Format",
"OSStandard": "Operating system standard",
"timeZoneDST": "DST",
"noDST": "No DST",
"addDST1Hour": "DST add 1 Hour",
"addDST2Hour": "DST add 2 Hours"
},

@@ -289,4 +268,3 @@ "placeholder": {

"config": "Starting from Version 2.0 the coordinates are not saved as credentials due to privacy reasons. So they no longer part of the regular flow and will not part of the export! To update from a previous version save and re-deploy is necessary.",
"sunPosControl": "Here you can specify the upper and lower limits for the solar radiation so that you can evaluate the sunshine on 4 sides of an object.",
"stateFormat":"Formatchanges to time could taken time until it will get any effect."
"timeZoneOffset": "If for the timezone OS Standard is choosen the standard timezone including daylight saving switch is used. If is not chosen this setting, but a special time zone then no change of the daylightsaving is done! Formatchanges to time could taken time until it will get any effect."
},

@@ -293,0 +271,0 @@ "errors": {

@@ -25,4 +25,7 @@ {

"resultOffset": "Offset"
},
"timeFormat": {
"default": ""
}
}
}

@@ -85,3 +85,3 @@ /********************************************

const altitude = (ports[0].payload.altitude) ? ports[0].payload.altitude.toFixed(2) : '?';
text = azimuth + '/' + altitude + ' - ' + node.positionConfig.dateToString(ports[0].payload.lastUpdate);
text = azimuth + '/' + altitude + ' - ' + node.positionConfig.toDateTimeString(ports[0].payload.lastUpdate);
fill = 'grey';

@@ -88,0 +88,0 @@ }

@@ -85,7 +85,16 @@ /********************************************

this.angleType = config.angleType;
this.tzOffset = (config.timeZoneOffset || 99);
this.tzOffset = parseInt(config.timeZoneOffset || 99);
this.tzDST = parseInt(config.timeZoneDST || 0);
if (isNaN(this.tzOffset) || this.tzOffset > 99 || this.tzOffset < -99) {
this.tzOffset = 99;
}
this.tzOffset = (this.tzOffset * -60);
if (this.tzOffset !== 99) {
this.tzOffset += this.tzDST;
this.tzOffset = (this.tzOffset * -60);
this.debug('tzOffset is set to ' + this.tzOffset + ' tzDST=' + this.tzDST);
} else {
this.tzOffset = null;
// this.debug('no tzOffset defined (tzDST=' + this.tzDST + ')');
}

@@ -155,3 +164,3 @@ this.stateTimeFormat = config.stateTimeFormat || '3';

getSunTime(now, value, offset, multiplier, next, days) {
this.debug('getSunTime value=' + value + ' offset=' + offset + ' multiplier=' + multiplier + ' next=' + next + ' days=' + days);
// this.debug('getSunTime value=' + value + ' offset=' + offset + ' multiplier=' + multiplier + ' next=' + next + ' days=' + days);
let result = this._sunTimesCheck(now);

@@ -168,3 +177,2 @@ result = Object.assign(result, this.sunTimesToday[value]);

}
result.value = hlp.addOffset(new Date(result.value), offset, multiplier);

@@ -239,4 +247,4 @@ }

*/
dateToString(dt) {
return (this.dateToDateString(dt) + ' ' + this.dateToTimeString(dt)).trim();
toDateTimeString(dt) {
return (this.toDateString(dt) + ' ' + this.toTimeString(dt)).trim();
}

@@ -249,7 +257,7 @@

*/
dateToTimeString(dt) {
if (this.stateTimeFormat === '3') {
toTimeString(dt) {
if (!this.tzOffset && this.stateTimeFormat === '3') {
return dt.toLocaleTimeString();
}
return hlp.getFormattedDateOut(dt, this.stateTimeFormat);
return hlp.getFormattedDateOut(dt, this.stateTimeFormat, (this.tzOffset === 0), this.tzOffset);
}

@@ -262,7 +270,7 @@

*/
dateToDateString(dt) {
if (this.stateDateFormat === '12') {
toDateString(dt) {
if (!this.tzOffset && this.stateDateFormat === '12') {
return dt.toLocaleDateString();
}
return hlp.getFormattedDateOut(dt, this.stateDateFormat);
return hlp.getFormattedDateOut(dt, this.stateDateFormat, (this.tzOffset === 0), this.tzOffset);
}

@@ -306,3 +314,3 @@ /*******************************************************************************************************/

getOutDataProp(_srcNode, msg, vType, value, format, offset, offsetType, multiplier, days) {
// _srcNode.debug('getOutDataProp type='+vType+' value='+value+' format='+format+' offset='+offset+' offset='+offsetType+' multiplier='+multiplier);
_srcNode.debug(`getOutDataProp type=${vType} value=${value} format=${format} offset=${offset} offset=${offsetType} multiplier=${multiplier} tzOffset=${this.tzOffset}`);
let result = null;

@@ -313,6 +321,9 @@ if (vType === null || vType === 'none' || vType === '' || (typeof vType === 'undefined')) {

result = hlp.addOffset((new Date()), offsetX, multiplier);
return hlp.getFormattedDateOut(result, format);
return hlp.getFormattedDateOut(result, format, (this.tzOffset === 0), this.tzOffset);
}
return value;
} else if (vType === 'date') {
if (this.tzOffset) {
return hlp.convertDateTimeZone(Date.now(), this.tzOffset);
}
return Date.now();

@@ -322,3 +333,3 @@ } else if (vType === 'dateSpecific') {

result = hlp.addOffset((new Date()), offsetX, multiplier);
return hlp.getFormattedDateOut(result, format);
return hlp.getFormattedDateOut(result, format, (this.tzOffset === 0), this.tzOffset);
} else if ((vType === 'pdsTime') || (vType === 'pdmTime')) {

@@ -333,10 +344,10 @@ if (vType === 'pdsTime') { // sun

if (result && result.value && !result.error) {
return hlp.getFormattedDateOut(result.value, format);
return hlp.getFormattedDateOut(result.value, format, (this.tzOffset === 0), this.tzOffset);
}
return null;
} else if (vType === 'entered' || vType === 'dateEntered') {
result = hlp.getDateOfText(String(value));
result = hlp.getDateOfText(String(value), (this.tzOffset === 0), this.tzOffset);
const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);
result = hlp.normalizeDate(result, offsetX, multiplier, undefined, days);
return hlp.getFormattedDateOut(result, format);
return hlp.getFormattedDateOut(result, format, (this.tzOffset === 0), this.tzOffset);
} else if (vType === 'dayOfMonth') {

@@ -348,3 +359,3 @@ result = new Date();

result = hlp.addOffset(result, offsetX, multiplier);
return hlp.getFormattedDateOut(result, format);
return hlp.getFormattedDateOut(result, format, (this.tzOffset === 0), this.tzOffset);
}

@@ -357,12 +368,17 @@ return null;

getDateFromProp(_srcNode, msg, vType, value, format, offset, offsetType, multiplier) {
// _srcNode.debug('getDateFromProp type='+vType+' value='+value+' format='+format+' offset='+offset+ ' offsetType=' + offsetType +' multiplier='+multiplier);
_srcNode.debug(`getDateFromProp type=${vType} value=${value} format=${format} offset=${offset} offsetType=${offsetType} multiplier=${multiplier} tzOffset=${this.tzOffset}`);
let result = null;
try {
if (vType === null || vType === 'none' || vType === '') {
if (vType === null || vType === 'none' || vType === '' || vType === 'date') {
if (this.tzOffset) {
return hlp.convertDateTimeZone(new Date(), this.tzOffset);
}
return new Date();
} else if (vType === 'date') {
return new Date();
} else if (vType === 'dateSpecific') {
const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);
return hlp.addOffset((new Date()), offsetX, multiplier);
let d = new Date();
if (this.tzOffset) {
d = hlp.convertDateTimeZone(d, this.tzOffset);
}
return hlp.addOffset(d, offsetX, multiplier);
} else if (vType === 'dayOfMonth') {

@@ -372,2 +388,5 @@ let d = new Date();

const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);
if (this.tzOffset) {
return hlp.addOffset(hlp.convertDateTimeZone((new Date()), this.tzOffset), offsetX, multiplier);
}
return hlp.addOffset(d, offsetX, multiplier);

@@ -386,2 +405,5 @@ } else if ((vType === 'pdsTime') || (vType === 'pdmTime')) {

if (result && result.value && !result.error) {
if (this.tzOffset) {
return hlp.convertDateTimeZone(result.value, this.tzOffset);
}
return result.value;

@@ -391,3 +413,3 @@ }

} else if (vType === 'entered' || vType === 'dateEntered') {
result = hlp.getDateOfText(String(value));
result = hlp.getDateOfText(String(value), (this.tzOffset === 0), this.tzOffset);
const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);

@@ -400,8 +422,12 @@ return hlp.addOffset(result, offsetX, multiplier);

if (result !== null && typeof result !== 'undefined') {
_srcNode.log(result);
const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);
result = hlp.parseDateFromFormat(result, format, RED._('position-config.days'), RED._('position-config.month'), RED._('position-config.dayDiffNames'));
if (this.tzOffset) {
result = hlp.convertDateTimeZone(result, this.tzOffset);
}
return hlp.addOffset(result, offsetX, multiplier);
}
} catch (err) {
this.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
_srcNode.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
const e = new Error(`Exception "${err.message}", on try to evaluate ${vType}.${value}`);

@@ -415,3 +441,3 @@ e.original = err;

getTimeProp(_srcNode, msg, vType, value, offsetType, offset, multiplier, next, days) {
this.debug('getTimeProp [' + hlp.getNodeId(_srcNode) + '] vType=' + vType + ' value=' + value + ' offset=' + offset + ' offsetType=' + offsetType + ' multiplier=' + multiplier + ' next=' + next + ' days=' + days);
_srcNode.debug(`getTimeProp vType=${vType} value=${value} offset=${offset} offsetType=${offsetType} multiplier=${multiplier} next=${next} days=${days} tzOffset=${this.tzOffset}`);
let result = {

@@ -429,2 +455,5 @@ value: null,

result.value = new Date();
if (this.tzOffset) {
result.value = hlp.convertDateTimeZone(result.value, this.tzOffset);
}
result.fix = true;

@@ -434,5 +463,8 @@ } else if (vType === 'dateSpecific') {

result.value = hlp.normalizeDate((new Date()), offsetX, multiplier, next, days);
if (this.tzOffset) {
result.value = hlp.convertDateTimeZone(result.value);
}
result.fix = true;
} else if (vType === 'entered') {
result.value = hlp.getTimeOfText(String(value), (new Date()));
result.value = hlp.getTimeOfText(String(value), (new Date()), (this.tzOffset === 0), this.tzOffset);
if (result.value !== null) {

@@ -447,2 +479,5 @@ const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);

result = this.getSunTime((new Date()), value, offsetX, multiplier, next, days);
if (this.tzOffset) {
result.value = hlp.convertDateTimeZone(result.value, this.tzOffset);
}
result.fix = true;

@@ -453,2 +488,5 @@ } else if (vType === 'pdmTime') {

result = this.getMoonTime((new Date()), value, offsetX, multiplier, next, days);
if (this.tzOffset) {
result.value = hlp.convertDateTimeZone(result.value, this.tzOffset);
}
result.fix = true;

@@ -461,5 +499,8 @@ } else {

if (res) {
result.value = hlp.getDateOfText(res);
result.value = hlp.getDateOfText(res, (this.tzOffset === 0), this.tzOffset);
const offsetX = this.getFloatProp(_srcNode, msg, offsetType, offset, 0);
result.value = hlp.normalizeDate(result.value, offsetX, multiplier, next, days);
if (this.tzOffset) {
result.value = hlp.convertDateTimeZone(result.value, this.tzOffset);
}
// this.debug(String(res) + ' -- ' + result.value);

@@ -471,3 +512,3 @@ } else {

} catch (err) {
this.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
_srcNode.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
const e = new Error(RED._('errors.notEvaluablePropertyAdd', {type:vType, value:value, err:result.error}));

@@ -485,2 +526,3 @@ e.original = err;

}
_srcNode.debug('getTimeProp result=' + util.inspect(result));
return result;

@@ -525,3 +567,3 @@ }

} else if (type === 'entered' || type === 'dateEntered') {
result = hlp.getDateOfText(String(value));
result = hlp.getDateOfText(String(value), (this.tzOffset === 0), this.tzOffset);
} else {

@@ -540,2 +582,3 @@ try {

}
_srcNode.debug('getPropValue result=' + util.inspect(result) + ' - ' + typeof result);
return result;

@@ -542,0 +585,0 @@ }

/************************************************************************/
const SelectFields = {
const globSelectFields = {
operatorsGroups: [

@@ -56,10 +56,6 @@ {id: 'default', label: 'compare Timestamp'}

{id: 11, group: 'number', name: 'YYYYMMDD_HHMMSS', label: 'YYYYMMDD.HHMMSS'},
{id: 1, group: 'string', name: 'ECMA262', label: 'ECMA-262', add: 'standard JSON Date representation'},
{id: 1, group: 'string', name: 'UTC', label: 'UTC date and time' },
{id: 2, group: 'string', name: 'local', label: 'local date and time'},
{id: 14, group: 'string', name: 'localLong', label: 'local date and time enhanced'},
{id: 3, group: 'string', name: 'localTime', label: 'local time'},
{id: 13, group: 'string', name: 'localTimeLong', label: 'local time enhanced'},
{id: 12, group: 'string', name: 'localDate', label: 'local date'},
{id: 15, group: 'string', name: 'localDateLong', label: 'local date long'},
{id: 4, group: 'string', name: 'UTC', label: 'UTC date and time'},
{id: 5, group: 'string', name: 'ISO', label: 'ISO date and time'},

@@ -128,3 +124,3 @@ {id: 18, group: 'string', name: 'ISO-2', label: 'ISO date and time of local timezone' },

function getSelectFields() { // eslint-disable-line no-unused-vars
return SelectFields;
return globSelectFields;
}

@@ -425,9 +421,9 @@

// console.log('appendOptions elementName='+ elementName + ' limit='+limit);
const groups = SelectFields[elementName + 'Groups'];
const groups = globSelectFields[elementName + 'Groups'];
if (!groups) {
throw new Error('no group "' + elementName + 'Groups" in SelectFields found!');
throw new Error('no group "' + elementName + 'Groups" in globSelectFields found!');
}
const elements = SelectFields[elementName];
const elements = globSelectFields[elementName];
if (!groups) {
throw new Error('no elements "' + elementName + '" in SelectFields found!');
throw new Error('no elements "' + elementName + '" in globSelectFields found!');
}

@@ -596,3 +592,3 @@ const groupLength = groups.length;

function multiselect(node, parent, elementName, i18N, id) { // eslint-disable-line no-unused-vars
const types = SelectFields[elementName + 'Short'];
const types = globSelectFields[elementName + 'Short'];
const getSelection = function getCBText(parent) {

@@ -621,5 +617,5 @@ const value = parent.find('#option-checkboxes input[type=checkbox]:checked');

list.attr('expanded', 'false');
const groups = SelectFields[elementName + 'Groups'];
const groups = globSelectFields[elementName + 'Groups'];
const groupLength = groups.length;
const elements = SelectFields[elementName];
const elements = globSelectFields[elementName];
const elementsLength = elements.length;

@@ -626,0 +622,0 @@ for (let gIndex = 0; gIndex < groupLength; gIndex++) {

@@ -69,3 +69,3 @@ /********************************************

node.error(startTime.error);
node.debug('startTime: ' + util.inspect(startTime));
// node.debug('startTime: ' + util.inspect(startTime));
} else {

@@ -82,3 +82,3 @@ ports[0].payload.startTime = startTime.value.getTime();

node.error(endTime.error);
node.debug('endTime: ' + util.inspect(endTime));
// node.debug('endTime: ' + util.inspect(endTime));
} else {

@@ -122,4 +122,4 @@ ports[0].payload.endTime = endTime.value.getTime();

shape: 'dot',
text: node.positionConfig.dateToTimeString(new Date(ports[0].payload.startTime)) + ' - ' +
node.positionConfig.dateToTimeString(new Date(ports[0].payload.endTime))
text: node.positionConfig.toTimeString(new Date(ports[0].payload.startTime)) + ' - ' +
node.positionConfig.toTimeString(new Date(ports[0].payload.endTime))
});

@@ -130,4 +130,4 @@ } else {

shape: 'dot',
text: node.positionConfig.dateToTimeString(new Date(ports[0].payload.startTime)) + ' - ' +
node.positionConfig.dateToTimeString(new Date(ports[0].payload.endTime))
text: node.positionConfig.toTimeString(new Date(ports[0].payload.startTime)) + ' - ' +
node.positionConfig.toTimeString(new Date(ports[0].payload.endTime))
});

@@ -142,3 +142,3 @@ }

const altitude = (ports[0].payload.altitude) ? ports[0].payload.altitude.toFixed(2) : '?';
text = azimuth + '/' + altitude + ' - ' + node.positionConfig.dateToString(ports[0].payload.lastUpdate);
text = azimuth + '/' + altitude + ' - ' + node.positionConfig.toDateTimeString(ports[0].payload.lastUpdate);
fill = 'grey';

@@ -145,0 +145,0 @@ }

@@ -73,10 +73,14 @@ /********************************************

if (operatorValid) {
if (rule.format === 'time-calc.timeFormat.default') {
rule.format = 0;
}
const ruleoperand = node.positionConfig.getDateFromProp(node, msg, rule.operandType, rule.operandValue, rule.format, rule.offsetValue, 'num', rule.multiplier);
/*
node.debug('operand ' + util.inspect(ruleoperand));
node.debug('operator ' + util.inspect(rule.operator));
node.debug('operatorType ' + util.inspect(rule.operatorType)); */
if (!ruleoperand) {
continue;
}
// node.debug('operand=' + util.inspect(ruleoperand));
// node.debug('operator=' + util.inspect(rule.operator));
let compare = null;
switch (rule.operator) {
switch (Number(rule.operator)) {
case 1: // equal { id: 1, group: "ms", label: "==", "text": "equal" },

@@ -105,3 +109,4 @@ compare = (op1, op2) => op1 === op2;

const inputOperant = new Date(inputData);
// result = inputOperant.getTime() <= ruleoperand.getTime();
// node.debug('inputOperant=' + util.inspect(inputOperant));
// node.debug('operatorType=' + util.inspect(rule.operatorType));
if (rule.operatorType !== '*' && typeof rule.operatorType !== 'undefined') {

@@ -174,4 +179,7 @@ switch (rule.operatorType) {

// node.debug('inputData=' + util.inspect(inputData));
// node.debug('operand=' + util.inspect(ruleoperand));
break;
}
// node.debug('result=' + util.inspect(result));
}

@@ -178,0 +186,0 @@ }

@@ -109,4 +109,4 @@ /********************************************

}
node.debug('node.nextTimeData=' + util.inspect(node.nextTimeData));
node.error(node.nextTimeData.error);
node.debug('nextTimeData ' + util.inspect(node.nextTimeData));
} else {

@@ -130,4 +130,4 @@ node.nextTime = node.nextTimeData.value;

}
node.debug('node.nextTimeAltData=' + util.inspect(node.nextTimeAltData));
node.error(node.nextTimeAltData.error);
node.debug('nextTimeAltData: ' + util.inspect(node.nextTimeAltData));
} else {

@@ -212,3 +212,2 @@ node.nextTimeAlt = node.nextTimeAltData.value;

}
if ((errorStatus !== '')) {

@@ -227,3 +226,3 @@ node.status({

shape: 'ring',
text: node.positionConfig.dateToString(node.nextTimeAlt) + ' / ' + node.positionConfig.dateToTimeString(node.nextTime)
text: node.positionConfig.toDateTimeString(node.nextTimeAlt) + ' / ' + node.positionConfig.toTimeString(node.nextTime)
});

@@ -234,3 +233,3 @@ } else {

shape: 'dot',
text: node.positionConfig.dateToString(node.nextTime) + ' / ' + node.positionConfig.dateToTimeString(node.nextTimeAlt)
text: node.positionConfig.toDateTimeString(node.nextTime) + ' / ' + node.positionConfig.toTimeString(node.nextTimeAlt)
});

@@ -242,3 +241,3 @@ }

shape: 'dot',
text: node.positionConfig.dateToString(node.nextTime)
text: node.positionConfig.toDateTimeString(node.nextTime)
});

@@ -245,0 +244,0 @@ } else {

@@ -193,5 +193,3 @@ /********************************************

timeUTCStr: date1.toUTCString(),
timeISOStr: date1.toISOString(),
timeLocaleStr: date1.toLocaleString(),
timeLocaleTimeStr: date1.toLocaleTimeString()
timeISOStr: date1.toISOString()
},

@@ -202,5 +200,3 @@ end: {

timeUTCStr: date2.toUTCString(),
timeISOStr: date2.toISOString(),
timeLocaleStr: date2.toLocaleString(),
timeLocaleTimeStr: date2.toLocaleTimeString()
timeISOStr: date2.toISOString()
},

@@ -269,2 +265,6 @@ timeSpan: timeSpan,

resultObj = getFormattedTimeSpanOut(operand1, operand2, config.result1TSFormat);
resultObj.start.timeLocaleTimeStr = node.positionConfig.toTimeString(resultObj.start.date);
resultObj.start.timeLocaleDateStr = node.positionConfig.toDateString(resultObj.start.date);
resultObj.end.timeLocaleTimeStr = node.positionConfig.toTimeString(resultObj.end.date);
resultObj.end.timeLocaleDateStr = node.positionConfig.toDateString(resultObj.end.date);
} else if (config.result1ValueType === 'operand1') {

@@ -271,0 +271,0 @@ resultObj = hlp.getFormattedDateOut(operand1, config.result1Format);

@@ -45,7 +45,12 @@ /********************************************

function setstate(node, result, status, statusObj, _onInit) {
if (status > 255) {
function setstate(node, data, _onInit) {
if (data.error) {
node.status({
fill: 'red',
shape: 'dot',
text: data.error
});
return false;
}
if (result.start.error) {
if (data.start && data.start.error) {
if (_onInit === true) {

@@ -55,9 +60,9 @@ node.status({

shape: 'ring',
text: RED._('node-red-contrib-sun-position/position-config:errors.error-init', result.start.error)
text: RED._('node-red-contrib-sun-position/position-config:errors.error-init', data.start.error)
});
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.warn-init', result.start.error));
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.warn-init', data.start.error));
return true;
}
hlp.handleError(node, RED._('within-time-switch.errors.error-start-time', { message : result.start.error}), undefined, result.start.error);
} else if (result.end.error) {
hlp.handleError(node, RED._('within-time-switch.errors.error-start-time', { message : data.start.error}), undefined, data.start.error);
} else if (data.end && data.end.error) {
if (_onInit === true) {

@@ -67,24 +72,14 @@ node.status({

shape: 'ring',
text: RED._('node-red-contrib-sun-position/position-config:errors.error-init', result.end.error)
text: RED._('node-red-contrib-sun-position/position-config:errors.error-init', data.end.error)
});
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.warn-init', result.end.error));
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.warn-init', data.end.error));
return true;
}
hlp.handleError(node, RED._('within-time-switch.errors.error-end-time', { message : result.end.error}), undefined, result.end.error);
} else if ((status & 2) && statusObj) {
node.status(statusObj);
} else if ((status & 1) && result.start.value && result.end.value) {
hlp.handleError(node, RED._('within-time-switch.errors.error-end-time', { message : data.end.error}), undefined, data.end.error);
} else if (data.start && data.start.value && data.end && data.end.value) {
node.status({
fill: 'yellow',
shape: 'dot',
text: '⏲ ⏵' + node.positionConfig.dateToTimeString(result.start.value) + result.startSuffix + ' - ⏴' + node.positionConfig.dateToTimeString(result.end.value) + result.endSuffix
text: '⏵' + node.positionConfig.toTimeString(data.start.value) + data.startSuffix + ' - ⏴' + node.positionConfig.toTimeString(data.end.value) + data.endSuffix
});
} else {
node.status({});
/*
node.status({
fill: "red",
shape: "dot",
text: 'status not available'
}); */
}

@@ -214,7 +209,3 @@ return false;

node.error(RED._('node-red-contrib-sun-position/position-config:errors.pos-config'));
node.status({
fill: 'red',
shape: 'dot',
text: RED._('node-red-contrib-sun-position/position-config:errors.pos-config-state')
});
setstate(node, { error: RED._('node-red-contrib-sun-position/position-config:errors.pos-config-state')});
return null;

@@ -235,12 +226,7 @@ }

const cmpNow = hlp.getTimeNumberUTC(now);
const status = (config.statusOut || 3);
setstate(this, result);
if (startNr < endNr) {
if (cmpNow >= startNr && cmpNow < endNr) {
// this.debug('compare in time 1 ' + startNr + ' - ' + cmpNow + ' - ' + endNr);
this.debug('in time [1] - send msg to first output ' + result.startSuffix + node.positionConfig.toDateTimeString(now) + result.endSuffix + ' (' + startNr + ' - ' + cmpNow + ' - ' + endNr + ')');
this.send([msg, null]);
setstate(this, result, status, {
fill: 'green',
shape: 'ring',
text: '🖅 ' + result.startSuffix + node.positionConfig.dateToString(now) + result.endSuffix
}, false);
checkReSendMsgDelayed(config.lastMsgOnEndOut, this, result.end.value, msg);

@@ -250,9 +236,4 @@ return null;

} else if (!(cmpNow >= endNr && cmpNow < startNr)) {
// this.debug('compare in time 2 ' + startNr + ' - ' + cmpNow + ' - ' + endNr);
this.debug('in time [2] - send msg to first output ' + result.startSuffix + node.positionConfig.toDateTimeString(now) + result.endSuffix + ' (' + startNr + ' - ' + cmpNow + ' - ' + endNr + ')');
this.send([msg, null]);
setstate(this, result, status, {
fill: 'green',
shape: 'dot',
text: '🖅 ' + result.startSuffix + node.positionConfig.dateToString(now) + result.endSuffix
}, false);
checkReSendMsgDelayed(config.lastMsgOnEndOut, this, result.end.value, msg);

@@ -262,9 +243,4 @@ return null;

// this.debug('compare out of time ' + startNr + ' - ' + cmpNow + ' - ' + endNr);
this.debug('out of time - send msg to second output ' + result.startSuffix + node.positionConfig.toDateTimeString(now) + result.endSuffix + ' (' + startNr + ' - ' + cmpNow + ' - ' + endNr + ')');
this.send([null, msg]);
setstate(this, result, status, {
fill: 'yellow',
shape: 'dot',
text: '⛔' + result.startSuffix + node.positionConfig.dateToString(now) + result.endSuffix
}, false);
checkReSendMsgDelayed(config.lastMsgOnStartOut, this, result.start.value, msg);

@@ -274,7 +250,3 @@ } catch (err) {

node.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
node.status({
fill: 'red',
shape: 'ring',
text: RED._('node-red-contrib-sun-position/position-config:errors.error-title')
});
setstate(node, { error: RED._('node-red-contrib-sun-position/position-config:errors.error-title') });
}

@@ -286,7 +258,3 @@ });

node.error(RED._('node-red-contrib-sun-position/position-config:errors.pos-config'));
node.status({
fill: 'red',
shape: 'dot',
text: RED._('node-red-contrib-sun-position/position-config:errors.pos-config-state')
});
setstate(node, { error: RED._('node-red-contrib-sun-position/position-config:errors.pos-config-state') });
return null;

@@ -297,3 +265,3 @@ }

// if an error occurred, will retry in 6 minutes. This will prevent errors on initialization.
if (setstate(this, result, (config.statusOut || 3), null, true)) {
if (setstate(this, result, true)) {
node.debug('node is in initialization, retrigger time calculation in 6 min');

@@ -303,11 +271,7 @@ setTimeout(() => {

const result = calcWithinTimes(this, null, config);
setstate(this, result, (config.statusOut || 3));
setstate(this, result);
} catch (err) {
node.error(err.message);
node.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
node.status({
fill: 'red',
shape: 'ring',
text: RED._('node-red-contrib-sun-position/position-config:errors.error-title')
});
setstate(node, { error: RED._('node-red-contrib-sun-position/position-config:errors.error-title') });
}

@@ -319,7 +283,3 @@ }, 360000); // 6 Minuten

node.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
node.status({
fill: 'red',
shape: 'ring',
text: RED._('node-red-contrib-sun-position/position-config:errors.error-title')
});
setstate(node, { error: RED._('node-red-contrib-sun-position/position-config:errors.error-title') });
}

@@ -326,0 +286,0 @@ }

{
"name": "node-red-contrib-sun-position",
"version": "0.3.2",
"version": "0.3.3",
"description": "NodeRED nodes to get sun and moon position",

@@ -5,0 +5,0 @@ "keywords": [

@@ -29,43 +29,43 @@ # node-red-contrib-sun-position for NodeRED

- [node-red-contrib-sun-position for NodeRED](#node-red-contrib-sun-position-for-nodered)
- [Table of contents](#table-of-contents)
- [Installation](#installation)
- [General](#general)
- [Saving resources](#saving-resources)
- [second based accuracy](#second-based-accuracy)
- [Implemented Nodes](#implemented-nodes)
- [sun-position](#sun-position)
- [sun-position - Node settings](#sun-position---node-settings)
- [Node Input](#node-input)
- [sun-position - Node Output](#sun-position---node-output)
- [moon-position](#moon-position)
- [moon-position - Node settings](#moon-position---node-settings)
- [moon-position - Node Output](#moon-position---node-output)
- [time-inject](#time-inject)
- [time-inject - Node settings](#time-inject---node-settings)
- [time-inject - Node Input](#time-inject---node-input)
- [time-inject - Node Output](#time-inject---node-output)
- [within-time](#within-time)
- [within-time - Node settings](#within-time---node-settings)
- [time-comp](#time-comp)
- [time-comp - Node settings](#time-comp---node-settings)
- [time-span](#time-span)
- [time-span - Node settings](#time-span---node-settings)
- [blind-control](#blind-control)
- [Times definitions](#times-definitions)
- [sun times](#sun-times)
- [remarks](#remarks)
- [blue hour](#blue-hour)
- [amateurDawn /amateurDusk](#amateurdawn-amateurdusk)
- [alternate properties](#alternate-properties)
- [moon times](#moon-times)
- [message, flow or global property or JSONATA expression](#message-flow-or-global-property-or-jsonata-expression)
- [input parse formats](#input-parse-formats)
- [output timestamp formats](#output-timestamp-formats)
- [output timespan formats](#output-timespan-formats)
- [Conditions](#conditions)
- [TODO](#todo)
- [Bugs and Feedback](#bugs-and-feedback)
- [LICENSE](#license)
- [Other](#other)
* [node-red-contrib-sun-position for NodeRED](#node-red-contrib-sun-position-for-nodered)
* [Table of contents](#table-of-contents)
* [Installation](#installation)
* [General](#general)
* [Saving resources](#saving-resources)
* [second based accuracy](#second-based-accuracy)
* [Implemented Nodes](#implemented-nodes)
* [sun-position](#sun-position)
* [sun-position - Node settings](#sun-position---node-settings)
* [Node Input](#node-input)
* [sun-position - Node Output](#sun-position---node-output)
* [moon-position](#moon-position)
* [moon-position - Node settings](#moon-position---node-settings)
* [moon-position - Node Output](#moon-position---node-output)
* [time-inject](#time-inject)
* [time-inject - Node settings](#time-inject---node-settings)
* [time-inject - Node Input](#time-inject---node-input)
* [time-inject - Node Output](#time-inject---node-output)
* [within-time](#within-time)
* [within-time - Node settings](#within-time---node-settings)
* [time-comp](#time-comp)
* [time-comp - Node settings](#time-comp---node-settings)
* [time-span](#time-span)
* [time-span - Node settings](#time-span---node-settings)
* [blind-control](#blind-control)
* [Times definitions](#times-definitions)
* [sun times](#sun-times)
* [remarks](#remarks)
* [blue hour](#blue-hour)
* [amateurDawn /amateurDusk](#amateurdawn-amateurdusk)
* [alternate properties](#alternate-properties)
* [moon times](#moon-times)
* [message, flow or global property or JSONATA expression](#message-flow-or-global-property-or-jsonata-expression)
* [input parse formats](#input-parse-formats)
* [output timestamp formats](#output-timestamp-formats)
* [output timespan formats](#output-timespan-formats)
* [Conditions](#conditions)
* [TODO](#todo)
* [Bugs and Feedback](#bugs-and-feedback)
* [LICENSE](#license)
* [Other](#other)

@@ -76,3 +76,2 @@ ## Installation

## General

@@ -149,43 +148,2 @@

```json
{
"lastUpdate": "2018-11-11T11:11:11.111Z",
"latitude": "18.473782",
"longitude": "-34.357051",
"angleType": "deg",
"azimuth": 117.72942647370792,
"altitude": 20.984193272523992,
"times": {
"solarNoon":"2018-12-10T10:59:14.814Z",
"nadir":"2018-12-10T22:59:14.814Z",
"sunrise":"2018-12-10T06:58:55.584Z",
"sunset":"2018-12-10T14:59:34.044Z",
"sunriseEnd":"2018-12-10T07:03:12.232Z",
"sunsetStart":"2018-12-10T14:55:17.395Z",
"blueHourDawnEnd":"2018-12-10T06:34:22.885Z",
"blueHourDuskStart":"2018-12-10T15:24:06.743Z",
"civilDawn":"2018-12-10T06:19:31.249Z",
"civilDusk":"2018-12-10T15:38:58.379Z",
"blueHourDawnStart":"2018-12-10T06:05:03.443Z",
"blueHourDuskEnd":"2018-12-10T15:53:26.185Z",
"nauticalDawn":"2018-12-10T05:37:04.859Z",
"nauticalDusk":"2018-12-10T16:21:24.768Z",
"amateurDawn":"2018-12-10T05:16:44.832Z",
"amateurDusk":"2018-12-10T16:41:44.795Z",
"astronomicalDawn":"2018-12-10T04:56:49.931Z",
"astronomicalDusk":"2018-12-10T17:01:39.696Z",
"goldenHourDawnEnd":"2018-12-10T07:58:28.541Z",
"goldenHourDuskStart":"2018-12-10T14:00:01.086Z",
"dawn":"2018-12-10T06:19:31.249Z",
"dusk":"2018-12-10T15:38:58.379Z",
"nightEnd":"2018-12-10T04:56:49.931Z",
"night":"2018-12-10T17:01:39.696Z",
"nightStart":"2018-12-10T17:01:39.696Z",
"goldenHour":"2018-12-10T14:00:01.086Z"
},
"pos": [],
"posChanged": false
}
```
* **second output** to **... output** if limits for azimuth are defined the incoming message will send to this output. It adds a `msg.posChanged` property of type _boolean_ which is true if in the previous calculation no message was send to this output.

@@ -361,22 +319,2 @@

* **Status** here can be adjusted which status should be displayed under the node.
* this has the following possibilities:
* **none** - no status will be displayed - **only errors** - if an error occurs it will be displayed
![within-time-status-error](https://user-images.githubusercontent.com/12692680/57134527-b62e5800-6da6-11e9-946a-677044d25655.png)
* **time limits** - the time limits will be displayed. An `⎇` sign after a time will show that an alternate time is used.
![within-time-status-time](https://user-images.githubusercontent.com/12692680/57134513-b4649480-6da6-11e9-9bb2-3acda84b8ef8.png)
* **last message** - the time limits will be shown and if the last message was blocked. An `⎇` sign after a time will show that an alternate time is used.
![within-time-status-message-block](https://user-images.githubusercontent.com/12692680/57134528-b6c6ee80-6da6-11e9-90be-e3b15c2b2bff.png)
if the message was pass through the timestamp of this message will be shown.
![within-time-status-message-send](https://user-images.githubusercontent.com/12692680/57134529-b6c6ee80-6da6-11e9-8c71-7245dda4b6ee.png)
* **time limits or last message** - on deploy/start until a message arrives the same behavior as `time limits` options, otherwise the `last message` status display.
* **resend start** If this checkbox is checked and a message arrived outside of time, this message will be additional send again some milliseconds after next start time point. This option is only for fixed time definitions available.

@@ -391,4 +329,2 @@ * **resend end** If this checkbox is checked and a message arrived within time, this message will be additional send again some milliseconds after next end time point. This option is only for fixed time definitions available.

**This node is in development and has a pre release state!!**
```json

@@ -423,4 +359,2 @@ [{"id":"1a6b5f99.4c928","type":"time-comp","z":"4e9a710a.bf0b9","outputs":1,"name":"","positionConfig":"d9e9ca6a.952218","input":"payload","inputType":"msg","inputFormat":"0","inputOffset":0,"inputOffsetMultiplier":60,"rules":[],"checkall":"true","result1":"payload","result1Type":"msg","result1Value":"","result1ValueType":"input","result1Format":"5","result1Offset":0,"result1OffsetMultiplier":60,"x":350,"y":120,"wires":[["fd45b2d2.eba89"]]},{"id":"fd45b2d2.eba89","type":"debug","z":"4e9a710a.bf0b9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":570,"y":120,"wires":[]},{"id":"f390b758.7dd9b8","type":"inject","z":"4e9a710a.bf0b9","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":120,"wires":[["1a6b5f99.4c928"]]},{"id":"b87a5c79.d4ce3","type":"comment","z":"4e9a710a.bf0b9","name":"change Unix Timestamp to ISO","info":"","x":210,"y":80,"wires":[]},{"id":"20afdf5d.4cd8d","type":"comment","z":"4e9a710a.bf0b9","name":"compare Time","info":"","x":150,"y":180,"wires":[]},{"id":"3d8ee66c.7c86ea","type":"inject","z":"4e9a710a.bf0b9","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":240,"wires":[["f19f0fd9.8ad1d"]]},{"id":"f19f0fd9.8ad1d","type":"time-comp","z":"4e9a710a.bf0b9","outputs":3,"name":"","positionConfig":"d9e9ca6a.952218","input":"payload","inputType":"msg","inputFormat":"0","inputOffset":0,"inputOffsetMultiplier":60,"rules":[{"operator":"5","operatorType":"11,12,13,14,15,16,17,18","operatorText":"","operandType":"str","operandValue":"12:00","format":"ddd MMM dd yyyy HH:mm:ss","formatSelection":"0","offsetType":"none","offsetValue":"","propertyType":"none","propertyValue":""},{"operator":"3","operatorType":"11,12,13,14,15,16,17,18","operatorText":"","operandType":"str","operandValue":"15:00","format":"ddd MMM dd yyyy HH:mm:ss","formatSelection":"0","offsetType":"none","offsetValue":"","propertyType":"none","propertyValue":""}],"checkall":"true","result1":"payload","result1Type":"msg","result1Value":"","result1ValueType":"input","result1Format":"5","result1Offset":0,"result1OffsetMultiplier":60,"x":350,"y":240,"wires":[["723d7d7c.e7a874"],["44ac03f7.fd68fc"],["4d8512cd.73c90c"]]},{"id":"723d7d7c.e7a874","type":"debug","z":"4e9a710a.bf0b9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":220,"wires":[]},{"id":"44ac03f7.fd68fc","type":"debug","z":"4e9a710a.bf0b9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":570,"y":260,"wires":[]},{"id":"4d8512cd.73c90c","type":"debug","z":"4e9a710a.bf0b9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":570,"y":300,"wires":[]},{"id":"d9e9ca6a.952218","type":"position-config","z":0,"name":"Entenhausen","longitude":"13.72324","latitude":"51.12381","angleType":"deg"}]

**This node is in development and has a pre release state!!**
```json

@@ -427,0 +361,0 @@ tbd

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 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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc