Merge pull request #73 from susisstrolch/syslog

Thank you!
pull/91/head
Thorsten von Eicken 9 years ago
commit 91b35f3488
  1. 1
      .gitignore
  2. 40
      Makefile
  3. 40
      esp-link/config.c
  4. 6
      esp-link/config.h
  5. 64
      esp-link/main.c
  6. 78
      esp-link/task.c
  7. 20
      esp-link/task.h
  8. BIN
      html/favicon.ico
  9. 16
      html/home.html
  10. 11
      include/espmissingincludes.h
  11. 4
      serial/serbridge.c
  12. 11
      serial/uart.c
  13. 392
      syslog/syslog.c
  14. 110
      syslog/syslog.h

1
.gitignore vendored

@ -16,4 +16,5 @@ esp-link.sdf
espfs/mkespfsimage/mman-win32/libmman.a espfs/mkespfsimage/mman-win32/libmman.a
.localhistory/ .localhistory/
tools/ tools/
local.conf
*.tgz *.tgz

@ -8,10 +8,12 @@
# `VERBOSE=1 make ...` will print debug info # `VERBOSE=1 make ...` will print debug info
# `ESP_HOSTNAME=my.esp.example.com make wiflash` is an easy way to override a variable # `ESP_HOSTNAME=my.esp.example.com make wiflash` is an easy way to override a variable
# #
# optional local configuration file
-include local.conf
# Makefile heavily adapted to esp-link and wireless flashing by Thorsten von Eicken # Makefile heavily adapted to esp-link and wireless flashing by Thorsten von Eicken
# Lots of work, in particular to support windows, by brunnels # Lots of work, in particular to support windows, by brunnels
# Original from esphttpd and others... # Original from esphttpd and others...
#VERBOSE=1 # VERBOSE=1
# --------------- toolchain configuration --------------- # --------------- toolchain configuration ---------------
@ -21,7 +23,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/
# Base directory of the ESP8266 SDK package, absolute # Base directory of the ESP8266 SDK package, absolute
# Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 # Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5
SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.4.0) SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.4.1_pre7)
# Esptool.py path and port, only used for 1-time serial flashing # Esptool.py path and port, only used for 1-time serial flashing
# Typically you'll use https://github.com/themadinventor/esptool # Typically you'll use https://github.com/themadinventor/esptool
@ -30,11 +32,29 @@ ESPTOOL ?= $(abspath ../esp-open-sdk/esptool/esptool.py)
ESPPORT ?= /dev/ttyUSB0 ESPPORT ?= /dev/ttyUSB0
ESPBAUD ?= 460800 ESPBAUD ?= 460800
# The Wifi station configuration can be hard-coded here, which makes esp-link come up in STA+AP # --------------- chipset configuration ---------------
# mode trying to connect to the specified AP *only* if the flash wireless settings are empty!
# This happens on a full serial flash and avoids having to hunt for the AP... # Pick your flash size: "512KB" or "4MB"
# STA_SSID ?= FLASH_SIZE ?= 4MB
# STA_PASS ?=
ifeq ("$(FLASH_SIZE)","512KB")
# Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11
ESP_SPI_SIZE ?= 0 # 0->512KB
ESP_FLASH_MODE ?= 0 # 0->QIO
ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz
ESP_FLASH_MAX ?= 241664 # max bin file for 512KB flash: 236KB
else
# Winbond 25Q32 4MB flash, typ for esp-12
# Here we're using two partitions of approx 0.5MB because that's what's easily available in terms
# of linker scripts in the SDK. Ideally we'd use two partitions of approx 1MB, the remaining 2MB
# cannot be used for code.
ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB)
ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO
ESP_FLASH_FREQ_DIV ?= 15 # 15->80Mhz
ESP_FLASH_MAX ?= 503808 # max bin file for 512KB flash partition: 492KB
#ESP_FLASH_MAX ?= 1028096 # max bin file for 1MB flash partition: 1004KB
endif
# hostname or IP address for wifi flashing # hostname or IP address for wifi flashing
ESP_HOSTNAME ?= esp-link ESP_HOSTNAME ?= esp-link
@ -63,7 +83,7 @@ LED_SERIAL_PIN ?= 14
CHANGE_TO_STA ?= yes CHANGE_TO_STA ?= yes
# Optional Modules # Optional Modules
MODULES ?= mqtt rest MODULES ?= mqtt rest syslog
# --------------- esphttpd config options --------------- # --------------- esphttpd config options ---------------
@ -178,6 +198,10 @@ ifneq (,$(findstring rest,$(MODULES)))
CFLAGS += -DREST CFLAGS += -DREST
endif endif
ifneq (,$(findstring syslog,$(MODULES)))
CFLAGS += -DSYSLOG
endif
# which modules (subdirectories) of the project to include in compiling # which modules (subdirectories) of the project to include in compiling
LIBRARIES_DIR = libraries LIBRARIES_DIR = libraries
MODULES += espfs httpd user serial cmd esp-link MODULES += espfs httpd user serial cmd esp-link

