NTP Timezone & Enable/Disable Setting (#80)
* quick and dirty WIP to investigate timezones, currently only building under esp8266 platform much of the status stuff has been stripped for now, to test the concepts * support set of common features across ESP32/ESP8266 WRT timezone and sntp return dates as ISO format strings * remove time library, and timelib fix which is no longer required * fix the icons * remove temporary changes to demo project
This commit is contained in:
parent
59326c6426
commit
ced5b74ba1
@ -1,4 +1,6 @@
|
||||
{
|
||||
"server": "pool.ntp.org",
|
||||
"interval": 3600
|
||||
"enabled": true,
|
||||
"server": "time.google.com",
|
||||
"tz_label": "Europe/London",
|
||||
"tz_format": "GMT0BST,M3.5.0/1,M10.5.0"
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
# Change the IP address to that of your ESP device to enable local development of the UI.
|
||||
# Remember to also enable CORS in platformio.ini before uploading the code to the device.
|
||||
REACT_APP_ENDPOINT_ROOT=http://192.168.0.20/rest/
|
||||
REACT_APP_ENDPOINT_ROOT=http://192.168.0.29/rest/
|
||||
|
@ -1,18 +1,16 @@
|
||||
import * as Highlight from '../constants/Highlight';
|
||||
|
||||
export const NTP_TIME_NOT_SET = 0;
|
||||
export const NTP_TIME_NEEDS_SYNC = 1;
|
||||
export const NTP_TIME_SET = 2;
|
||||
export const NTP_INACTIVE = 0;
|
||||
export const NTP_ACTIVE = 1;
|
||||
|
||||
export const isSynchronized = ntpStatus => ntpStatus && (ntpStatus.status === NTP_TIME_NEEDS_SYNC || ntpStatus.status === NTP_TIME_SET);
|
||||
export const isNtpActive = ntpStatus => ntpStatus && ntpStatus.status === NTP_ACTIVE;
|
||||
|
||||
export const ntpStatusHighlight = ntpStatus => {
|
||||
switch (ntpStatus.status) {
|
||||
case NTP_TIME_SET:
|
||||
case NTP_INACTIVE:
|
||||
return Highlight.IDLE;
|
||||
case NTP_ACTIVE:
|
||||
return Highlight.SUCCESS;
|
||||
case NTP_TIME_NEEDS_SYNC:
|
||||
return Highlight.WARN;
|
||||
case NTP_TIME_NOT_SET:
|
||||
default:
|
||||
return Highlight.ERROR;
|
||||
}
|
||||
@ -20,12 +18,10 @@ export const ntpStatusHighlight = ntpStatus => {
|
||||
|
||||
export const ntpStatus = ntpStatus => {
|
||||
switch (ntpStatus.status) {
|
||||
case NTP_TIME_SET:
|
||||
return "Synchronized";
|
||||
case NTP_TIME_NEEDS_SYNC:
|
||||
return "Synchronization required";
|
||||
case NTP_TIME_NOT_SET:
|
||||
return "Time not set"
|
||||
case NTP_INACTIVE:
|
||||
return "Inactive";
|
||||
case NTP_ACTIVE:
|
||||
return "Active";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
475
interface/src/constants/TZ.js
Normal file
475
interface/src/constants/TZ.js
Normal file
@ -0,0 +1,475 @@
|
||||
import React from 'react';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
export const TIME_ZONES = {
|
||||
"Africa/Abidjan": "GMT0",
|
||||
"Africa/Accra": "GMT0",
|
||||
"Africa/Addis_Ababa": "EAT-3",
|
||||
"Africa/Algiers": "CET-1",
|
||||
"Africa/Asmara": "EAT-3",
|
||||
"Africa/Bamako": "GMT0",
|
||||
"Africa/Bangui": "WAT-1",
|
||||
"Africa/Banjul": "GMT0",
|
||||
"Africa/Bissau": "GMT0",
|
||||
"Africa/Blantyre": "CAT-2",
|
||||
"Africa/Brazzaville": "WAT-1",
|
||||
"Africa/Bujumbura": "CAT-2",
|
||||
"Africa/Cairo": "EET-2",
|
||||
"Africa/Casablanca": "<+01>-1",
|
||||
"Africa/Ceuta": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Africa/Conakry": "GMT0",
|
||||
"Africa/Dakar": "GMT0",
|
||||
"Africa/Dar_es_Salaam": "EAT-3",
|
||||
"Africa/Djibouti": "EAT-3",
|
||||
"Africa/Douala": "WAT-1",
|
||||
"Africa/El_Aaiun": "<+01>-1",
|
||||
"Africa/Freetown": "GMT0",
|
||||
"Africa/Gaborone": "CAT-2",
|
||||
"Africa/Harare": "CAT-2",
|
||||
"Africa/Johannesburg": "SAST-2",
|
||||
"Africa/Juba": "EAT-3",
|
||||
"Africa/Kampala": "EAT-3",
|
||||
"Africa/Khartoum": "CAT-2",
|
||||
"Africa/Kigali": "CAT-2",
|
||||
"Africa/Kinshasa": "WAT-1",
|
||||
"Africa/Lagos": "WAT-1",
|
||||
"Africa/Libreville": "WAT-1",
|
||||
"Africa/Lome": "GMT0",
|
||||
"Africa/Luanda": "WAT-1",
|
||||
"Africa/Lubumbashi": "CAT-2",
|
||||
"Africa/Lusaka": "CAT-2",
|
||||
"Africa/Malabo": "WAT-1",
|
||||
"Africa/Maputo": "CAT-2",
|
||||
"Africa/Maseru": "SAST-2",
|
||||
"Africa/Mbabane": "SAST-2",
|
||||
"Africa/Mogadishu": "EAT-3",
|
||||
"Africa/Monrovia": "GMT0",
|
||||
"Africa/Nairobi": "EAT-3",
|
||||
"Africa/Ndjamena": "WAT-1",
|
||||
"Africa/Niamey": "WAT-1",
|
||||
"Africa/Nouakchott": "GMT0",
|
||||
"Africa/Ouagadougou": "GMT0",
|
||||
"Africa/Porto-Novo": "WAT-1",
|
||||
"Africa/Sao_Tome": "GMT0",
|
||||
"Africa/Tripoli": "EET-2",
|
||||
"Africa/Tunis": "CET-1",
|
||||
"Africa/Windhoek": "CAT-2",
|
||||
"America/Adak": "HST10HDT,M3.2.0,M11.1.0",
|
||||
"America/Anchorage": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/Anguilla": "AST4",
|
||||
"America/Antigua": "AST4",
|
||||
"America/Araguaina": "<-03>3",
|
||||
"America/Argentina/Buenos_Aires": "<-03>3",
|
||||
"America/Argentina/Catamarca": "<-03>3",
|
||||
"America/Argentina/Cordoba": "<-03>3",
|
||||
"America/Argentina/Jujuy": "<-03>3",
|
||||
"America/Argentina/La_Rioja": "<-03>3",
|
||||
"America/Argentina/Mendoza": "<-03>3",
|
||||
"America/Argentina/Rio_Gallegos": "<-03>3",
|
||||
"America/Argentina/Salta": "<-03>3",
|
||||
"America/Argentina/San_Juan": "<-03>3",
|
||||
"America/Argentina/San_Luis": "<-03>3",
|
||||
"America/Argentina/Tucuman": "<-03>3",
|
||||
"America/Argentina/Ushuaia": "<-03>3",
|
||||
"America/Aruba": "AST4",
|
||||
"America/Asuncion": "<-04>4<-03>,M10.1.0/0,M3.4.0/0",
|
||||
"America/Atikokan": "EST5",
|
||||
"America/Bahia": "<-03>3",
|
||||
"America/Bahia_Banderas": "CST6CDT,M4.1.0,M10.5.0",
|
||||
"America/Barbados": "AST4",
|
||||
"America/Belem": "<-03>3",
|
||||
"America/Belize": "CST6",
|
||||
"America/Blanc-Sablon": "AST4",
|
||||
"America/Boa_Vista": "<-04>4",
|
||||
"America/Bogota": "<-05>5",
|
||||
"America/Boise": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Cambridge_Bay": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Campo_Grande": "<-04>4",
|
||||
"America/Cancun": "EST5",
|
||||
"America/Caracas": "<-04>4",
|
||||
"America/Cayenne": "<-03>3",
|
||||
"America/Cayman": "EST5",
|
||||
"America/Chicago": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Chihuahua": "MST7MDT,M4.1.0,M10.5.0",
|
||||
"America/Costa_Rica": "CST6",
|
||||
"America/Creston": "MST7",
|
||||
"America/Cuiaba": "<-04>4",
|
||||
"America/Curacao": "AST4",
|
||||
"America/Danmarkshavn": "GMT0",
|
||||
"America/Dawson": "PST8PDT,M3.2.0,M11.1.0",
|
||||
"America/Dawson_Creek": "MST7",
|
||||
"America/Denver": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Detroit": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Dominica": "AST4",
|
||||
"America/Edmonton": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Eirunepe": "<-05>5",
|
||||
"America/El_Salvador": "CST6",
|
||||
"America/Fortaleza": "<-03>3",
|
||||
"America/Fort_Nelson": "MST7",
|
||||
"America/Glace_Bay": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"America/Godthab": "<-03>3<-02>,M3.5.0/-2,M10.5.0/-1",
|
||||
"America/Goose_Bay": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"America/Grand_Turk": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Grenada": "AST4",
|
||||
"America/Guadeloupe": "AST4",
|
||||
"America/Guatemala": "CST6",
|
||||
"America/Guayaquil": "<-05>5",
|
||||
"America/Guyana": "<-04>4",
|
||||
"America/Halifax": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"America/Havana": "CST5CDT,M3.2.0/0,M11.1.0/1",
|
||||
"America/Hermosillo": "MST7",
|
||||
"America/Indiana/Indianapolis": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Knox": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Marengo": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Petersburg": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Tell_City": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Vevay": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Vincennes": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Indiana/Winamac": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Inuvik": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Iqaluit": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Jamaica": "EST5",
|
||||
"America/Juneau": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/Kentucky/Louisville": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Kentucky/Monticello": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Kralendijk": "AST4",
|
||||
"America/La_Paz": "<-04>4",
|
||||
"America/Lima": "<-05>5",
|
||||
"America/Los_Angeles": "PST8PDT,M3.2.0,M11.1.0",
|
||||
"America/Lower_Princes": "AST4",
|
||||
"America/Maceio": "<-03>3",
|
||||
"America/Managua": "CST6",
|
||||
"America/Manaus": "<-04>4",
|
||||
"America/Marigot": "AST4",
|
||||
"America/Martinique": "AST4",
|
||||
"America/Matamoros": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Mazatlan": "MST7MDT,M4.1.0,M10.5.0",
|
||||
"America/Menominee": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Merida": "CST6CDT,M4.1.0,M10.5.0",
|
||||
"America/Metlakatla": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/Mexico_City": "CST6CDT,M4.1.0,M10.5.0",
|
||||
"America/Miquelon": "<-03>3<-02>,M3.2.0,M11.1.0",
|
||||
"America/Moncton": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"America/Monterrey": "CST6CDT,M4.1.0,M10.5.0",
|
||||
"America/Montevideo": "<-03>3",
|
||||
"America/Montreal": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Montserrat": "AST4",
|
||||
"America/Nassau": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/New_York": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Nipigon": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Nome": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/Noronha": "<-02>2",
|
||||
"America/North_Dakota/Beulah": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/North_Dakota/Center": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/North_Dakota/New_Salem": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Ojinaga": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"America/Panama": "EST5",
|
||||
"America/Pangnirtung": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Paramaribo": "<-03>3",
|
||||
"America/Phoenix": "MST7",
|
||||
"America/Port-au-Prince": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Port_of_Spain": "AST4",
|
||||
"America/Porto_Velho": "<-04>4",
|
||||
"America/Puerto_Rico": "AST4",
|
||||
"America/Punta_Arenas": "<-03>3",
|
||||
"America/Rainy_River": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Rankin_Inlet": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Recife": "<-03>3",
|
||||
"America/Regina": "CST6",
|
||||
"America/Resolute": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Rio_Branco": "<-05>5",
|
||||
"America/Santarem": "<-03>3",
|
||||
"America/Santiago": "<-04>4<-03>,M9.1.6/24,M4.1.6/24",
|
||||
"America/Santo_Domingo": "AST4",
|
||||
"America/Sao_Paulo": "<-03>3",
|
||||
"America/Scoresbysund": "<-01>1<+00>,M3.5.0/0,M10.5.0/1",
|
||||
"America/Sitka": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/St_Barthelemy": "AST4",
|
||||
"America/St_Johns": "NST3:30NDT,M3.2.0,M11.1.0",
|
||||
"America/St_Kitts": "AST4",
|
||||
"America/St_Lucia": "AST4",
|
||||
"America/St_Thomas": "AST4",
|
||||
"America/St_Vincent": "AST4",
|
||||
"America/Swift_Current": "CST6",
|
||||
"America/Tegucigalpa": "CST6",
|
||||
"America/Thule": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"America/Thunder_Bay": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Tijuana": "PST8PDT,M3.2.0,M11.1.0",
|
||||
"America/Toronto": "EST5EDT,M3.2.0,M11.1.0",
|
||||
"America/Tortola": "AST4",
|
||||
"America/Vancouver": "PST8PDT,M3.2.0,M11.1.0",
|
||||
"America/Whitehorse": "PST8PDT,M3.2.0,M11.1.0",
|
||||
"America/Winnipeg": "CST6CDT,M3.2.0,M11.1.0",
|
||||
"America/Yakutat": "AKST9AKDT,M3.2.0,M11.1.0",
|
||||
"America/Yellowknife": "MST7MDT,M3.2.0,M11.1.0",
|
||||
"Antarctica/Casey": "<+08>-8",
|
||||
"Antarctica/Davis": "<+07>-7",
|
||||
"Antarctica/DumontDUrville": "<+10>-10",
|
||||
"Antarctica/Macquarie": "<+11>-11",
|
||||
"Antarctica/Mawson": "<+05>-5",
|
||||
"Antarctica/McMurdo": "NZST-12NZDT,M9.5.0,M4.1.0/3",
|
||||
"Antarctica/Palmer": "<-03>3",
|
||||
"Antarctica/Rothera": "<-03>3",
|
||||
"Antarctica/Syowa": "<+03>-3",
|
||||
"Antarctica/Troll": "<+00>0<+02>-2,M3.5.0/1,M10.5.0/3",
|
||||
"Antarctica/Vostok": "<+06>-6",
|
||||
"Arctic/Longyearbyen": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Asia/Aden": "<+03>-3",
|
||||
"Asia/Almaty": "<+06>-6",
|
||||
"Asia/Amman": "EET-2EEST,M3.5.4/24,M10.5.5/1",
|
||||
"Asia/Anadyr": "<+12>-12",
|
||||
"Asia/Aqtau": "<+05>-5",
|
||||
"Asia/Aqtobe": "<+05>-5",
|
||||
"Asia/Ashgabat": "<+05>-5",
|
||||
"Asia/Atyrau": "<+05>-5",
|
||||
"Asia/Baghdad": "<+03>-3",
|
||||
"Asia/Bahrain": "<+03>-3",
|
||||
"Asia/Baku": "<+04>-4",
|
||||
"Asia/Bangkok": "<+07>-7",
|
||||
"Asia/Barnaul": "<+07>-7",
|
||||
"Asia/Beirut": "EET-2EEST,M3.5.0/0,M10.5.0/0",
|
||||
"Asia/Bishkek": "<+06>-6",
|
||||
"Asia/Brunei": "<+08>-8",
|
||||
"Asia/Chita": "<+09>-9",
|
||||
"Asia/Choibalsan": "<+08>-8",
|
||||
"Asia/Colombo": "<+0530>-5:30",
|
||||
"Asia/Damascus": "EET-2EEST,M3.5.5/0,M10.5.5/0",
|
||||
"Asia/Dhaka": "<+06>-6",
|
||||
"Asia/Dili": "<+09>-9",
|
||||
"Asia/Dubai": "<+04>-4",
|
||||
"Asia/Dushanbe": "<+05>-5",
|
||||
"Asia/Famagusta": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Asia/Gaza": "EET-2EEST,M3.5.5/0,M10.5.6/1",
|
||||
"Asia/Hebron": "EET-2EEST,M3.5.5/0,M10.5.6/1",
|
||||
"Asia/Ho_Chi_Minh": "<+07>-7",
|
||||
"Asia/Hong_Kong": "HKT-8",
|
||||
"Asia/Hovd": "<+07>-7",
|
||||
"Asia/Irkutsk": "<+08>-8",
|
||||
"Asia/Jakarta": "WIB-7",
|
||||
"Asia/Jayapura": "WIT-9",
|
||||
"Asia/Jerusalem": "IST-2IDT,M3.4.4/26,M10.5.0",
|
||||
"Asia/Kabul": "<+0430>-4:30",
|
||||
"Asia/Kamchatka": "<+12>-12",
|
||||
"Asia/Karachi": "PKT-5",
|
||||
"Asia/Kathmandu": "<+0545>-5:45",
|
||||
"Asia/Khandyga": "<+09>-9",
|
||||
"Asia/Kolkata": "IST-5:30",
|
||||
"Asia/Krasnoyarsk": "<+07>-7",
|
||||
"Asia/Kuala_Lumpur": "<+08>-8",
|
||||
"Asia/Kuching": "<+08>-8",
|
||||
"Asia/Kuwait": "<+03>-3",
|
||||
"Asia/Macau": "CST-8",
|
||||
"Asia/Magadan": "<+11>-11",
|
||||
"Asia/Makassar": "WITA-8",
|
||||
"Asia/Manila": "PST-8",
|
||||
"Asia/Muscat": "<+04>-4",
|
||||
"Asia/Nicosia": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Asia/Novokuznetsk": "<+07>-7",
|
||||
"Asia/Novosibirsk": "<+07>-7",
|
||||
"Asia/Omsk": "<+06>-6",
|
||||
"Asia/Oral": "<+05>-5",
|
||||
"Asia/Phnom_Penh": "<+07>-7",
|
||||
"Asia/Pontianak": "WIB-7",
|
||||
"Asia/Pyongyang": "KST-9",
|
||||
"Asia/Qatar": "<+03>-3",
|
||||
"Asia/Qyzylorda": "<+05>-5",
|
||||
"Asia/Riyadh": "<+03>-3",
|
||||
"Asia/Sakhalin": "<+11>-11",
|
||||
"Asia/Samarkand": "<+05>-5",
|
||||
"Asia/Seoul": "KST-9",
|
||||
"Asia/Shanghai": "CST-8",
|
||||
"Asia/Singapore": "<+08>-8",
|
||||
"Asia/Srednekolymsk": "<+11>-11",
|
||||
"Asia/Taipei": "CST-8",
|
||||
"Asia/Tashkent": "<+05>-5",
|
||||
"Asia/Tbilisi": "<+04>-4",
|
||||
"Asia/Tehran": "<+0330>-3:30<+0430>,J79/24,J263/24",
|
||||
"Asia/Thimphu": "<+06>-6",
|
||||
"Asia/Tokyo": "JST-9",
|
||||
"Asia/Tomsk": "<+07>-7",
|
||||
"Asia/Ulaanbaatar": "<+08>-8",
|
||||
"Asia/Urumqi": "<+06>-6",
|
||||
"Asia/Ust-Nera": "<+10>-10",
|
||||
"Asia/Vientiane": "<+07>-7",
|
||||
"Asia/Vladivostok": "<+10>-10",
|
||||
"Asia/Yakutsk": "<+09>-9",
|
||||
"Asia/Yangon": "<+0630>-6:30",
|
||||
"Asia/Yekaterinburg": "<+05>-5",
|
||||
"Asia/Yerevan": "<+04>-4",
|
||||
"Atlantic/Azores": "<-01>1<+00>,M3.5.0/0,M10.5.0/1",
|
||||
"Atlantic/Bermuda": "AST4ADT,M3.2.0,M11.1.0",
|
||||
"Atlantic/Canary": "WET0WEST,M3.5.0/1,M10.5.0",
|
||||
"Atlantic/Cape_Verde": "<-01>1",
|
||||
"Atlantic/Faroe": "WET0WEST,M3.5.0/1,M10.5.0",
|
||||
"Atlantic/Madeira": "WET0WEST,M3.5.0/1,M10.5.0",
|
||||
"Atlantic/Reykjavik": "GMT0",
|
||||
"Atlantic/South_Georgia": "<-02>2",
|
||||
"Atlantic/Stanley": "<-03>3",
|
||||
"Atlantic/St_Helena": "GMT0",
|
||||
"Australia/Adelaide": "ACST-9:30ACDT,M10.1.0,M4.1.0/3",
|
||||
"Australia/Brisbane": "AEST-10",
|
||||
"Australia/Broken_Hill": "ACST-9:30ACDT,M10.1.0,M4.1.0/3",
|
||||
"Australia/Currie": "AEST-10AEDT,M10.1.0,M4.1.0/3",
|
||||
"Australia/Darwin": "ACST-9:30",
|
||||
"Australia/Eucla": "<+0845>-8:45",
|
||||
"Australia/Hobart": "AEST-10AEDT,M10.1.0,M4.1.0/3",
|
||||
"Australia/Lindeman": "AEST-10",
|
||||
"Australia/Lord_Howe": "<+1030>-10:30<+11>-11,M10.1.0,M4.1.0",
|
||||
"Australia/Melbourne": "AEST-10AEDT,M10.1.0,M4.1.0/3",
|
||||
"Australia/Perth": "AWST-8",
|
||||
"Australia/Sydney": "AEST-10AEDT,M10.1.0,M4.1.0/3",
|
||||
"Europe/Amsterdam": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Andorra": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Astrakhan": "<+04>-4",
|
||||
"Europe/Athens": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Belgrade": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Berlin": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Bratislava": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Brussels": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Bucharest": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Budapest": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Busingen": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Chisinau": "EET-2EEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Copenhagen": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Dublin": "IST-1GMT0,M10.5.0,M3.5.0/1",
|
||||
"Europe/Gibraltar": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Guernsey": "GMT0BST,M3.5.0/1,M10.5.0",
|
||||
"Europe/Helsinki": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Isle_of_Man": "GMT0BST,M3.5.0/1,M10.5.0",
|
||||
"Europe/Istanbul": "<+03>-3",
|
||||
"Europe/Jersey": "GMT0BST,M3.5.0/1,M10.5.0",
|
||||
"Europe/Kaliningrad": "EET-2",
|
||||
"Europe/Kiev": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Kirov": "<+03>-3",
|
||||
"Europe/Lisbon": "WET0WEST,M3.5.0/1,M10.5.0",
|
||||
"Europe/Ljubljana": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/London": "GMT0BST,M3.5.0/1,M10.5.0",
|
||||
"Europe/Luxembourg": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Madrid": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Malta": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Mariehamn": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Minsk": "<+03>-3",
|
||||
"Europe/Monaco": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Moscow": "MSK-3",
|
||||
"Europe/Oslo": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Paris": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Podgorica": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Prague": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Riga": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Rome": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Samara": "<+04>-4",
|
||||
"Europe/San_Marino": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Sarajevo": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Saratov": "<+04>-4",
|
||||
"Europe/Simferopol": "MSK-3",
|
||||
"Europe/Skopje": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Sofia": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Stockholm": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Tallinn": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Tirane": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Ulyanovsk": "<+04>-4",
|
||||
"Europe/Uzhgorod": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Vaduz": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Vatican": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Vienna": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Vilnius": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Volgograd": "<+04>-4",
|
||||
"Europe/Warsaw": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Zagreb": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Europe/Zaporozhye": "EET-2EEST,M3.5.0/3,M10.5.0/4",
|
||||
"Europe/Zurich": "CET-1CEST,M3.5.0,M10.5.0/3",
|
||||
"Indian/Antananarivo": "EAT-3",
|
||||
"Indian/Chagos": "<+06>-6",
|
||||
"Indian/Christmas": "<+07>-7",
|
||||
"Indian/Cocos": "<+0630>-6:30",
|
||||
"Indian/Comoro": "EAT-3",
|
||||
"Indian/Kerguelen": "<+05>-5",
|
||||
"Indian/Mahe": "<+04>-4",
|
||||
"Indian/Maldives": "<+05>-5",
|
||||
"Indian/Mauritius": "<+04>-4",
|
||||
"Indian/Mayotte": "EAT-3",
|
||||
"Indian/Reunion": "<+04>-4",
|
||||
"Pacific/Apia": "<+13>-13<+14>,M9.5.0/3,M4.1.0/4",
|
||||
"Pacific/Auckland": "NZST-12NZDT,M9.5.0,M4.1.0/3",
|
||||
"Pacific/Bougainville": "<+11>-11",
|
||||
"Pacific/Chatham": "<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45",
|
||||
"Pacific/Chuuk": "<+10>-10",
|
||||
"Pacific/Easter": "<-06>6<-05>,M9.1.6/22,M4.1.6/22",
|
||||
"Pacific/Efate": "<+11>-11",
|
||||
"Pacific/Enderbury": "<+13>-13",
|
||||
"Pacific/Fakaofo": "<+13>-13",
|
||||
"Pacific/Fiji": "<+12>-12<+13>,M11.2.0,M1.2.3/99",
|
||||
"Pacific/Funafuti": "<+12>-12",
|
||||
"Pacific/Galapagos": "<-06>6",
|
||||
"Pacific/Gambier": "<-09>9",
|
||||
"Pacific/Guadalcanal": "<+11>-11",
|
||||
"Pacific/Guam": "ChST-10",
|
||||
"Pacific/Honolulu": "HST10",
|
||||
"Pacific/Kiritimati": "<+14>-14",
|
||||
"Pacific/Kosrae": "<+11>-11",
|
||||
"Pacific/Kwajalein": "<+12>-12",
|
||||
"Pacific/Majuro": "<+12>-12",
|
||||
"Pacific/Marquesas": "<-0930>9:30",
|
||||
"Pacific/Midway": "SST11",
|
||||
"Pacific/Nauru": "<+12>-12",
|
||||
"Pacific/Niue": "<-11>11",
|
||||
"Pacific/Norfolk": "<+11>-11<+12>,M10.1.0,M4.1.0/3",
|
||||
"Pacific/Noumea": "<+11>-11",
|
||||
"Pacific/Pago_Pago": "SST11",
|
||||
"Pacific/Palau": "<+09>-9",
|
||||
"Pacific/Pitcairn": "<-08>8",
|
||||
"Pacific/Pohnpei": "<+11>-11",
|
||||
"Pacific/Port_Moresby": "<+10>-10",
|
||||
"Pacific/Rarotonga": "<-10>10",
|
||||
"Pacific/Saipan": "ChST-10",
|
||||
"Pacific/Tahiti": "<-10>10",
|
||||
"Pacific/Tarawa": "<+12>-12",
|
||||
"Pacific/Tongatapu": "<+13>-13",
|
||||
"Pacific/Wake": "<+12>-12",
|
||||
"Pacific/Wallis": "<+12>-12",
|
||||
"Etc/GMT": "GMT0",
|
||||
"Etc/GMT-0": "GMT0",
|
||||
"Etc/GMT-1": "<+01>-1",
|
||||
"Etc/GMT-2": "<+02>-2",
|
||||
"Etc/GMT-3": "<+03>-3",
|
||||
"Etc/GMT-4": "<+04>-4",
|
||||
"Etc/GMT-5": "<+05>-5",
|
||||
"Etc/GMT-6": "<+06>-6",
|
||||
"Etc/GMT-7": "<+07>-7",
|
||||
"Etc/GMT-8": "<+08>-8",
|
||||
"Etc/GMT-9": "<+09>-9",
|
||||
"Etc/GMT-10": "<+10>-10",
|
||||
"Etc/GMT-11": "<+11>-11",
|
||||
"Etc/GMT-12": "<+12>-12",
|
||||
"Etc/GMT-13": "<+13>-13",
|
||||
"Etc/GMT-14": "<+14>-14",
|
||||
"Etc/GMT0": "GMT0",
|
||||
"Etc/GMT+0": "GMT0",
|
||||
"Etc/GMT+1": "<-01>1",
|
||||
"Etc/GMT+2": "<-02>2",
|
||||
"Etc/GMT+3": "<-03>3",
|
||||
"Etc/GMT+4": "<-04>4",
|
||||
"Etc/GMT+5": "<-05>5",
|
||||
"Etc/GMT+6": "<-06>6",
|
||||
"Etc/GMT+7": "<-07>7",
|
||||
"Etc/GMT+8": "<-08>8",
|
||||
"Etc/GMT+9": "<-09>9",
|
||||
"Etc/GMT+10": "<-10>10",
|
||||
"Etc/GMT+11": "<-11>11",
|
||||
"Etc/GMT+12": "<-12>12",
|
||||
"Etc/UCT": "UTC0",
|
||||
"Etc/UTC": "UTC0",
|
||||
"Etc/Greenwich": "GMT0",
|
||||
"Etc/Universal": "UTC0",
|
||||
"Etc/Zulu": "UTC0"
|
||||
}
|
||||
|
||||
export function selectedTimeZone(label, format){
|
||||
return TIME_ZONES[label] === format ? label : undefined;
|
||||
}
|
||||
|
||||
export function timeZoneSelectItems() {
|
||||
return Object.keys(TIME_ZONES).map(label => (
|
||||
<MenuItem value={label}>{label}</MenuItem>
|
||||
));
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import moment from 'moment';
|
||||
|
||||
export const TIME_AND_DATE = 'DD/MM/YYYY HH:mm:ss';
|
||||
export const unixTimeToTimeAndDate = unixTime => moment.unix(unixTime).format(TIME_AND_DATE);
|
||||
export const formatIsoDateTime = isoDateString => moment.parseZone(isoDateString).format('ll @ HH:mm:ss');
|
||||
|
@ -13,7 +13,7 @@ class NTPSettings extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fetched, errorMessage, data, saveData, loadData, handleValueChange } = this.props;
|
||||
const { fetched, errorMessage, data, saveData, setData, loadData, handleValueChange, handleCheckboxChange } = this.props;
|
||||
return (
|
||||
<SectionContent title="NTP Settings">
|
||||
<LoadingNotification
|
||||
@ -23,9 +23,11 @@ class NTPSettings extends Component {
|
||||
render={() =>
|
||||
<NTPSettingsForm
|
||||
ntpSettings={data}
|
||||
setData={setData}
|
||||
onSubmit={saveData}
|
||||
onReset={loadData}
|
||||
handleValueChange={handleValueChange}
|
||||
handleCheckboxChange={handleCheckboxChange}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
@ -8,17 +8,17 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
|
||||
import SwapVerticalCircleIcon from '@material-ui/icons/SwapVerticalCircle';
|
||||
import AccessTimeIcon from '@material-ui/icons/AccessTime';
|
||||
import DNSIcon from '@material-ui/icons/Dns';
|
||||
import TimerIcon from '@material-ui/icons/Timer';
|
||||
import UpdateIcon from '@material-ui/icons/Update';
|
||||
import AvTimerIcon from '@material-ui/icons/AvTimer';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
|
||||
import { isSynchronized, ntpStatusHighlight, ntpStatus } from '../constants/NTPStatus';
|
||||
import { isNtpActive, ntpStatusHighlight, ntpStatus } from '../constants/NTPStatus';
|
||||
import * as Highlight from '../constants/Highlight';
|
||||
import { unixTimeToTimeAndDate } from '../constants/TimeFormat';
|
||||
import { formatIsoDateTime } from '../constants/TimeFormat';
|
||||
import { NTP_STATUS_ENDPOINT } from '../constants/Endpoints';
|
||||
import { restComponent } from '../components/RestComponent';
|
||||
import LoadingNotification from '../components/LoadingNotification';
|
||||
@ -60,7 +60,8 @@ class NTPStatus extends Component {
|
||||
<ListItemText primary="Status" secondary={ntpStatus(data)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
{isSynchronized(data) &&
|
||||
{
|
||||
isNtpActive(data) && (
|
||||
<Fragment>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
@ -68,20 +69,20 @@ class NTPStatus extends Component {
|
||||
<AccessTimeIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="Time Now" secondary={unixTimeToTimeAndDate(data.now)} />
|
||||
<ListItemText primary="Local Time" secondary={formatIsoDateTime(data.time_local)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<SwapVerticalCircleIcon />
|
||||
<AccessTimeIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="Last Sync" secondary={data.last_sync > 0 ? unixTimeToTimeAndDate(data.last_sync) : "never"} />
|
||||
<ListItemText primary="UTC Time" secondary={formatIsoDateTime(data.time_utc)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</Fragment>
|
||||
}
|
||||
)}
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
@ -91,15 +92,6 @@ class NTPStatus extends Component {
|
||||
<ListItemText primary="NTP Server" secondary={data.server} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<TimerIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="Sync Interval" secondary={moment.duration(data.interval, 'seconds').humanize()} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
|
@ -1,16 +1,25 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator';
|
||||
import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator';
|
||||
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import SaveIcon from '@material-ui/icons/Save';
|
||||
|
||||
import isIP from '../validators/isIP';
|
||||
import isHostname from '../validators/isHostname';
|
||||
import or from '../validators/or';
|
||||
import { timeZoneSelectItems, selectedTimeZone, TIME_ZONES } from '../constants/TZ';
|
||||
|
||||
const styles = theme => ({
|
||||
switchControl: {
|
||||
width: "100%",
|
||||
marginTop: theme.spacing(2),
|
||||
marginBottom: theme.spacing(0.5)
|
||||
},
|
||||
textField: {
|
||||
width: "100%"
|
||||
},
|
||||
@ -26,10 +35,30 @@ class NTPSettingsForm extends React.Component {
|
||||
ValidatorForm.addValidationRule('isIPOrHostname', or(isIP, isHostname));
|
||||
}
|
||||
|
||||
changeTimeZone = (event) => {
|
||||
const { ntpSettings, setData } = this.props;
|
||||
setData({
|
||||
...ntpSettings,
|
||||
tz_label: event.target.value,
|
||||
tz_format: TIME_ZONES[event.target.value]
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, ntpSettings, handleValueChange, onSubmit, onReset } = this.props;
|
||||
const { classes, ntpSettings, handleValueChange, handleCheckboxChange, onSubmit, onReset } = this.props;
|
||||
return (
|
||||
<ValidatorForm onSubmit={onSubmit}>
|
||||
<FormControlLabel className={classes.switchControl}
|
||||
control={
|
||||
<Switch
|
||||
checked={ntpSettings.enabled}
|
||||
onChange={handleCheckboxChange('enabled')}
|
||||
value="enabled"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Enable NTP?"
|
||||
/>
|
||||
<TextValidator
|
||||
validators={['required', 'isIPOrHostname']}
|
||||
errorMessages={['Server is required', "Not a valid IP address or hostname"]}
|
||||
@ -40,17 +69,20 @@ class NTPSettingsForm extends React.Component {
|
||||
onChange={handleValueChange('server')}
|
||||
margin="normal"
|
||||
/>
|
||||
<TextValidator
|
||||
validators={['required', 'isNumber', 'minNumber:60', 'maxNumber:86400']}
|
||||
errorMessages={['Interval is required', 'Interval must be a number', 'Must be at least 60 seconds', "Must not be more than 86400 seconds (24 hours)"]}
|
||||
name="interval"
|
||||
label="Interval (Seconds)"
|
||||
<SelectValidator
|
||||
native
|
||||
validators={['required']}
|
||||
errorMessages={['Time zone is required']}
|
||||
labelId="tz_label"
|
||||
label="Time zone"
|
||||
value={selectedTimeZone(ntpSettings.tz_label, ntpSettings.tz_format)}
|
||||
onChange={this.changeTimeZone}
|
||||
className={classes.textField}
|
||||
value={ntpSettings.interval}
|
||||
type="number"
|
||||
onChange={handleValueChange('interval')}
|
||||
margin="normal"
|
||||
/>
|
||||
>
|
||||
<MenuItem disabled={true}>Time zone...</MenuItem>
|
||||
{timeZoneSelectItems()}
|
||||
</SelectValidator>
|
||||
<Button startIcon={<SaveIcon />} variant="contained" color="primary" className={classes.button} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
|
@ -14,10 +14,6 @@ NTPSettingsService::NTPSettingsService(AsyncWebServer* server, FS* fs, SecurityM
|
||||
_onStationModeGotIPHandler =
|
||||
WiFi.onStationModeGotIP(std::bind(&NTPSettingsService::onStationModeGotIP, this, std::placeholders::_1));
|
||||
#endif
|
||||
NTP.onNTPSyncEvent([this](NTPSyncEvent_t ntpEvent) {
|
||||
_ntpEvent = ntpEvent;
|
||||
_syncEventTriggered = true;
|
||||
});
|
||||
}
|
||||
|
||||
NTPSettingsService::~NTPSettingsService() {
|
||||
@ -29,38 +25,20 @@ void NTPSettingsService::loop() {
|
||||
_reconfigureNTP = false;
|
||||
configureNTP();
|
||||
}
|
||||
|
||||
// output sync event to serial
|
||||
if (_syncEventTriggered) {
|
||||
processSyncEvent(_ntpEvent);
|
||||
_syncEventTriggered = false;
|
||||
}
|
||||
|
||||
// keep time synchronized in background
|
||||
now();
|
||||
}
|
||||
|
||||
void NTPSettingsService::readFromJsonObject(JsonObject& root) {
|
||||
_enabled = root["enabled"] | NTP_SETTINGS_SERVICE_DEFAULT_ENABLED;
|
||||
_server = root["server"] | NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
||||
_interval = root["interval"];
|
||||
|
||||
// validate server is specified, resorting to default
|
||||
_server.trim();
|
||||
if (!_server) {
|
||||
_server = NTP_SETTINGS_SERVICE_DEFAULT_SERVER;
|
||||
}
|
||||
|
||||
// make sure interval is in bounds
|
||||
if (_interval < NTP_SETTINGS_MIN_INTERVAL) {
|
||||
_interval = NTP_SETTINGS_MIN_INTERVAL;
|
||||
} else if (_interval > NTP_SETTINGS_MAX_INTERVAL) {
|
||||
_interval = NTP_SETTINGS_MAX_INTERVAL;
|
||||
}
|
||||
_tzLabel = root["tz_label"] | NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_LABEL;
|
||||
_tzFormat = root["tz_format"] | NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_FORMAT;
|
||||
}
|
||||
|
||||
void NTPSettingsService::writeToJsonObject(JsonObject& root) {
|
||||
root["enabled"] = _enabled;
|
||||
root["server"] = _server;
|
||||
root["interval"] = _interval;
|
||||
root["tz_label"] = _tzLabel;
|
||||
root["tz_format"] = _tzFormat;
|
||||
}
|
||||
|
||||
void NTPSettingsService::onConfigUpdated() {
|
||||
@ -76,7 +54,7 @@ void NTPSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t i
|
||||
void NTPSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
Serial.printf("WiFi connection dropped, stopping NTP.\n");
|
||||
_reconfigureNTP = false;
|
||||
NTP.stop();
|
||||
sntp_stop();
|
||||
}
|
||||
#elif defined(ESP8266)
|
||||
void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) {
|
||||
@ -87,30 +65,19 @@ void NTPSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& eve
|
||||
void NTPSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) {
|
||||
Serial.printf("WiFi connection dropped, stopping NTP.\n");
|
||||
_reconfigureNTP = false;
|
||||
NTP.stop();
|
||||
sntp_stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
void NTPSettingsService::configureNTP() {
|
||||
Serial.println("Configuring NTP...");
|
||||
|
||||
// disable sync
|
||||
NTP.stop();
|
||||
|
||||
// enable sync
|
||||
NTP.begin(_server);
|
||||
NTP.setInterval(_interval);
|
||||
}
|
||||
|
||||
void NTPSettingsService::processSyncEvent(NTPSyncEvent_t ntpEvent) {
|
||||
if (ntpEvent) {
|
||||
Serial.print("Time Sync error: ");
|
||||
if (ntpEvent == noResponse)
|
||||
Serial.println("NTP server not reachable");
|
||||
else if (ntpEvent == invalidAddress)
|
||||
Serial.println("Invalid NTP server address");
|
||||
if (_enabled) {
|
||||
#ifdef ESP32
|
||||
configTzTime(_tzFormat.c_str(), _server.c_str());
|
||||
#elif defined(ESP8266)
|
||||
configTime(_tzFormat.c_str(), _server.c_str());
|
||||
#endif
|
||||
} else {
|
||||
Serial.print("Got NTP time: ");
|
||||
Serial.println(NTP.getTimeDateString(NTP.getLastNTPSync()));
|
||||
sntp_stop();
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,18 @@
|
||||
|
||||
#include <AdminSettingsService.h>
|
||||
|
||||
#include <NtpClientLib.h>
|
||||
#include <TimeLib.h>
|
||||
#include <time.h>
|
||||
#ifdef ESP32
|
||||
#include <lwip/apps/sntp.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <sntp.h>
|
||||
#endif
|
||||
|
||||
// default time server
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "pool.ntp.org"
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_INTERVAL 3600
|
||||
// default time zone
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_ENABLED true
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_LABEL "Europe/London"
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_TIME_ZONE_FORMAT "GMT0BST,M3.5.0/1,M10.5.0"
|
||||
#define NTP_SETTINGS_SERVICE_DEFAULT_SERVER "time.google.com"
|
||||
|
||||
// min poll delay of 60 secs, max 1 day
|
||||
#define NTP_SETTINGS_MIN_INTERVAL 60
|
||||
@ -28,14 +34,15 @@ class NTPSettingsService : public AdminSettingsService {
|
||||
void readFromJsonObject(JsonObject& root);
|
||||
void writeToJsonObject(JsonObject& root);
|
||||
void onConfigUpdated();
|
||||
void receivedNTPtime();
|
||||
|
||||
private:
|
||||
bool _enabled;
|
||||
String _tzLabel;
|
||||
String _tzFormat;
|
||||
String _server;
|
||||
int _interval;
|
||||
|
||||
bool _reconfigureNTP = false;
|
||||
bool _syncEventTriggered = false;
|
||||
NTPSyncEvent_t _ntpEvent;
|
||||
|
||||
#ifdef ESP32
|
||||
void onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
@ -49,7 +56,6 @@ class NTPSettingsService : public AdminSettingsService {
|
||||
#endif
|
||||
|
||||
void configureNTP();
|
||||
void processSyncEvent(NTPSyncEvent_t ntpEvent);
|
||||
};
|
||||
|
||||
#endif // end NTPSettingsService_h
|
||||
|
@ -7,24 +7,33 @@ NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
}
|
||||
|
||||
String toISOString(tm* time, bool incOffset) {
|
||||
char time_string[25];
|
||||
strftime(time_string, 25, incOffset ? "%FT%T%z" : "%FT%TZ", time);
|
||||
return String(time_string);
|
||||
}
|
||||
|
||||
void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// request time now first, this can sometimes force a sync
|
||||
time_t timeNow = now();
|
||||
timeStatus_t status = timeStatus();
|
||||
time_t lastSync = NTP.getLastNTPSync();
|
||||
root["status"] = (int)status;
|
||||
root["last_sync"] = lastSync;
|
||||
root["server"] = NTP.getNtpServerName();
|
||||
root["interval"] = NTP.getInterval();
|
||||
root["uptime"] = NTP.getUptime();
|
||||
// grab the current instant in unix seconds
|
||||
time_t now = time(nullptr);
|
||||
|
||||
// only add now to response if we have successfully synced
|
||||
if (status != timeNotSet) {
|
||||
root["now"] = timeNow;
|
||||
}
|
||||
// only provide enabled/disabled status for now
|
||||
root["status"] = sntp_enabled() ? 1 : 0;
|
||||
|
||||
// the current time in UTC
|
||||
root["time_utc"] = toISOString(gmtime(&now), false);
|
||||
|
||||
// local time as ISO String with TZ
|
||||
root["time_local"] = toISOString(localtime(&now), true);
|
||||
|
||||
// the sntp server name
|
||||
root["server"] = sntp_getservername(0);
|
||||
|
||||
// device uptime in seconds
|
||||
root["uptime"] = millis() / 1000;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
@ -1,20 +1,21 @@
|
||||
#ifndef NTPStatus_h
|
||||
#define NTPStatus_h
|
||||
|
||||
#include <time.h>
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#include <sntp.h>
|
||||
#endif
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <AsyncJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <NtpClientLib.h>
|
||||
#include <SecurityManager.h>
|
||||
#include <TimeLib.h>
|
||||
|
||||
#define MAX_NTP_STATUS_SIZE 1024
|
||||
#define NTP_STATUS_SERVICE_PATH "/rest/ntpStatus"
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <AsyncJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <SecurityManager.h>
|
||||
#include <TimeLib.h>
|
||||
|
||||
#define SCAN_NETWORKS_SERVICE_PATH "/rest/scanNetworks"
|
||||
#define LIST_NETWORKS_SERVICE_PATH "/rest/listNetworks"
|
||||
|
@ -21,11 +21,9 @@ framework = arduino
|
||||
monitor_speed = 115200
|
||||
|
||||
extra_scripts =
|
||||
pre:scripts/timelib_fix.py
|
||||
pre:scripts/build_interface.py
|
||||
|
||||
lib_deps =
|
||||
NtpClientLib@>=2.5.1,<3.0.0
|
||||
ArduinoJson@>=6.0.0,<7.0.0
|
||||
ESP Async WebServer@>=1.2.0,<2.0.0
|
||||
|
||||
|
@ -32,5 +32,3 @@ if (len(BUILD_TARGETS) == 0 or "upload" in BUILD_TARGETS):
|
||||
buildWeb()
|
||||
else:
|
||||
print("Skipping build interface step for target(s): " + ", ".join(BUILD_TARGETS))
|
||||
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
Import("env")
|
||||
|
||||
# Find files under 'root' of a given 'fileName' in directories matching 'subDirectoryPattern'
|
||||
# This will allow us to safely find the offending Time.h file for removal prior to building
|
||||
def findSubDirectoryFiles(root, subDirectoryPattern, fileName):
|
||||
subDirectories = os.listdir(root)
|
||||
subDirectories = filter(lambda d: re.match(subDirectoryPattern, d), subDirectories)
|
||||
result = []
|
||||
for subDirectory in subDirectories:
|
||||
candidateFile = os.path.join(root, subDirectory, fileName)
|
||||
if os.path.isfile(candidateFile):
|
||||
result.append(candidateFile)
|
||||
return result
|
||||
|
||||
def deleteTimeHeader(libDepsDir):
|
||||
timeHeaderFile = "Time.h"
|
||||
timeLibDirectoryPattern = "Time(_ID[0-9]+)?"
|
||||
|
||||
# delete the file, as long as we only find one
|
||||
if os.path.isdir(libDepsDir) :
|
||||
deletionCandidates = findSubDirectoryFiles(libDepsDir, timeLibDirectoryPattern, timeHeaderFile)
|
||||
numDeletionCandidates = len(deletionCandidates)
|
||||
if numDeletionCandidates == 1:
|
||||
os.remove(deletionCandidates[0])
|
||||
elif numDeletionCandidates > 1:
|
||||
os.write(2, "Can\'t delete Time.h, more than one instance found:\n" + "\n".join(deletionCandidates))
|
||||
sys.exit(1)
|
||||
|
||||
# old lib deps directory
|
||||
deleteTimeHeader(os.path.join(env.subst("$PROJECT_DIR"), ".piolibdeps"))
|
||||
|
||||
# pre 4.x lib deps directory
|
||||
deleteTimeHeader(os.path.join(env.subst("$PROJECTLIBDEPS_DIR"), env.subst("$PIOENV")))
|
||||
|
||||
# >4.x lib deps directory
|
||||
deleteTimeHeader(os.path.join(env.subst("$PROJECT_LIBDEPS_DIR"), env.subst("$PIOENV")))
|
Loading…
Reference in New Issue
Block a user