Skip to content

Commit 0781eda

Browse files
authored
Visual Crossing, etc. (#62)
* Added optional Visual Crossing weather service. * Removed soon-to-be-discontinued Dark Sky weather service. * Added ability to use a pool of multiple NTP servers. * Added client option for choosing from among available weather services (if API keys have been provided to make more than one service available).
1 parent 5d78d5b commit 0781eda

39 files changed

Lines changed: 1418 additions & 888 deletions

.eslintrc.json

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
"parser": "@typescript-eslint/parser",
1616
"parserOptions": {
17-
"ecmaVersion": 2018,
17+
"ecmaVersion": 2020,
1818
"sourceType": "module"
1919
},
2020
"plugins": [
@@ -56,21 +56,31 @@
5656
"ignoreComments": true,
5757
"ignoredNodes": [
5858
"ClassProperty[value]",
59-
"NewExpression[arguments] :expression *"
59+
"NewExpression[arguments] :expression *",
60+
"TSUnionType"
6061
],
6162
"ObjectExpression": "first",
6263
"SwitchCase": 1
6364
}
6465
],
66+
"guard-for-in": "error",
6567
"key-spacing": "off",
6668
"multiline-ternary": "off",
69+
"node/no-callback-literal": "off",
6770
"no-control-regex": "off",
6871
"no-empty": "off",
6972
"no-labels": "off",
7073
"no-mixed-operators": "off",
71-
"no-multi-spaces": "off",
74+
"no-multi-spaces": ["error", {
75+
"ignoreEOLComments": true,
76+
"exceptions": {
77+
"Property": true,
78+
"VariableDeclarator": true
79+
}
80+
}],
7281
"no-new": "off",
7382
"no-return-assign": "off",
83+
"no-unexpected-multiline": "off",
7484
"no-unused-expressions": "off",
7585
"no-useless-constructor": "off",
7686
"@typescript-eslint/no-useless-constructor": "error",
@@ -85,6 +95,8 @@
8595
"vars": "all"
8696
}
8797
],
98+
"object-curly-newline": "off",
99+
"object-property-newline": "off",
88100
"one-var": "off",
89101
"operator-linebreak": "off",
90102
"semi": [

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 2.12.0
2+
3+
* Added optional Visual Crossing weather service.
4+
* Removed soon-to-be-discontinued Dark Sky weather service.
5+
* Added ability to use a pool of multiple NTP servers.
6+
* Added client option for choosing from among available weather services (if API keys have been provided to make more than one service available).
7+
18
## 2.11.0
29

310
* Updated design of 3-D printed stand.

README.md

Lines changed: 28 additions & 26 deletions
Large diffs are not rendered by default.

build.js

Lines changed: 32 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const settings: Record<string, string> = {
8383
AWC_ALLOW_CORS: 'true',
8484
AWC_KIOSK_MODE: 'true',
8585
AWC_LOG_CACHE_ACTIVITY: 'false',
86-
AWC_NTP_SERVER: 'pool.ntp.org',
86+
AWC_NTP_SERVERS: '',
8787
AWC_PORT: '8080',
8888
AWC_PREFERRED_WS: 'wunderground',
8989
AWC_WIRED_TH_GPIO: '17',
@@ -318,9 +318,17 @@ if (treatAsRaspberryPi) {
318318
if (!clearAcu && oldSettings.AWC_WIRELESS_TH_GPIO)
319319
doAcu = true;
320320

321+
if (!settings.AWC_NTP_SERVERS) {
322+
if (oldSettings.AWC_NTP_SERVER === 'pool.ntp.org')
323+
settings.AWC_NTP_SERVERS = '';
324+
else if (oldSettings.AWC_NTP_SERVER)
325+
settings.AWC_NTP_SERVERS = oldSettings.AWC_NTP_SERVER;
326+
}
327+
321328
delete settings.AWC_HAS_INDOOR_SENSOR;
322329
delete settings.AWC_TH_SENSOR_GPIO;
323330
delete settings.AWC_WIRELESS_TEMP;
331+
delete settings.AWC_NTP_SERVER;
324332

325333
if (clearKiosk)
326334
doKiosk = false;
@@ -605,46 +613,47 @@ function portValidate(s: string): boolean {
605613
return true;
606614
}
607615

616+
const DOMAIN_PATTERN =
617+
/^(((?!-))(xn--|_)?[-a-z0-9]{0,61}[a-z0-9]\.)*(xn--)?([a-z0-9][-a-z0-9]{0,60}|[-a-z0-9]{1,30}\.[a-z]{2,})(:\d{1,5})?$/i;
618+
608619
function ntpValidate(s: string): boolean {
609-
if (/^(((?!-))(xn--|_)?[-a-z0-9]{0,61}[a-z0-9]\.)*(xn--)?([a-z0-9][-a-z0-9]{0,60}|[-a-z0-9]{1,30}\.[a-z]{2,})(:\d{1,5})?$/i.test(s))
620+
const domains = s.split(',').map(d => d.trim());
621+
622+
if (s.trim() === '' || (domains.length > 0 && domains.findIndex(d => !DOMAIN_PATTERN.test(d)) < 0))
610623
return true;
611624

612-
console.log(chalk.redBright('NTP server must be a valid domain name (with optional port number)'));
625+
console.log(chalk.redBright('NTP servers must be a valid domain names (with optional port numbers)'));
613626
return false;
614627
}
615628

616-
const NO_MORE_DARK_SKY = (Date.now() > Date.parse('2021-11-30'));
617-
618-
if (NO_MORE_DARK_SKY && process.env.AWC_PREFERRED_WS === 'darksky')
629+
// Change out-of-date preference to default.
630+
if (process.env.AWC_PREFERRED_WS === 'darksky')
619631
process.env.AWC_PREFERRED_WS = 'wunderground';
620632

621633
function wsValidate(s: string): boolean | string {
622634
if (/^w[-b]*$/i.test(s))
623635
return 'wunderground';
624636
else if (/b/i.test(s))
625637
return 'weatherbit';
626-
else if (!NO_MORE_DARK_SKY && /^d/i.test(s))
627-
return 'darksky';
638+
else if (/^v/i.test(s))
639+
return 'visual_x';
628640

629-
if (NO_MORE_DARK_SKY)
630-
console.log(chalk.redBright('Weather service must be either (w)underground, weather(b)it, or (d)arksky'));
631-
else
632-
console.log(chalk.redBright('Weather service must be either (w)underground, or weather(b)it'));
641+
console.log(chalk.redBright('Weather service must be either (w)underground, weather(b)it, or (v)isual crossing'));
633642

634643
return false;
635644
}
636645

637646
function wsAfter(s: string): void {
638647
if (/^w[-b]*$/i.test(s)) {
639-
console.log(chalk.paleBlue(` Weather Underground chosen, but Weatherbit.io${NO_MORE_DARK_SKY ? '' : 'or Dark Sky'} can be used`));
648+
console.log(chalk.paleBlue(' Weather Underground chosen, but Weatherbit.io or Visual Crossing can be used'));
640649
console.log(chalk.paleBlue(' as fallback weather services.'));
641650
}
642651
else if (/b/i.test(s)) {
643652
console.log(chalk.paleBlue(' Weatherbit.io chosen, but Weather Underground will be used'));
644653
console.log(chalk.paleBlue(' as a fallback weather service.'));
645654
}
646-
else if (/^d/i.test(s)) {
647-
console.log(chalk.paleBlue(' Dark Sky chosen, but Weather Underground will be used'));
655+
else if (/^v/i.test(s)) {
656+
console.log(chalk.paleBlue(' Visual Crossing chosen, but Weather Underground will be used'));
648657
console.log(chalk.paleBlue(' as a fallback weather service.'));
649658
}
650659
}
@@ -722,7 +731,7 @@ let questions = [
722731
{ prompt: 'Perform npm install? (N option for debug only)', ask: true, yn: true, deflt: doNpmI ? 'Y' : 'N', validate: npmIValidate },
723732
{ name: 'AWC_PORT', prompt: 'HTTP server port.', ask: true, validate: portValidate },
724733
{ prompt: 'Allow user to reboot, shutdown, update, etc.?', ask: true, yn: true, deflt: doAdmin ? 'Y' : 'N', validate: adminValidate },
725-
{ name: 'AWC_NTP_SERVER', prompt: 'time server', ask: true, validate: ntpValidate },
734+
{ name: 'AWC_NTP_SERVERS', prompt: 'time servers (comma-separated domains, blank for defaults)', ask: true, validate: ntpValidate },
726735
{
727736
name: 'AWC_GOOGLE_API_KEY',
728737
prompt: 'Optional Google geocoding API key (for city names from\n GPS coordinates).' +
@@ -731,7 +740,7 @@ let questions = [
731740
},
732741
{ // #5
733742
name: 'AWC_PREFERRED_WS',
734-
prompt: 'preferred weather service, (w)underground, weather(b)it,\n or (d)arksky).',
743+
prompt: 'preferred weather service, (w)underground, weather(b)it,\n or (v)isual crossing).',
735744
ask: true,
736745
validate: wsValidate,
737746
after: wsAfter
@@ -743,9 +752,9 @@ let questions = [
743752
ask: true
744753
},
745754
{ // #7
746-
name: 'AWC_DARK_SKY_API_KEY',
747-
prompt: 'Optional Dark Sky weather API key.' +
748-
(settings.AWC_DARK_SKY_API_KEY ? '\n Enter - (dash) to remove old API key' : ''),
755+
name: 'AWC_VISUAL_CROSSING_API_KEY',
756+
prompt: 'Optional Visual Crossing weather API key.' +
757+
(settings.AWC_VISUAL_CROSSING_API_KEY ? '\n Enter - (dash) to remove old API key' : ''),
749758
ask: true
750759
},
751760
{ prompt: 'Use wired DHT temperature/humidity sensor?', ask: true, yn: true, deflt: doDht ? 'Y' : 'N', validate: dhtValidate },
@@ -760,11 +769,6 @@ let questions = [
760769
}
761770
];
762771

763-
if (NO_MORE_DARK_SKY) {
764-
questions[5].prompt = 'preferred weather service, (w)underground, or weather(b)it';
765-
questions.splice(7, 1);
766-
}
767-
768772
if (doDedicated) {
769773
questions.splice(questions.length - 1, 0,
770774
{ prompt: 'Launch browser in kiosk mode?', ask: true, yn: true, deflt: doKiosk ? 'Y' : 'N', validate: kioskValidate }

img/awc_dlog.png

72.5 KB
Loading

img/awc_screenshot.png

109 KB
Loading

0 commit comments

Comments
 (0)