@ -9,21 +9,31 @@
FlashConfig flashConfig; FlashConfig flashConfig;
FlashConfig flashDefault = { FlashConfig flashDefault = {
33, 0, 0, .seq=33, .magic=0, .crc=0,
MCU_RESET_PIN, MCU_ISP_PIN, LED_CONN_PIN, LED_SERIAL_PIN, .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN,
115200, .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN,
"esp-link\0", // hostname .baud_rate = 115200,
0, 0x00ffffff, 0, // static ip, netmask, gateway .hostname = "esp-link\0",
0, // log mode .staticip = 0,
0, // swap uart (don't by default) .netmask = 0x00ffffff,
1, 0, // tcp_enable, rssi_enable .gateway = 0,
"\0", // api_key .log_mode = 0,
0, 0, 0, // slip_enable, mqtt_enable, mqtt_status_enable .swap_uart = 0,
2, 1, // mqtt_timeout, mqtt_clean_session .tcp_enable = 1, .rssi_enable = 0,
1883, 60, // mqtt port, mqtt_keepalive .api_key = "\0",
"\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic .slip_enable = 0, .mqtt_enable = 0, .mqtt_status_enable = 0,
"\0", // system description .mqtt_timeout = 2, .mqtt_clean_session = 1,
1, // rx_pullup .mqtt_port = 1883, .mqtt_keepalive = 60,
.mqtt_host = "\0", .mqtt_clientid = "\0",
.mqtt_username= "\0", .mqtt_password = "\0", .mqtt_status_topic = "\0",
.sys_descr = "\0",
.rx_pullup = 1,
.sntp_server = "\0",
.syslog_host = "\0",
.syslog_minheap= 8192,
.syslog_filter = 7,
.syslog_showtick= 1,
.syslog_showdate= 0,
}; };
typedef union { typedef union {

@ -25,6 +25,12 @@ typedef struct {
char mqtt_status_topic[32]; char mqtt_status_topic[32];
char sys_descr[129]; // system description char sys_descr[129]; // system description
int8_t rx_pullup; // internal pull-up on RX pin int8_t rx_pullup; // internal pull-up on RX pin
char sntp_server[32];
char syslog_host[32];
uint16_t syslog_minheap; // min. heap to allow queuing
uint8_t syslog_filter; // min. severity
uint8_t syslog_showtick; // show system tick (µs)
uint8_t syslog_showdate; // populate SYSLOG date field
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;

@ -30,10 +30,18 @@
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
#include <gpio.h> #include <gpio.h>
#include "syslog.h"
#include "sntp.h"
static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData); static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData);
static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData); static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData);
#define NOTICE(format, ...) do { \
LOG_NOTICE(format, ## __VA_ARGS__ ); \
os_printf(format "\n", ## __VA_ARGS__); \
} while ( 0 )
/* /*
This is the main url->function dispatching data struct. This is the main url->function dispatching data struct.
In short, it's a struct with various URLs plus their handlers. The handlers can In short, it's a struct with various URLs plus their handlers. The handlers can
@ -102,6 +110,17 @@ static char *flash_maps[] = {
"2MB:1024/1024", "4MB:1024/1024" "2MB:1024/1024", "4MB:1024/1024"
}; };
// enable SNTP client...
static void ICACHE_FLASH_ATTR enableSNTP() {
if (flashConfig.sntp_server[0]) {
NOTICE("SNTP timesource set to %s", flashConfig.sntp_server);
sntp_stop();
sntp_setservername(0, flashConfig.sntp_server);
// sntp_set_timezone(flashConfig.timezone); /* stay with GMT... */
sntp_init();
}
}
// Cgi to return various System information // Cgi to return various System information
static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) {
char buff[1024]; char buff[1024];
@ -115,13 +134,18 @@ static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) {
os_sprintf(buff, "{\"name\": \"%s\", \"reset cause\": \"%d=%s\", " os_sprintf(buff, "{\"name\": \"%s\", \"reset cause\": \"%d=%s\", "
"\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\"," "\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\","
"\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\"," "\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\","
"\"description\": \"%s\"" "}", "\"description\": \"%s\","
"\"syslog\": \"%s\","
"\"sntp\": \"%s\" "
"}",
flashConfig.hostname, rst_info->reason, rst_codes[rst_info->reason], flashConfig.hostname, rst_info->reason, rst_codes[rst_info->reason],
flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff), flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff),
part_id ? "user2.bin" : "user1.bin", part_id ? "user2.bin" : "user1.bin",
flashConfig.slip_enable ? "enabled" : "disabled", flashConfig.slip_enable ? "enabled" : "disabled",
flashConfig.mqtt_enable ? "enabled" : "disabled", flashConfig.mqtt_enable ? "enabled" : "disabled",
mqttState(), flashConfig.baud_rate, flashConfig.sys_descr mqttState(), flashConfig.baud_rate, flashConfig.sys_descr,
flashConfig.syslog_host,
flashConfig.sntp_server
); );
jsonHeader(connData, 200); jsonHeader(connData, 200);
@ -137,7 +161,27 @@ static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData) {
int8_t n = getStringArg(connData, "name", flashConfig.hostname, sizeof(flashConfig.hostname)); int8_t n = getStringArg(connData, "name", flashConfig.hostname, sizeof(flashConfig.hostname));
int8_t d = getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr)); int8_t d = getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr));
if (n < 0 || d < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response int8_t t = getStringArg(connData, "sntp", flashConfig.sntp_server, sizeof(flashConfig.sntp_server));
int8_t l = getStringArg(connData, "syslog", flashConfig.syslog_host, sizeof(flashConfig.syslog_host));
if (n < 0 || d < 0 || t < 0 || l < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response
// set defaults for syslog server
// we also should add a config or services web page...
if (l > 0) {
// set defaults for syslog server
syslog_init(flashConfig.syslog_host);
flashConfig.syslog_minheap= 8192;
flashConfig.syslog_filter = SYSLOG_PRIO_DEBUG;
flashConfig.syslog_showtick= 1; // show ESP µs Ticker in log message
flashConfig.syslog_showdate= 0; // Synology does a log rotate if timestamp is in the past, so we simply don't send it
os_printf("flashConfig: syslog: %s, minheap: %d, filter: %d, showtick: %d, showdate: %d\n",
flashConfig.syslog_host, flashConfig.syslog_minheap, flashConfig.syslog_filter, flashConfig.syslog_showtick, flashConfig.syslog_showdate);
}
// (re)start SNTP client if server setting is changed
if (t > 0) {
enableSNTP();
}
if (n > 0) { if (n > 0) {
// schedule hostname change-over // schedule hostname change-over
@ -225,18 +269,24 @@ void user_init(void) {
#endif #endif
struct rst_info *rst_info = system_get_rst_info(); struct rst_info *rst_info = system_get_rst_info();
os_printf("Reset cause: %d=%s\n", rst_info->reason, rst_codes[rst_info->reason]); NOTICE("Reset cause: %d=%s", rst_info->reason, rst_codes[rst_info->reason]);
os_printf("exccause=%d epc1=0x%x epc2=0x%x epc3=0x%x excvaddr=0x%x depc=0x%x\n", NOTICE("exccause=%d epc1=0x%x epc2=0x%x epc3=0x%x excvaddr=0x%x depc=0x%x",
rst_info->exccause, rst_info->epc1, rst_info->epc2, rst_info->epc3, rst_info->exccause, rst_info->epc1, rst_info->epc2, rst_info->epc3,
rst_info->excvaddr, rst_info->depc); rst_info->excvaddr, rst_info->depc);
uint32_t fid = spi_flash_get_id(); uint32_t fid = spi_flash_get_id();
os_printf("Flash map %s, manuf 0x%02lX chip 0x%04lX\n", flash_maps[system_get_flash_size_map()], NOTICE("Flash map %s, manuf 0x%02lX chip 0x%04lX", flash_maps[system_get_flash_size_map()],
fid & 0xff, (fid&0xff00)|((fid>>16)&0xff)); fid & 0xff, (fid&0xff00)|((fid>>16)&0xff));
NOTICE("** esp-link ready");
enableSNTP();
os_printf("** esp-link ready\n");
#ifdef MQTT #ifdef MQTT
NOTICE("initializing MQTT");
mqtt_client_init(); mqtt_client_init();
#endif #endif
NOTICE("initializing user application");
app_init(); app_init();
NOTICE("waiting for work to do...");
} }

@ -0,0 +1,78 @@
/*
* task.c
*
* Copyright 2015 Susi's Strolch
*
* For license information see projects "License.txt"
*
* Not sure if it's save to use ICACHE_FLASH_ATTR, so we're running from RAM
*/
#undef USRTASK_DBG
#include "esp8266.h"
#include <task.h>
#define MAXUSRTASKS 8
#ifdef USRTASK_DBG
#define DBG_USRTASK(format, ...) os_printf(format, ## __VA_ARGS__)
#else
#define DBG_USRTASK(format, ...) do { } while(0)
#endif
LOCAL os_event_t *_task_queue = NULL; // system_os_task queue
LOCAL os_task_t *usr_task_queue = NULL; // user task queue
// it seems save to run the usr_event_handler from RAM, so no ICACHE_FLASH_ATTR here...
LOCAL void usr_event_handler(os_event_t *e)
{
DBG_USRTASK("usr_event_handler: event %p (sig=%d, par=%p)\n", e, (int)e->sig, (void *)e->par);
if (usr_task_queue[e->sig] == NULL || e->sig < 0 || e->sig >= MAXUSRTASKS) {
os_printf("usr_event_handler: task %d %s\n", (int)e->sig,
usr_task_queue[e->sig] == NULL ? "not registered" : "out of range");
return;
}
(usr_task_queue[e->sig])(e);
}
LOCAL void init_usr_task() {
if (_task_queue == NULL)
_task_queue = (os_event_t *)os_zalloc(sizeof(os_event_t) * _task_queueLen);
if (usr_task_queue == NULL)
usr_task_queue = (os_task_t *)os_zalloc(sizeof(os_task_t) * MAXUSRTASKS);
system_os_task(usr_event_handler, _taskPrio, _task_queue, _task_queueLen);
}
// public functions
bool post_usr_task(uint8_t task, os_param_t par)
{
return system_os_post(_taskPrio, task, par);
}
uint8_t register_usr_task (os_task_t event)
{
int task;
DBG_USRTASK("register_usr_task: %p\n", event);
if (_task_queue == NULL || usr_task_queue == NULL)
init_usr_task();
for (task = 0; task < MAXUSRTASKS; task++) {
if (usr_task_queue[task] == event)
return task; // task already registered - bail out...
}
for (task = 0; task < MAXUSRTASKS; task++) {
if (usr_task_queue[task] == NULL) {
DBG_USRTASK("register_usr_task: assign task #%d\n", task);
usr_task_queue[task] = event;
break;
}
}
return task;
}

@ -0,0 +1,20 @@
/*
* task.h
*
* Copyright 2015 Susi's Strolch
*
* For license information see projects "License.txt"
*
*
*/
#ifndef USRTASK_H
#define USRTASK_H
#define _taskPrio 1
#define _task_queueLen 64
uint8_t register_usr_task (os_task_t event);
bool post_usr_task(uint8_t task, os_param_t par);
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

After

Width:  |  Height:  |  Size: 874 B

@ -27,6 +27,20 @@
<tr><td>SLIP status</td><td class="system-slip"></td></tr> <tr><td>SLIP status</td><td class="system-slip"></td></tr>
<tr><td>MQTT status</td><td class="system-mqtt"></td></tr> <tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>Serial baud</td><td class="system-baud"></td></tr> <tr><td>Serial baud</td><td class="system-baud"></td></tr>
<tr><td class="popup-target">Syslog Server</td><td>
<div class="click-to-edit system-syslog">
<span class="edit-off"></span>
<input class="edit-on" maxlength=31 hidden></input>
<div class="popup">Click to edit!<br>Use server [hostname:port] as UDP Syslog server</div>
</div>
</td></tr>
<tr><td class="popup-target">SNTP Server</td><td>
<div class="click-to-edit system-sntp">
<span class="edit-off"></span>
<input class="edit-on" maxlength=31 hidden></input>
<div class="popup">Click to edit!<br>Use server (f.e. 0.europe.pool.ntp.org) as NTP timesource</div>
</div>
</td></tr>
</tbody></table> </tbody></table>
</div> </div>
<div class="card"> <div class="card">
@ -145,6 +159,8 @@
onLoad(function() { onLoad(function() {
makeAjaxInput("system", "description"); makeAjaxInput("system", "description");
makeAjaxInput("system", "name"); makeAjaxInput("system", "name");
makeAjaxInput("system", "sntp");
makeAjaxInput("system", "syslog");
fetchPins(); fetchPins();
getWifiInfo(); getWifiInfo();
getSystemInfo(); getSystemInfo();

@ -3,6 +3,10 @@
#include <user_interface.h> #include <user_interface.h>
#include <eagle_soc.h> #include <eagle_soc.h>
#include <stdint.h>
#include <c_types.h>
#include <ets_sys.h>
#include <stdarg.h>
//Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. //Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere.
//MOST OF THESE ARE GUESSED! but they seem to work and shut up the compiler. //MOST OF THESE ARE GUESSED! but they seem to work and shut up the compiler.
@ -43,14 +47,17 @@ void ets_update_cpu_frequency(int freqmhz);
#define DEBUG_SDK false #define DEBUG_SDK false
#endif #endif
int ets_vsprintf(char *str, const char *format, va_list argptr);
int ets_vsnprintf(char *buffer, size_t sizeOfBuffer, const char *format, va_list argptr);
int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4))); int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4)));
int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2))); int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2)));
#undef os_printf #undef os_printf
#define os_printf(format, ...) \ #define os_printf(format, ...) do { \
system_set_os_print(true); \ system_set_os_print(true); \
os_printf_plus(format, ## __VA_ARGS__); \ os_printf_plus(format, ## __VA_ARGS__); \
system_set_os_print(DEBUG_SDK); // int os_printf(const char *format, ...) system_set_os_print(DEBUG_SDK); \
} while (0)
// memory allocation functions are "different" due to memory debugging functionality // memory allocation functions are "different" due to memory debugging functionality

