Adicionar primeiro
This commit is contained in:
136
components/protocols/src/date_time.c
Executable file
136
components/protocols/src/date_time.c
Executable file
@@ -0,0 +1,136 @@
|
||||
|
||||
#include <time.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_sntp.h"
|
||||
#include "esp_netif_sntp.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include "date_time.h"
|
||||
|
||||
#define NVS_NAMESPACE "date_time"
|
||||
#define NVS_NTP_ENABLED "ntp_en"
|
||||
#define NVS_NTP_SERVER "ntp_server"
|
||||
#define NVS_NTP_FROM_DHCP "ntp_from_dhcp"
|
||||
#define NVS_TIMEZONE "timezone"
|
||||
|
||||
static const char* TAG = "date_time";
|
||||
|
||||
static nvs_handle nvs;
|
||||
|
||||
static char ntp_server[64]; // if renew_servers_after_new_IP = false, will be used static string reference
|
||||
|
||||
static const char* tz_data[][2] = {
|
||||
#include "tz_data.h"
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const char* find_tz(const char* name)
|
||||
{
|
||||
if (name != NULL) {
|
||||
int index = 0;
|
||||
while (true) {
|
||||
if (tz_data[index][0] == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(tz_data[index][0], name) == 0) {
|
||||
return tz_data[index][1];
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void date_time_init(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
||||
|
||||
if (date_time_is_ntp_enabled()) {
|
||||
date_time_get_ntp_server(ntp_server);
|
||||
|
||||
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(ntp_server);
|
||||
|
||||
esp_err_t ret = esp_netif_sntp_init(&config);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "SNTP init return %s", esp_err_to_name(ret));
|
||||
}
|
||||
}
|
||||
|
||||
char str[64];
|
||||
date_time_get_timezone(str);
|
||||
const char *tz = find_tz(str);
|
||||
if (tz) {
|
||||
setenv("TZ", tz, 1);
|
||||
tzset();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown timezone %s", str);
|
||||
}
|
||||
}
|
||||
|
||||
bool date_time_is_ntp_enabled(void)
|
||||
{
|
||||
uint8_t value = false;
|
||||
nvs_get_u8(nvs, NVS_NTP_ENABLED, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void date_time_get_ntp_server(char* value)
|
||||
{
|
||||
size_t len = 64;
|
||||
value[0] = '\0';
|
||||
nvs_get_str(nvs, NVS_NTP_SERVER, value, &len);
|
||||
}
|
||||
|
||||
bool date_time_is_ntp_from_dhcp(void)
|
||||
{
|
||||
uint8_t value = false;
|
||||
nvs_get_u8(nvs, NVS_NTP_FROM_DHCP, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
esp_err_t date_time_set_ntp_config(bool enabled, const char* server, bool from_dhcp)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
esp_netif_sntp_deinit();
|
||||
if (enabled) {
|
||||
strcpy(ntp_server, server);
|
||||
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(ntp_server);
|
||||
config.renew_servers_after_new_IP = from_dhcp;
|
||||
ret = esp_netif_sntp_init(&config);
|
||||
}
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
nvs_set_u8(nvs, NVS_NTP_ENABLED, enabled);
|
||||
nvs_set_str(nvs, NVS_NTP_SERVER, server);
|
||||
nvs_set_u8(nvs, NVS_NTP_FROM_DHCP, from_dhcp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void date_time_get_timezone(char* value)
|
||||
{
|
||||
size_t len = 64;
|
||||
value[0] = '\0';
|
||||
strcpy(value, "Etc/UTC");
|
||||
nvs_get_str(nvs, NVS_TIMEZONE, value, &len);
|
||||
}
|
||||
|
||||
esp_err_t date_time_set_timezone(const char* value)
|
||||
{
|
||||
const char* tz = find_tz(value);
|
||||
|
||||
if (tz) {
|
||||
setenv("TZ", tz, 1);
|
||||
tzset();
|
||||
|
||||
nvs_set_str(nvs, NVS_TIMEZONE, value);
|
||||
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown timezone %s", value);
|
||||
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
340
components/protocols/src/mqtt.c
Executable file
340
components/protocols/src/mqtt.c
Executable file
@@ -0,0 +1,340 @@
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_event.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include "mqtt.h"
|
||||
#include "json.h"
|
||||
#include "board_config.h"
|
||||
#include "timeout_utils.h"
|
||||
|
||||
#define NVS_NAMESPACE "mqtt"
|
||||
#define NVS_ENABLED "enabled"
|
||||
#define NVS_SERVER "server"
|
||||
#define NVS_BASE_TOPIC "base_topic"
|
||||
#define NVS_USER "user"
|
||||
#define NVS_PASSWORD "password"
|
||||
#define NVS_PERIODICITY "periodicity"
|
||||
|
||||
static const char* TAG = "mqtt";
|
||||
|
||||
static nvs_handle nvs;
|
||||
|
||||
static TaskHandle_t client_task = NULL;
|
||||
|
||||
static esp_mqtt_client_handle_t client = NULL;
|
||||
|
||||
static uint16_t periodicity = 30;
|
||||
|
||||
static void subcribe_topics(void)
|
||||
{
|
||||
|
||||
ESP_LOGI(TAG, "subcribe_topics");
|
||||
|
||||
char topic[48];
|
||||
|
||||
mqtt_get_base_topic(topic);
|
||||
strcat(topic, "/request/#");
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
|
||||
ESP_LOGI(TAG, "data: %s", topic);
|
||||
|
||||
mqtt_get_base_topic(topic);
|
||||
strcat(topic, "/set/config/#");
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
|
||||
ESP_LOGI(TAG, "data: %s", topic);
|
||||
|
||||
mqtt_get_base_topic(topic);
|
||||
strcat(topic, "/enable");
|
||||
esp_mqtt_client_subscribe(client, topic, 0);
|
||||
|
||||
ESP_LOGI(TAG, "data: %s", topic);
|
||||
}
|
||||
|
||||
static void publish_message(const char* topic, cJSON* root)
|
||||
{
|
||||
ESP_LOGI(TAG, "publish_message");
|
||||
|
||||
char target_topic[48];
|
||||
|
||||
mqtt_get_base_topic(target_topic);
|
||||
strcat(target_topic, topic);
|
||||
|
||||
const char* json = cJSON_PrintUnformatted(root);
|
||||
esp_mqtt_client_publish(client, target_topic, json, 0, 1, 0);
|
||||
free((void*)json);
|
||||
}
|
||||
|
||||
static void handle_message(const char* topic, const char* data)
|
||||
{
|
||||
char base_topic[32];
|
||||
mqtt_get_base_topic(base_topic);
|
||||
|
||||
ESP_LOGI(TAG, "Topic: %s", topic);
|
||||
ESP_LOGI(TAG, "data: %s", data);
|
||||
ESP_LOGI(TAG, "base_topic: %s", base_topic);
|
||||
|
||||
if (strncmp(topic, base_topic, strlen(base_topic)) == 0) {
|
||||
const char* sub_topic = &topic[strlen(base_topic)];
|
||||
|
||||
ESP_LOGI(TAG, "Sub_topic: %s", sub_topic);
|
||||
|
||||
if (strcmp(sub_topic, "/request/config/evse") == 0) {
|
||||
cJSON* root = json_get_evse_config();
|
||||
publish_message("/response/config/evse", root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/request/config/wifi") == 0) {
|
||||
cJSON* root = json_get_wifi_config();
|
||||
publish_message("/response/config/wifi", root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/request/config/mqtt") == 0) {
|
||||
cJSON* root = json_get_mqtt_config();
|
||||
publish_message("/response/config/mqtt", root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/request/boardConfig") == 0) {
|
||||
cJSON* root = json_get_board_config();
|
||||
publish_message("/response/boardConfig", root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/request/info") == 0) {
|
||||
cJSON* root = json_get_info();
|
||||
publish_message("/response/info", root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/request/restart") == 0) {
|
||||
timeout_restart();
|
||||
} else if (strcmp(sub_topic, "/set/config/evse") == 0) {
|
||||
cJSON* root = cJSON_Parse(data);
|
||||
json_set_evse_config(root);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/set/config/wifi") == 0) {
|
||||
cJSON* root = cJSON_Parse(data);
|
||||
json_set_wifi_config(root, true);
|
||||
cJSON_Delete(root);
|
||||
} else if (strcmp(sub_topic, "/set/config/mqtt") == 0) {
|
||||
cJSON* root = cJSON_Parse(data);
|
||||
json_set_mqtt_config(root);
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handler(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data)
|
||||
{
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
char topic[48];
|
||||
char data[256];
|
||||
|
||||
ESP_LOGI(TAG, "Handle Data 1");
|
||||
|
||||
switch (event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "Connected");
|
||||
vTaskResume(client_task);
|
||||
subcribe_topics();
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Disconnected");
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "Handle Data 2");
|
||||
memset(topic, 0, sizeof(topic));
|
||||
strncpy(topic, event->topic, MIN(event->topic_len, sizeof(topic) - 1));
|
||||
memset(data, 0, sizeof(data));
|
||||
strncpy(data, event->data, MIN(event->data_len, sizeof(data) - 1));
|
||||
handle_message(topic, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void client_task_func(void* param)
|
||||
{
|
||||
while (true) {
|
||||
if (!client) {
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
cJSON* root = json_get_state();
|
||||
publish_message("/state", root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(periodicity * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
static void client_start(void)
|
||||
{
|
||||
char server[64];
|
||||
char user[32];
|
||||
char password[64];
|
||||
|
||||
mqtt_get_server(server);
|
||||
mqtt_get_user(user);
|
||||
mqtt_get_password(password);
|
||||
|
||||
ESP_LOGI(TAG, "Client Start");
|
||||
|
||||
esp_mqtt_client_config_t cfg = {
|
||||
.broker.address.uri = server,
|
||||
.credentials.username = user,
|
||||
.credentials.authentication.password = password
|
||||
};
|
||||
|
||||
if (client) {
|
||||
if (esp_mqtt_set_config(client, &cfg) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Cant set config");
|
||||
}
|
||||
} else {
|
||||
client = esp_mqtt_client_init(&cfg);
|
||||
if (esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, event_handler, client) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Cant register handler");
|
||||
}
|
||||
if (client == NULL) {
|
||||
ESP_LOGW(TAG, "Cant set config");
|
||||
} else {
|
||||
if (esp_mqtt_client_start(client) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Cant start");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void client_stop(void)
|
||||
{
|
||||
if (client != NULL) {
|
||||
esp_mqtt_client_destroy(client);
|
||||
client = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_init(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
||||
|
||||
nvs_get_u16(nvs, NVS_PERIODICITY, &periodicity);
|
||||
|
||||
esp_register_shutdown_handler(&client_stop);
|
||||
|
||||
xTaskCreate(client_task_func, "mqtt_client_task", 3 * 1024, NULL, 5, &client_task);
|
||||
|
||||
if (mqtt_get_enabled()) {
|
||||
client_start();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t mqtt_set_config(bool enabled, const char* server, const char* base_topic, const char* user, const char* password, uint16_t _periodicity)
|
||||
{
|
||||
if (enabled) {
|
||||
if (server == NULL || strlen(server) == 0) {
|
||||
size_t len = 0;
|
||||
nvs_get_str(nvs, NVS_SERVER, NULL, &len);
|
||||
if (len <= 1) {
|
||||
ESP_LOGE(TAG, "Required server");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_topic == NULL || strlen(base_topic) == 0) {
|
||||
size_t len = 0;
|
||||
nvs_get_str(nvs, NVS_BASE_TOPIC, NULL, &len);
|
||||
if (len <= 1) {
|
||||
ESP_LOGE(TAG, "Required base topic");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (_periodicity == 0) {
|
||||
ESP_LOGE(TAG, "Periodicity muse be larger than zero");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (server != NULL && strlen(server) > 63) {
|
||||
ESP_LOGE(TAG, "Server out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (base_topic != NULL && strlen(base_topic) > 31) {
|
||||
ESP_LOGE(TAG, "Base topic out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (user != NULL && strlen(user) > 31) {
|
||||
ESP_LOGE(TAG, "User out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (password != NULL && strlen(password) > 63) {
|
||||
ESP_LOGE(TAG, "Password out of range");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nvs_set_u8(nvs, NVS_ENABLED, enabled);
|
||||
|
||||
nvs_set_str(nvs, NVS_SERVER, server);
|
||||
|
||||
nvs_set_str(nvs, NVS_BASE_TOPIC, base_topic);
|
||||
|
||||
nvs_set_str(nvs, NVS_USER, user);
|
||||
|
||||
nvs_set_str(nvs, NVS_PASSWORD, password);
|
||||
|
||||
nvs_set_u16(nvs, NVS_PERIODICITY, _periodicity);
|
||||
periodicity = _periodicity;
|
||||
|
||||
nvs_commit(nvs);
|
||||
|
||||
if (enabled) {
|
||||
client_start();
|
||||
} else {
|
||||
client_stop();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool mqtt_get_enabled(void)
|
||||
{
|
||||
uint8_t value = false;
|
||||
nvs_get_u8(nvs, NVS_ENABLED, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void mqtt_get_server(char* value)
|
||||
{
|
||||
size_t len = 64;
|
||||
value[0] = '\0';
|
||||
nvs_get_str(nvs, NVS_SERVER, value, &len);
|
||||
}
|
||||
|
||||
void mqtt_get_base_topic(char* value)
|
||||
{
|
||||
size_t len = 32;
|
||||
value[0] = '\0';
|
||||
nvs_get_str(nvs, NVS_BASE_TOPIC, value, &len);
|
||||
}
|
||||
|
||||
void mqtt_get_user(char* value)
|
||||
{
|
||||
size_t len = 32;
|
||||
value[0] = '\0';
|
||||
nvs_get_str(nvs, NVS_USER, value, &len);
|
||||
}
|
||||
|
||||
void mqtt_get_password(char* value)
|
||||
{
|
||||
size_t len = 64;
|
||||
value[0] = '\0';
|
||||
nvs_get_str(nvs, NVS_PASSWORD, value, &len);
|
||||
}
|
||||
|
||||
uint16_t mqtt_get_periodicity(void)
|
||||
{
|
||||
return periodicity;
|
||||
}
|
||||
13
components/protocols/src/protocols.c
Executable file
13
components/protocols/src/protocols.c
Executable file
@@ -0,0 +1,13 @@
|
||||
#include "protocols.h"
|
||||
#include "date_time.h"
|
||||
#include "rest.h"
|
||||
#include "mqtt.h"
|
||||
//#include "modbus_tcp.h"
|
||||
|
||||
void protocols_init(void)
|
||||
{
|
||||
date_time_init();
|
||||
rest_init();
|
||||
//mqtt_init();
|
||||
//modbus_tcp_init();
|
||||
}
|
||||
226
components/protocols/src/rest.c
Executable file
226
components/protocols/src/rest.c
Executable file
@@ -0,0 +1,226 @@
|
||||
/* HTTP Restful API Server
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_chip_info.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *REST_TAG = "esp-rest";
|
||||
#define REST_CHECK(a, str, goto_tag, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(REST_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILE_PATH_MAX (ESP_VFS_PATH_MAX + 128)
|
||||
#define SCRATCH_BUFSIZE (10240)
|
||||
|
||||
typedef struct rest_server_context {
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
} rest_server_context_t;
|
||||
|
||||
#define CHECK_FILE_EXTENSION(filename, ext) (strcasecmp(&filename[strlen(filename) - strlen(ext)], ext) == 0)
|
||||
|
||||
/* Set HTTP response content type according to file extension */
|
||||
static esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filepath)
|
||||
{
|
||||
const char *type = "text/plain";
|
||||
if (CHECK_FILE_EXTENSION(filepath, ".html")) {
|
||||
type = "text/html";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".js")) {
|
||||
type = "application/javascript";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".css")) {
|
||||
type = "text/css";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".png")) {
|
||||
type = "image/png";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".ico")) {
|
||||
type = "image/x-icon";
|
||||
} else if (CHECK_FILE_EXTENSION(filepath, ".svg")) {
|
||||
type = "text/xml";
|
||||
}
|
||||
return httpd_resp_set_type(req, type);
|
||||
}
|
||||
|
||||
/* Send HTTP response with the contents of the requested file */
|
||||
static esp_err_t rest_common_get_handler(httpd_req_t *req)
|
||||
{
|
||||
char filepath[FILE_PATH_MAX];
|
||||
|
||||
rest_server_context_t *rest_context = (rest_server_context_t *)req->user_ctx;
|
||||
strlcpy(filepath, rest_context->base_path, sizeof(filepath));
|
||||
if (req->uri[strlen(req->uri) - 1] == '/') {
|
||||
strlcat(filepath, "/index.html", sizeof(filepath));
|
||||
} else {
|
||||
strlcat(filepath, req->uri, sizeof(filepath));
|
||||
}
|
||||
int fd = open(filepath, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
ESP_LOGE(REST_TAG, "Failed to open file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
set_content_type_from_file(req, filepath);
|
||||
|
||||
char *chunk = rest_context->scratch;
|
||||
ssize_t read_bytes;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
read_bytes = read(fd, chunk, SCRATCH_BUFSIZE);
|
||||
if (read_bytes == -1) {
|
||||
ESP_LOGE(REST_TAG, "Failed to read file : %s", filepath);
|
||||
} else if (read_bytes > 0) {
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, read_bytes) != ESP_OK) {
|
||||
close(fd);
|
||||
ESP_LOGE(REST_TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
} while (read_bytes > 0);
|
||||
/* Close file after sending complete */
|
||||
close(fd);
|
||||
ESP_LOGI(REST_TAG, "File sending complete");
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Simple handler for light brightness control */
|
||||
static esp_err_t light_brightness_post_handler(httpd_req_t *req)
|
||||
{
|
||||
int total_len = req->content_len;
|
||||
int cur_len = 0;
|
||||
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
|
||||
int received = 0;
|
||||
if (total_len >= SCRATCH_BUFSIZE) {
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
while (cur_len < total_len) {
|
||||
received = httpd_req_recv(req, buf + cur_len, total_len);
|
||||
if (received <= 0) {
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
cur_len += received;
|
||||
}
|
||||
buf[total_len] = '\0';
|
||||
|
||||
cJSON *root = cJSON_Parse(buf);
|
||||
int red = cJSON_GetObjectItem(root, "red")->valueint;
|
||||
int green = cJSON_GetObjectItem(root, "green")->valueint;
|
||||
int blue = cJSON_GetObjectItem(root, "blue")->valueint;
|
||||
ESP_LOGI(REST_TAG, "Light control: red = %d, green = %d, blue = %d", red, green, blue);
|
||||
cJSON_Delete(root);
|
||||
httpd_resp_sendstr(req, "Post control value successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Simple handler for getting system handler */
|
||||
static esp_err_t system_info_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
cJSON_AddStringToObject(root, "version", IDF_VER);
|
||||
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
|
||||
const char *sys_info = cJSON_Print(root);
|
||||
httpd_resp_sendstr(req, sys_info);
|
||||
free((void *)sys_info);
|
||||
cJSON_Delete(root);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Simple handler for getting temperature data */
|
||||
static esp_err_t temperature_data_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(root, "raw", esp_random() % 20);
|
||||
const char *sys_info = cJSON_Print(root);
|
||||
httpd_resp_sendstr(req, sys_info);
|
||||
free((void *)sys_info);
|
||||
cJSON_Delete(root);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rest_init(const char *base_path)
|
||||
{
|
||||
REST_CHECK(base_path, "wrong base path", err);
|
||||
rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));
|
||||
REST_CHECK(rest_context, "No memory for rest context", err);
|
||||
strlcpy(rest_context->base_path, base_path, sizeof(rest_context->base_path));
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
|
||||
ESP_LOGI(REST_TAG, "Starting HTTP Server");
|
||||
REST_CHECK(httpd_start(&server, &config) == ESP_OK, "Start server failed", err_start);
|
||||
|
||||
/* URI handler for fetching system info */
|
||||
httpd_uri_t system_info_get_uri = {
|
||||
.uri = "/api/v1/system/info",
|
||||
.method = HTTP_GET,
|
||||
.handler = system_info_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &system_info_get_uri);
|
||||
|
||||
/* URI handler for fetching temperature data */
|
||||
httpd_uri_t temperature_data_get_uri = {
|
||||
.uri = "/api/v1/temp/raw",
|
||||
.method = HTTP_GET,
|
||||
.handler = temperature_data_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &temperature_data_get_uri);
|
||||
|
||||
/* URI handler for light brightness control */
|
||||
httpd_uri_t light_brightness_post_uri = {
|
||||
.uri = "/api/v1/light/brightness",
|
||||
.method = HTTP_POST,
|
||||
.handler = light_brightness_post_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &light_brightness_post_uri);
|
||||
|
||||
/* URI handler for getting web server files */
|
||||
httpd_uri_t common_get_uri = {
|
||||
.uri = "/*",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_common_get_handler,
|
||||
.user_ctx = rest_context
|
||||
};
|
||||
httpd_register_uri_handler(server, &common_get_uri);
|
||||
|
||||
return ESP_OK;
|
||||
err_start:
|
||||
free(rest_context);
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
354
components/protocols/src/tz_data.h
Executable file
354
components/protocols/src/tz_data.h
Executable file
@@ -0,0 +1,354 @@
|
||||
{"Africa/Abidjan", "GMT0"},
|
||||
{"Africa/Algiers", "CET-1"},
|
||||
{"Africa/Bissau", "GMT0"},
|
||||
{"Africa/Cairo", "EET-2EEST,M4.5.5/0,M10.5.4/24"},
|
||||
{"Africa/Casablanca", "<+01>-1"},
|
||||
{"Africa/Ceuta", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Africa/El_Aaiun", "<+01>-1"},
|
||||
{"Africa/Johannesburg", "SAST-2"},
|
||||
{"Africa/Juba", "CAT-2"},
|
||||
{"Africa/Khartoum", "CAT-2"},
|
||||
{"Africa/Lagos", "WAT-1"},
|
||||
{"Africa/Maputo", "CAT-2"},
|
||||
{"Africa/Monrovia", "GMT0"},
|
||||
{"Africa/Nairobi", "EAT-3"},
|
||||
{"Africa/Ndjamena", "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/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/Asuncion", "<-04>4<-03>,M10.1.0/0,M3.4.0/0"},
|
||||
{"America/Bahia", "<-03>3"},
|
||||
{"America/Bahia_Banderas", "CST6"},
|
||||
{"America/Barbados", "AST4"},
|
||||
{"America/Belem", "<-03>3"},
|
||||
{"America/Belize", "CST6"},
|
||||
{"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", "CST6"},
|
||||
{"America/Costa_Rica", "CST6"},
|
||||
{"America/Creston", "MST7"},
|
||||
{"America/Cuiaba", "<-04>4"},
|
||||
{"America/Curacao", "AST4"},
|
||||
{"America/Danmarkshavn", "GMT0"},
|
||||
{"America/Dawson", "MST7"},
|
||||
{"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", "<-02>2<-01>,M3.5.0/-1,M10.5.0/0"},
|
||||
{"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/La_Paz", "<-04>4"},
|
||||
{"America/Lima", "<-05>5"},
|
||||
{"America/Los_Angeles", "PST8PDT,M3.2.0,M11.1.0"},
|
||||
{"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", "MST7"},
|
||||
{"America/Menominee", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Merida", "CST6"},
|
||||
{"America/Metlakatla", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Mexico_City", "CST6"},
|
||||
{"America/Miquelon", "<-03>3<-02>,M3.2.0,M11.1.0"},
|
||||
{"America/Moncton", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Monterrey", "CST6"},
|
||||
{"America/Montevideo", "<-03>3"},
|
||||
{"America/New_York", "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/Nuuk", "<-02>2<-01>,M3.5.0/-1,M10.5.0/0"},
|
||||
{"America/Ojinaga", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Panama", "EST5"},
|
||||
{"America/Paramaribo", "<-03>3"},
|
||||
{"America/Phoenix", "MST7"},
|
||||
{"America/Port-au-Prince", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Porto_Velho", "<-04>4"},
|
||||
{"America/Puerto_Rico", "AST4"},
|
||||
{"America/Punta_Arenas", "<-03>3"},
|
||||
{"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_Johns", "NST3:30NDT,M3.2.0,M11.1.0"},
|
||||
{"America/Swift_Current", "CST6"},
|
||||
{"America/Tegucigalpa", "CST6"},
|
||||
{"America/Thule", "AST4ADT,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/Vancouver", "PST8PDT,M3.2.0,M11.1.0"},
|
||||
{"America/Whitehorse", "MST7"},
|
||||
{"America/Winnipeg", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Yakutat", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"Antarctica/Casey", "<+11>-11"},
|
||||
{"Antarctica/Davis", "<+07>-7"},
|
||||
{"Antarctica/Macquarie", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Antarctica/Mawson", "<+05>-5"},
|
||||
{"Antarctica/Palmer", "<-03>3"},
|
||||
{"Antarctica/Rothera", "<-03>3"},
|
||||
{"Antarctica/Troll", "<+00>0<+02>-2,M3.5.0/1,M10.5.0/3"},
|
||||
{"Asia/Almaty", "<+06>-6"},
|
||||
{"Asia/Amman", "<+03>-3"},
|
||||
{"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", "<+03>-3"},
|
||||
{"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.4.4/50,M10.4.4/50"},
|
||||
{"Asia/Hebron", "EET-2EEST,M3.4.4/50,M10.4.4/50"},
|
||||
{"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/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/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"},
|
||||
{"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/South_Georgia", "<-02>2"},
|
||||
{"Atlantic/Stanley", "<-03>3"},
|
||||
{"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/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/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/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/Chisinau", "EET-2EEST,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/Helsinki", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Istanbul", "<+03>-3"},
|
||||
{"Europe/Kaliningrad", "EET-2"},
|
||||
{"Europe/Kyiv", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Kirov", "MSK-3"},
|
||||
{"Europe/Lisbon", "WET0WEST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/London", "GMT0BST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Madrid", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Malta", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Minsk", "<+03>-3"},
|
||||
{"Europe/Moscow", "MSK-3"},
|
||||
{"Europe/Paris", "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/Saratov", "<+04>-4"},
|
||||
{"Europe/Simferopol", "MSK-3"},
|
||||
{"Europe/Sofia", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"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/Vienna", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Vilnius", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Volgograd", "MSK-3"},
|
||||
{"Europe/Warsaw", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Zurich", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Indian/Chagos", "<+06>-6"},
|
||||
{"Indian/Maldives", "<+05>-5"},
|
||||
{"Indian/Mauritius", "<+04>-4"},
|
||||
{"Pacific/Apia", "<+13>-13"},
|
||||
{"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"},
|
||||
{"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/Port_Moresby", "<+10>-10"},
|
||||
{"Pacific/Rarotonga", "<-10>10"},
|
||||
{"Pacific/Tahiti", "<-10>10"},
|
||||
{"Pacific/Tarawa", "<+12>-12"},
|
||||
{"Pacific/Tongatapu", "<+13>-13"},
|
||||
{"Etc/GMT", "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/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/UTC", "UTC0"},
|
||||
Reference in New Issue
Block a user