@ -10,6 +10,7 @@
#include "console.h" #include "console.h"
#include "slip.h" #include "slip.h"
#include "cmd.h" #include "cmd.h"
#include "syslog.h"
#define SKIP_AT_RESET #define SKIP_AT_RESET
@ -404,11 +405,12 @@ serbridgeConnectCb(void *arg)
#ifdef SERBR_DBG #ifdef SERBR_DBG
os_printf("Accept port %d, conn=%p, pool slot %d\n", conn->proto.tcp->local_port, conn, i); os_printf("Accept port %d, conn=%p, pool slot %d\n", conn->proto.tcp->local_port, conn, i);
#endif #endif
syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_NOTICE, "esp-link", "Accept port %d, conn=%p, pool slot %d\n", conn->proto.tcp->local_port, conn, i);
if (i==MAX_CONN) { if (i==MAX_CONN) {
#ifdef SERBR_DBG #ifdef SERBR_DBG
os_printf("Aiee, conn pool overflow!\n"); os_printf("Aiee, conn pool overflow!\n");
#endif #endif
syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_WARNING, "esp-link", "Aiee, conn pool overflow!\n");
espconn_disconnect(conn); espconn_disconnect(conn);
return; return;
} }

@ -18,6 +18,7 @@
* Heavily modified and enhanced by Thorsten von Eicken in 2015 * Heavily modified and enhanced by Thorsten von Eicken in 2015
*/ */
#include "esp8266.h" #include "esp8266.h"
#include "task.h"
#include "uart.h" #include "uart.h"
#ifdef UART_DBG #ifdef UART_DBG
@ -26,14 +27,10 @@
#define DBG_UART(format, ...) do { } while(0) #define DBG_UART(format, ...) do { } while(0)
#endif #endif
#define recvTaskPrio 1 LOCAL uint8_t uart_recvTaskNum;
#define recvTaskQueueLen 64
// UartDev is defined and initialized in rom code. // UartDev is defined and initialized in rom code.
extern UartDevice UartDev; extern UartDevice UartDev;
os_event_t recvTaskQueue[recvTaskQueueLen];
#define MAX_CB 4 #define MAX_CB 4
static UartRecv_cb uart_recv_cb[4]; static UartRecv_cb uart_recv_cb[4];
@ -208,7 +205,7 @@ uart0_rx_intr_handler(void *para)
{ {
//DBG_UART("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no)); //DBG_UART("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no));
ETS_UART_INTR_DISABLE(); ETS_UART_INTR_DISABLE();
system_os_post(recvTaskPrio, 0, 0); post_usr_task(uart_recvTaskNum, 0);
} }
} }
@ -284,7 +281,7 @@ uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
// install uart1 putc callback // install uart1 putc callback
os_install_putc1((void *)uart0_write_char); os_install_putc1((void *)uart0_write_char);
system_os_task(uart_recvTask, recvTaskPrio, recvTaskQueue, recvTaskQueueLen); uart_recvTaskNum = register_usr_task(uart_recvTask);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR

@ -0,0 +1,392 @@
/*
* syslog.c
*
*
* Copyright 2015 Susi's Strolch
*
* For license information see projects "License.txt"
*
*/
#include <esp8266.h>
#include "config.h"
#include <syslog.h>
#include <time.h>
#include "task.h"
extern void * mem_trim(void *m, size_t s); // not well documented...
#define SYSLOG_DBG
#ifdef SYSLOG_DBG
#define DBG_SYSLOG(format, ...) os_printf(format, ## __VA_ARGS__)
#else
#define DBG_SYSLOG(format, ...) do { } while(0)
#endif
#define WIFI_CHK_INTERVAL 1000 // ms to check Wifi statis
LOCAL os_timer_t wifi_chk_timer;
LOCAL struct espconn syslog_espconn;
LOCAL uint32_t syslog_msgid = 1;
LOCAL uint8_t syslog_task = 0;
LOCAL syslog_host_t syslogHost;
LOCAL syslog_entry_t *syslogQueue = NULL;
static enum syslog_state syslogState = SYSLOG_NONE;
LOCAL void ICACHE_FLASH_ATTR syslog_add_entry(syslog_entry_t *entry);
LOCAL void ICACHE_FLASH_ATTR syslog_chk_wifi_stat(void);
LOCAL void ICACHE_FLASH_ATTR syslog_udp_sent_cb(void *arg);
#ifdef SYSLOG_UDP_RECV
LOCAL void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length);
#endif
#define syslog_send_udp() post_usr_task(syslog_task,0)
/******************************************************************************
* FunctionName : syslog_chk_wifi_stat
* Description : check whether get ip addr or not
* Parameters : none
* Returns : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
syslog_chk_wifi_stat(void)
{
struct ip_info ipconfig;
DBG_SYSLOG("syslog_chk_wifi_stat: state: %d ", syslogState);
//disarm timer first
os_timer_disarm(&wifi_chk_timer);
//try to get ip info of ESP8266 station
wifi_get_ip_info(STATION_IF, &ipconfig);
int wifi_status = wifi_station_get_connect_status();
if (wifi_status == STATION_GOT_IP && ipconfig.ip.addr != 0)
{
if (syslogState == SYSLOG_WAIT) { // waiting for initialization
DBG_SYSLOG("connected, initializing UDP socket\n");
syslog_init(flashConfig.syslog_host);
}
} else {
if ((wifi_status == STATION_WRONG_PASSWORD ||
wifi_status == STATION_NO_AP_FOUND ||
wifi_status == STATION_CONNECT_FAIL)) {
syslogState = SYSLOG_ERROR;
os_printf("*** connect failure!!!\n");
} else {
DBG_SYSLOG("re-arming timer...\n");
os_timer_setfn(&wifi_chk_timer, (os_timer_func_t *)syslog_chk_wifi_stat, NULL);
os_timer_arm(&wifi_chk_timer, WIFI_CHK_INTERVAL, 0);
}
}
}
LOCAL void ICACHE_FLASH_ATTR
syslog_udp_send_event(os_event_t *events) {
if (syslogQueue == NULL)
syslogState = SYSLOG_READY;
else {
int res = 0;
syslog_espconn.proto.udp->remote_port = syslogHost.port; // ESP8266 udp remote port
os_memcpy(&syslog_espconn.proto.udp->remote_ip, &syslogHost.addr.addr, 4); // ESP8266 udp remote IP
res = espconn_send(&syslog_espconn, (uint8_t *)syslogQueue->datagram, syslogQueue->datagram_len);
if (res != 0) {
os_printf("syslog_udp_send: error %d\n", res);
}
}
}
/******************************************************************************
* FunctionName : syslog_compose
* Description : compose a syslog_entry_t from va_args
* Parameters : va_args
* Returns : the malloced syslog_entry_t
******************************************************************************/
LOCAL syslog_entry_t ICACHE_FLASH_ATTR *
syslog_compose(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
{
syslog_entry_t *se = os_zalloc(sizeof (syslog_entry_t) + 1024); // allow up to 1k datagram
char *p = se->datagram;
uint32_t tick = WDEV_NOW(); // 0 ... 4294.967295s
// The Priority value is calculated by first multiplying the Facility
// number by 8 and then adding the numerical value of the Severity.
p += os_sprintf(p, "<%d> ", facility * 8 + severity);
// strftime doesn't work as expected - or adds 8k overhead.
// so let's do poor man conversion - format is fixed anyway
if (flashConfig.syslog_showdate == 0)
p += os_sprintf(p, "- ");
else {
time_t now = NULL;
struct tm *tp = NULL;
// create timestamp: FULL-DATE "T" PARTIAL-TIME "Z": 'YYYY-mm-ddTHH:MM:SSZ '
// as long as realtime_stamp is 0 we use tick div 10⁶ as date
now = (realtime_stamp == 0) ? (tick / 1000000) : realtime_stamp;
tp = gmtime(&now);
p += os_sprintf(p, "%4d-%02d-%02dT%02d:%02d:%02dZ ",
tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec);
}
// add HOSTNAME APP-NAME PROCID MSGID
if (flashConfig.syslog_showtick)
p += os_sprintf(p, "%s %s %lu.%06lu %lu ", flashConfig.hostname, tag, tick / 1000000, tick % 1000000, syslog_msgid++);
else
p += os_sprintf(p, "%s %s - %lu ", flashConfig.hostname, tag, syslog_msgid++);
// append syslog message
va_list arglist;
va_start(arglist, fmt);
p += ets_vsprintf(p, fmt, arglist );
va_end(arglist);
se->datagram_len = p - se->datagram;
se = mem_trim(se, sizeof(syslog_entry_t) + se->datagram_len + 1);
return se;
}
/******************************************************************************
* FunctionName : syslog_add_entry
* Description : add a syslog_entry_t to the syslogQueue
* Parameters : entry: the syslog_entry_t
* Returns : none
******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
syslog_add_entry(syslog_entry_t *entry)
{
syslog_entry_t *pse = syslogQueue;
// append msg to syslog_queue
if (pse == NULL)
syslogQueue = entry;
else {
while (pse->next != NULL)
pse = pse->next;
pse->next = entry; // append msg to syslog queue
}
// ensure we have sufficient heap for the rest of the system
if (system_get_free_heap_size() < syslogHost.min_heap_size) {
if (syslogState != SYSLOG_HALTED) {
os_printf("syslog_add_entry: Warning: queue filled up, halted\n");
entry->next = syslog_compose(SYSLOG_FAC_SYSLOG, SYSLOG_PRIO_CRIT, "-", "queue filled up, halted");
if (syslogState == SYSLOG_READY)
syslog_send_udp();
syslogState = SYSLOG_HALTED;
}
}
}
/******************************************************************************
* FunctionName : syslog_sent_cb
* Description : udp sent successfully
* fetch next syslog package, free old message
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
syslog_udp_sent_cb(void *arg)
{
struct espconn *pespconn = arg;
(void) pespconn;
// datagram is delivered - free and advance queue
syslog_entry_t *pse = syslogQueue;
syslogQueue = syslogQueue -> next;
os_free(pse);
if (syslogQueue != NULL)
syslog_send_udp();
else
syslogState = SYSLOG_READY;
}
/*****************************************************************************
* FunctionName : syslog_recv_cb
* Description : Processing the received udp packet
* Parameters : arg -- Additional argument to pass to the callback function
* pusrdata -- The received data (or NULL when the connection has been closed!)
* length -- The length of received data
* Returns : none
******************************************************************************/
#ifdef SYSLOG_UDP_RECV
LOCAL void ICACHE_FLASH_ATTR
syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length)
{
DBG_SYSLOG("syslog_udp_recv_cb: %p, %p, %d\n", arg, pusrdata, length);
}
#endif
/******************************************************************************
*
******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg)
{
struct espconn *pespconn = (struct espconn *)arg;
(void) pespconn;
if (ipaddr != NULL) {
syslogHost.addr.addr = ipaddr->addr;
syslogState = SYSLOG_SENDING;
syslog_send_udp();
} else {
syslogState = SYSLOG_ERROR;
DBG_SYSLOG("syslog_gethostbyname_cb: state=SYSLOG_ERROR\n");
}
}
/******************************************************************************
* FunctionName : initSyslog
* Description : Initialize the syslog library
* Parameters : hostname -- the syslog server (host:port)
* host: IP-Addr | hostname
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
syslog_init(char *syslog_server)
{
char host[32], *port = &host[0];
syslog_task = register_usr_task(syslog_udp_send_event);
syslogHost.min_heap_size = flashConfig.syslog_minheap;
syslogHost.port = 514;
syslogState = SYSLOG_WAIT;
os_strncpy(host, syslog_server, 32);
while (*port && *port != ':') // find port delimiter
port++;
if (*port) {
*port++ = '\0';
syslogHost.port = atoi(port);
}
wifi_set_broadcast_if(STATIONAP_MODE); // send UDP broadcast from both station and soft-AP interface
syslog_espconn.type = ESPCONN_UDP;
syslog_espconn.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
syslog_espconn.proto.udp->local_port = espconn_port(); // set a available port
#ifdef SYSLOG_UDP_RECV
espconn_regist_recvcb(&syslog_espconn, syslog_udp_recv_cb); // register a udp packet receiving callback
#endif
espconn_regist_sentcb(&syslog_espconn, syslog_udp_sent_cb); // register a udp packet sent callback
espconn_create(&syslog_espconn); // create udp
if (UTILS_StrToIP((const char *)host, (void*)&syslogHost.addr)) {
syslogState = SYSLOG_SENDING;
syslog_send_udp();
} else {
static struct espconn espconn_ghbn;
espconn_gethostbyname(&espconn_ghbn, host, &syslogHost.addr, syslog_gethostbyname_cb);
// syslog_send_udp is called by syslog_gethostbyname_cb()
}
#ifdef SYSLOG_UDP_RECV
DBG_SYSLOG("syslog_init: host: %s, port: %d, lport: %d, recvcb: %p, sentcb: %p, state: %d\n",
host, syslogHost.port, syslog_espconn.proto.udp->local_port,
syslog_udp_recv_cb, syslog_udp_sent_cb, syslogState );
#else
DBG_SYSLOG("syslog_init: host: %s, port: %d, lport: %d, rsentcb: %p, state: %d\n",
host, syslogHost.port, syslog_espconn.proto.udp->local_port,
syslog_udp_sent_cb, syslogState );
#endif
}
/******************************************************************************
* FunctionName : syslog
* Description : compose and queue a new syslog message
* Parameters : facility
* severity
* tag
* message
* ...
*
* SYSLOG-MSG = HEADER SP STRUCTURED-DATA [SP MSG]
HEADER = PRI VERSION SP TIMESTAMP SP HOSTNAME
SP APP-NAME SP PROCID SP MSGID
PRI = "<" PRIVAL ">"
PRIVAL = 1*3DIGIT ; range 0 .. 191
VERSION = NONZERO-DIGIT 0*2DIGIT
HOSTNAME = NILVALUE / 1*255PRINTUSASCII
APP-NAME = NILVALUE / 1*48PRINTUSASCII
PROCID = NILVALUE / 1*128PRINTUSASCII
MSGID = NILVALUE / 1*32PRINTUSASCII
TIMESTAMP = NILVALUE / FULL-DATE "T" FULL-TIME
FULL-DATE = DATE-FULLYEAR "-" DATE-MONTH "-" DATE-MDAY
DATE-FULLYEAR = 4DIGIT
DATE-MONTH = 2DIGIT ; 01-12
DATE-MDAY = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
; month/year
FULL-TIME = PARTIAL-TIME TIME-OFFSET
PARTIAL-TIME = TIME-HOUR ":" TIME-MINUTE ":" TIME-SECOND
[TIME-SECFRAC]
TIME-HOUR = 2DIGIT ; 00-23
TIME-MINUTE = 2DIGIT ; 00-59
TIME-SECOND = 2DIGIT ; 00-59
TIME-SECFRAC = "." 1*6DIGIT
TIME-OFFSET = "Z" / TIME-NUMOFFSET
TIME-NUMOFFSET = ("+" / "-") TIME-HOUR ":" TIME-MINUTE
STRUCTURED-DATA = NILVALUE / 1*SD-ELEMENT
SD-ELEMENT = "[" SD-ID *(SP SD-PARAM) "]"
SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34
SD-ID = SD-NAME
PARAM-NAME = SD-NAME
PARAM-VALUE = UTF-8-STRING ; characters '"', '\' and
; ']' MUST be escaped.
SD-NAME = 1*32PRINTUSASCII
; except '=', SP, ']', %d34 (")
MSG = MSG-ANY / MSG-UTF8
MSG-ANY = *OCTET ; not starting with BOM
MSG-UTF8 = BOM UTF-8-STRING
BOM = %xEF.BB.BF
UTF-8-STRING = *OCTET ; UTF-8 string as specified
; in RFC 3629
OCTET = %d00-255
SP = %d32
PRINTUSASCII = %d33-126
NONZERO-DIGIT = %d49-57
DIGIT = %d48 / NONZERO-DIGIT
NILVALUE = "-"
*
* TIMESTAMP: realtime_clock == 0 ? timertick / 10 : realtime_clock
* HOSTNAME hostname
* APPNAME: ems-esp-link
* PROCID: timertick
* MSGID: NILVALUE
*
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
syslog(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
{
DBG_SYSLOG("syslog: state=%d ", syslogState);
if (syslogState == SYSLOG_ERROR ||
syslogState == SYSLOG_HALTED)
return;
// compose the syslog message
void *arg = __builtin_apply_args();
void *res = __builtin_apply((void*)syslog_compose, arg, 128);
syslog_entry_t *se = *(syslog_entry_t **)res;
// and append it to the message queue
syslog_add_entry(se);
if (syslogState == SYSLOG_READY) {
syslogState = SYSLOG_SENDING;
syslog_send_udp();
}
if (syslogState == SYSLOG_NONE) {
syslogState = SYSLOG_WAIT;
syslog_chk_wifi_stat(); // fire the timer to check the Wifi connection status
}
}

@ -0,0 +1,110 @@
/*
* syslog.h
*
*
* Copyright 2015 Susi's Strolch
*
* For license information see projects "License.txt"
*
* part of syslog.c - client library
*
*/
#ifndef _SYSLOG_H
#define _SYSLOG_H
#ifdef __cplusplus
extern "C" {
#endif
enum syslog_state {
SYSLOG_NONE, // not initialized
SYSLOG_WAIT, // initialized, waiting for Wifi
SYSLOG_READY, // Wifi established, ready to send
SYSLOG_SENDING, // UDP package on the air
SYSLOG_HALTED, // heap full, discard message
SYSLOG_ERROR,
};
enum syslog_priority {
SYSLOG_PRIO_EMERG, /* system is unusable */
SYSLOG_PRIO_ALERT, /* action must be taken immediately */
SYSLOG_PRIO_CRIT, /* critical conditions */
SYSLOG_PRIO_ERR, /* error conditions */
SYSLOG_PRIO_WARNING, /* warning conditions */
SYSLOG_PRIO_NOTICE, /* normal but significant condition */
SYSLOG_PRIO_INFO, /* informational */
SYSLOG_PRIO_DEBUG, /* debug-level messages */
};
enum syslog_facility {
SYSLOG_FAC_KERN, /* kernel messages */
SYSLOG_FAC_USER, /* random user-level messages */
SYSLOG_FAC_MAIL, /* mail system */
SYSLOG_FAC_DAEMON, /* system daemons */
SYSLOG_FAC_AUTH, /* security/authorization messages */
SYSLOG_FAC_SYSLOG, /* messages generated internally by syslogd */
SYSLOG_FAC_LPR, /* line printer subsystem */
SYSLOG_FAC_NEWS, /* network news subsystem */
SYSLOG_FAC_UUCP, /* UUCP subsystem */
SYSLOG_FAC_CRON, /* clock daemon */
SYSLOG_FAC_AUTHPRIV,/* security/authorization messages (private) */
SYSLOG_FAC_FTP, /* ftp daemon */
SYSLOG_FAC_LOCAL0, /* reserved for local use */
SYSLOG_FAC_LOCAL1, /* reserved for local use */
SYSLOG_FAC_LOCAL2, /* reserved for local use */
SYSLOG_FAC_LOCAL3, /* reserved for local use */
SYSLOG_FAC_LOCAL4, /* reserved for local use */
SYSLOG_FAC_LOCAL5, /* reserved for local use */
SYSLOG_FAC_LOCAL6, /* reserved for local use */
SYSLOG_FAC_LOCAL7, /* reserved for local use */
};
#define MINIMUM_HEAP_SIZE 8192
#define REG_READ(_r) (*(volatile uint32 *)(_r))
#define WDEV_NOW() REG_READ(0x3ff20c00)
extern uint32_t realtime_stamp; // 1sec NTP ticker
typedef struct syslog_host_t syslog_host_t;
struct syslog_host_t {
uint32_t min_heap_size; // minimum allowed heap size when buffering
ip_addr_t addr;
uint16_t port;
};
// buffered syslog event - f.e. if network stack isn't up and running
typedef struct syslog_entry_t syslog_entry_t;
struct syslog_entry_t {
syslog_entry_t *next;
uint16_t datagram_len;
char datagram[];
};
syslog_host_t syslogserver;
void ICACHE_FLASH_ATTR syslog_init(char *syslog_server);
void ICACHE_FLASH_ATTR syslog(uint8_t facility, uint8_t severity, const char tag[], const char message[], ...);
// some convenience macros
#ifdef SYSLOG
// extern char *esp_link_version; // in user_main.c
#define LOG_DEBUG(format, ...) syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_DEBUG, "esp_link", format, ## __VA_ARGS__ )
#define LOG_NOTICE(format, ...) syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_NOTICE, "esp_link", format, ## __VA_ARGS__ )
#define LOG_INFO(format, ...) syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_INFO, "esp_link", format, ## __VA_ARGS__ )
#define LOG_WARN(format, ...) syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_WARNING, "esp_link", format, ## __VA_ARGS__ )
#define LOG_ERR(format, ...) syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_ERR, "esp_link", format, ## __VA_ARGS__ )
#else
#define LOG_DEBUG(format, ...) do { } while(0)
#define LOG_NOTICE(format, ...) do { } while(0)
#define LOG_WARN(format, ...) do { } while(0)
#define LOG_INFO(format, ...) do { } while(0)
#define LOG_ERR(format, ...) do { } while(0)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _SYSLOG_H */
Loading…
Cancel
Save