From 2fd207241154cb6d0e6c38807132dde3990f07af Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Mon, 13 Jul 2015 10:25:29 -0700 Subject: [PATCH 01/11] reduce size of icons --- html/favicon.ico | Bin 622 -> 874 bytes html/home.html | 2 +- html/jl-200x55.png | Bin 2751 -> 0 bytes html/style.css | 7 + html/ui.js | 358 --------------------------------------------- 5 files changed, 8 insertions(+), 359 deletions(-) delete mode 100755 html/jl-200x55.png delete mode 100644 html/ui.js diff --git a/html/favicon.ico b/html/favicon.ico index ea4eca11c5ea71459cf3dcecea6e9c4c6bf90fa3..fe24a7b535b3d0acfd1db7f56d08b424ef11f880 100755 GIT binary patch literal 874 zcmV-w1C{(oNk%w1VL$*t0P6q%|NsC0{{UlaYpoa|=HA|SZf>NktgRs>r5G6Aq^!kV zV*l^&R#sN6EiJ7W7^MspA^8LW00031EC2ui06+jh000F4Fvv-(wIb^+uK!?I6(nbp zg{ZEh>Aoo|Tg+?U-OMrt?w>kU4OcK2kA|Kv__-AcfT(l|AS7?h%FVE#dc6w+Hf!U4 z&tI`Crc-hX==j;aVYBEOs64Kp64o*=U3+K*3||Cz87wD+az$v0D~*nE0)1bSA$V|= z01B83nn0Vsd5Sf0|x^NqKAZkbsj?+ot_Q50}oP3m1-Lo zCZ16V2)wn zS4jY|&=Txy^$gv*0*c4URS~k3zN^KqjE4Lefdvb$f5En_*)gyK;$ocs4mq#|tPmh@ z;H7t1;Nl2OmA7<)OSgW#s5a`g@h;QUxWfkj9i4D@04Ai#)J#D84ImF56h!oi1NkVB zKmrO}lM+Y3*+kNXAchzsCbVQ_*8jg_yR@t#1B&+Nf3(Q9PEVR)wlH3m^RQsz9+IH(L1rY!MJGW+g AmH+?% literal 622 zcmZ?wbhEHbRA5kGSj)ih|NsAg|Nf<=r>~MzDkv=69~QZC)vC>#H$Qs(_~y-W_-g;e`3n{tO-Zk;s@iI0ckI})UmriddGqGh z+)qmoN^8pc?NdZa4UcGWFSz5y!S41)Ps2yzJm~o!NdHTtYwwY~5 zE9EXQh_$6j|5P)1Q6iAa$eUg5=EKrlEF_mEB~Z+f9qv=#puj9H#I9Jv>)XM^){w@> zEW;qiE!dY{$>iEu)F8;rEX^q|xm`4!dx~?xQby73LLw5|m<5YB1Tl3N?_u62#>l!| za*~g;H_H*}?Sc{_LVLNdr^os;_;4MOVdi6$=M>&9E3qV<>+U-y9T^Fa4+lDb0$Sv;b6n2XlXCSAL=Z98!MNyiEub191P`SJ=B)_ z?TkjFP-MR4gbNK!TcZmqnHEQtPHEvxG|yRlVL|ha{mG}DgbQAZTO_49Tr}0rm4C!A zS&aW>a75!4|F%hcBu%%7$l2x{nZP(Dt+&BBa6`_+M^C#0wbsT;M_yVo_s#9FCI$v; E07DSuRsaA1 diff --git a/html/home.html b/html/home.html index f16a0e0..308b4df 100644 --- a/html/home.html +++ b/html/home.html @@ -1,6 +1,6 @@
-
+
JEELABS

esp-link

diff --git a/html/jl-200x55.png b/html/jl-200x55.png deleted file mode 100755 index 3bc4a42cdfe781b8e1b0a9e2dc48e6b6e8577a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 zcmV;w3PAOVP) zPly}W9ml^;?Ze8jU9tsd-LX> z+}Q5}Vl^{QZ+t06Na=I)FySFdAvfA(2F7Pm-M# zbv+N@1MDh7SULbsR}7<-luQyy91>BGqONaZU@4O1YQ->4C)}q*5{g&~Qq=W3h;A)J zX;lp4aLVV9NT@_okfN?H0(c`?Q36@27{=n5&nbDt39TSSUH@97ou+9x@xlv2eg5_1 zk71goNYh@$Fb)WHDv>0Bu!0nIJqzFtuT2=GU{SBvajjktYIdMv7`<30l1Ky)QV=IQ zb&GX;?(A6{IdUX1p#Y%SY@%AL@tPc#*)B=i1S$wmIdZuiUcY!TaiQESudHBeYm0SQ zDv2ajzQsGpQ;t%pgrC0nVq$_UT)c>HPflWXcGk21=+UG2ZZ3yrvq}5d{12agx_0yC zP3dk)QsJ?H<5cBXU0ucO%uJ$!^!t6Lo0iMvu)4a+`Y1Opl1SpfR1j9S$|#qSnV3ja zh-S0tvm7Lui3u3xGWD2fW=$dq3spgix=y`abME4S{QdRcFppJhHCz;oWmqyewHb*d zQCJq_0=c79Dn+&&t)*pj-g_S#Pdtf@C!VA#i)i1Oi3yZSCEB5J7cM1_06qnAhL3p2 z<#MrNj(`3B9pvp@I?fcu?xcY;`OgD_={Q2{~eMMbo z7BnT2u#grcOE#dnGGX}glTSU{ZtJmLE_F=XNI{Ca zK1UvOU%XN1efGI;U-lP2AHCn&+VaF7_qVq_Z42-IG4LET8H>7pDvX>G2@AIc@kP>c z$5%C8dDXMM-xcV$Zr{fA^z>-E^WOWu&mVm5*}!u!WMpRrB$5y?3x)2BH!5VneeB&o zjNY%WuX|z$GUk~2{`Z8>lgVVrT~opzmPj}-6-3jtSRK<+yZeb$F)wv2;$98W&YTe! zOd<)vUVt8dFalsUEr--%bCL*5*6E+Lg0f ztKr0n6H!k2vnU^ugu_(S0%iA(PSu#&icjq(wG3|990?)VuI1NrBPUH}uoDQcOqq(B)oiPi@aa47Dq`ql3=LXhfvO<=en0XMliS_@ zdbXdr{3afE`dTlSJ+%*VoR&Kc+-x>6Jv|+JsEZ^u$UOeg#c9BMN56vvm$)?*brppB ztl1W81Zh0`QN5lDhoRm3=6$uesGhH~%wyv6r$~t@jzy;UwHO;ns@!l|t)esbh z3$GeZPOB9uB*v`f%hgWOgJnI2G>GlAGFm+ZB$%9=hsd>X!AbLa;;Ny7{E79cukPK$ zm!EvN|p_Gq`;NvyNQT~tdF4O3BlvrS2h7$Tz-mni^uOhx5RanNk* zu%jp<8Nq^+1OTw>VpTyz{Oxudxm*st&p!91V$b~N-@aaHwGVeS9N8& z!yWh!sTf98xPyd9!PTKw+#fK$%#ffvbPFM35#D#{q?g@y`n;*Ai)4n1(&rimvB$8V zIZ)EZaHXgp0|44Gp612|0I?CZfIt3lTLf}i?cX?)sG=~GRgx~w@R~TEFC-y{W3kqV z-Jys5Xtq_=Z0i6+87}~w!HS&K4DpvA9UHk?Uwrrxbz&25TJ0Afe&lKEE+j^QCo2t8 zQE!DX`Pais^w1J_VGLH)JqiVpMy8?;hmZ)hchLj9S*!&R=5uR%8?!Sr*grGlnap&5 zdz)JUcW16>(`rdtOUu*&i!9tO9?iW1$JcZfnQobi+5vD*v#o}ysHZS^I+lkZvrY6} z5N#`%$(jn$XGbJcB-$S-AI*A*xRjKPRzc){=g64_-7V@+`k2FRLSfU%Sb5UB&bTX| z;yUiwu7XqyV~t!7Yk7GYM!AfaZd?zX{_4g(Fp)Q{HVJ42!ir&#<`)3fSI%Phi=)vA zDNdL>q=-L09Dypr5`aa4cB1`}@{!iVH}aK12i~dNo0Pt3gta!F3b=FO(0KI~ z;TzJ$^2H)U3vlY6!D}Jxo1F9o@IljRiJ#jJmX45E9QZ5;|N)I*4=sJ;u$8KMyg z?K`B^QDSm{Ecj`*)pLIDM##Q8Zkb61@jdG7x0fyf*uD6lf4l6fR~&rqS-f=Px=)Ej zrq#w_C>sIyqISNtLttBn4uC^p=QBLy%n{q7)?-MA*iK?fbQOc&X%DX&uG!Xc=Qlr1 zk;6?314Z*(KfXIEZJpbfPoBid2xGJK`FWH|rNkGy2AB`pkx!tKBnmBy<-5SH)$8c* z>_j?28p_e%*B`xh2OrzH#^r`0A2LzaeoESn^0m_aM=@dqLV z%_EPBK2I+)Rt#gT1NJ132D}I8P~jzSkA+^V7)H3@NFoV==wqOnN&*a?`jqrz z+4?&>L5TsW9Fo)#4s4yp<(LJYOeTZUrAx7wEbVr?SYBB{zu)IIJNF=lvr8U5LS=r6 zx;_QqZcw{?J`e588DVAVcDpb)HqdGbO#(b1V-Crlh;1mX{th3^k76vP-T&);}T&71Nkx0Ht{14hL^?zhM5i|e*002ovPDHLk FV1fk~Lhb+n diff --git a/html/style.css b/html/style.css index 4fa393a..29d15a3 100644 --- a/html/style.css +++ b/html/style.css @@ -114,6 +114,13 @@ div.tt { .header h1 .esp { font-size: 1.25em; } +.jl { + font: normal 800 1.5em sans-serif; + position: relative; + bottom: 19px; + color: #9d1414; + margin-left: 3px; +} .content-subhead { margin: 50px 0 20px 0; diff --git a/html/ui.js b/html/ui.js deleted file mode 100644 index b67f077..0000000 --- a/html/ui.js +++ /dev/null @@ -1,358 +0,0 @@ -//===== Collection of small utilities - -/* - * Bind/Unbind events - * - * Usage: - * var el = document.getElementyById('#container'); - * bnd(el, 'click', function() { - * console.log('clicked'); - * }); - */ - -var bnd = function( - d, // a DOM element - e, // an event name such as "click" - f // a handler function -){ - d.addEventListener(e, f, false); -} - -/* - * Create DOM element - * - * Usage: - * var el = m('

Hello

'); - * document.body.appendChild(el); - * - * Copyright (C) 2011 Jed Schmidt - WTFPL - * More: https://gist.github.com/966233 - */ - -var m = function( - a, // an HTML string - b, // placeholder - c // placeholder -){ - b = document; // get the document, - c = b.createElement("p"); // create a container element, - c.innerHTML = a; // write the HTML to it, and - a = b.createDocumentFragment(); // create a fragment. - - while ( // while - b = c.firstChild // the container element has a first child - ) a.appendChild(b); // append the child to the fragment, - - return a // and then return the fragment. -} - -/* - * DOM selector - * - * Usage: - * $('div'); - * $('#name'); - * $('.name'); - * - * Copyright (C) 2011 Jed Schmidt - WTFPL - * More: https://gist.github.com/991057 - */ - -var $ = function( - a, // take a simple selector like "name", "#name", or ".name", and - b // an optional context, and -){ - a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol. - return( // return an element or list, from within the scope of - b // the passed context - || document // or document, - )[ - "getElement" + ( // obtained by the appropriate method calculated by - a[1] - ? a[1] == "#" - ? "ById" // the node by ID, - : "sByClassName" // the nodes by class name, or - : "sByTagName" // the nodes by tag name, - ) - ]( - a[2] // called with the name. - ) -} - -/* - * Get cross browser xhr object - * - * Copyright (C) 2011 Jed Schmidt - * More: https://gist.github.com/993585 - */ - -var j = function( - a // cursor placeholder -){ - for( // for all a - a=0; // from 0 - a<4; // to 4, - a++ // incrementing - ) try { // try - return a // returning - ? new ActiveXObject( // a new ActiveXObject - [ // reflecting - , // (elided) - "Msxml2", // the various - "Msxml3", // working - "Microsoft" // options - ][a] + // for Microsoft implementations, and - ".XMLHTTP" // the appropriate suffix, - ) // but make sure to - : new XMLHttpRequest // try the w3c standard first, and - } - - catch(e){} // ignore when it fails. -} - -// createElement short-hand - -e = function(a) { return document.createElement(a); } - -// chain onload handlers - -function onLoad(f) { - var old = window.onload; - if (typeof old != 'function') { - window.onload = f; - } else { - window.onload = function() { - old(); - f(); - } - } -} - -//===== helpers to add/remove/toggle HTML element classes - -function addClass(el, cl) { - el.className += ' ' + cl; -} -function removeClass(el, cl) { - var cls = el.className.split(/\s+/), - l = cls.length; - for (var i=0; i= 200 && xhr.status < 300) { - console.log("XHR done:", method, url, "->", xhr.status); - ok_cb(xhr.responseText); - } else { - console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr); - err_cb(xhr.status, xhr.responseText); - } - } - console.log("XHR send:", method, url); - try { - xhr.send(); - } catch(err) { - console.log("XHR EXC :", method, url, "->", err); - err_cb(599, err); - } -} - -function dispatchJson(resp, ok_cb, err_cb) { - var j; - try { j = JSON.parse(resp); } - catch(err) { - console.log("JSON parse error: " + err + ". In: " + resp); - err_cb(500, "JSON parse error: " + err); - return; - } - ok_cb(j); -} - -function ajaxJson(method, url, ok_cb, err_cb) { - ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); -} - -function ajaxSpin(method, url, ok_cb, err_cb) { - $("#spinner").removeAttribute('hidden'); - ajaxReq(method, url, function(resp) { - $("#spinner").setAttribute('hidden', ''); - ok_cb(resp); - }, function(status, statusText) { - $("#spinner").setAttribute('hidden', ''); - //showWarning("Error: " + statusText); - err_cb(status, statusText); - }); -} - -function ajaxJsonSpin(method, url, ok_cb, err_cb) { - ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); -} - -//===== main menu, header spinner and notification boxes - -onLoad(function() { - var l = $("#layout"); - var o = l.childNodes[0]; - // spinner - l.insertBefore(m(''), o); - // notification boxes - l.insertBefore(m( - '
'), o); - // menu hamburger button - l.insertBefore(m(''), o); - // menu left-pane - var mm = m( - '\ - '); - l.insertBefore(mm, o); - - // make hamburger button pull out menu - var ml = $('#menuLink'), mm = $('#menu'); - bnd(ml, 'click', function (e) { - console.log("hamburger time"); - var active = 'active'; - e.preventDefault(); - toggleClass(l, active); - toggleClass(mm, active); - toggleClass(ml, active); - }); - - // populate menu via ajax call - var getMenu = function() { - ajaxJson("GET", "/menu", function(data) { - var html = "", path = window.location.pathname; - for (var i=0; i" + - "" + - data.menu[i] + ""); - } - $("#menu-list").innerHTML = html; - - v = $("#version"); - if (v != null) { v.innerHTML = data.version; } - }, function() { setTimeout(getMenu, 1000); }); - }; - getMenu(); -}); - -//===== Wifi info - -function showWifiInfo(data) { - Object.keys(data).forEach(function(v) { - el = $("#wifi-" + v); - if (el != null) { - if (el.nodeName === "INPUT") el.value = data[v]; - else el.innerHTML = data[v]; - } - }); - var dhcp = $('#dhcp-r'+data.dhcp); - if (dhcp) dhcp.click(); - $("#wifi-spinner").setAttribute("hidden", ""); - $("#wifi-table").removeAttribute("hidden"); - currAp = data.ssid; -} - -function getWifiInfo() { - ajaxJson('GET', "/wifi/info", showWifiInfo, - function(s, st) { window.setTimeout(getWifiInfo, 1000); }); -} - -//===== Notifications - -function showWarning(text) { - var el = $("#warning"); - el.innerHTML = text; - el.removeAttribute('hidden'); -} -function hideWarning() { - el = $("#warning").setAttribute('hidden', ''); -} -var notifTimeout = null; -function showNotification(text) { - var el = $("#notification"); - el.innerHTML = text; - el.removeAttribute('hidden'); - if (notifTimeout != null) clearTimeout(notifTimeout); - notifTimout = setTimeout(function() { - el.setAttribute('hidden', ''); - notifTimout = null; - }, 4000); -} - -//===== GPIO Pin mux card - -var currPin; -// pin={reset:12, isp:13, LED_conn:0, LED_ser:2} -function createInputForPin(pin) { - var input = document.createElement("input"); - input.type = "radio"; - input.name = "pins"; - input.data = pin.name; - input.className = "pin-input"; - input.value= pin.value; - input.id = "opt-" + pin.value; - if (currPin == pin.name) input.checked = "1"; - - var descr = m('"); - var div = document.createElement("div"); - div.appendChild(input); - div.appendChild(descr); - return div; -} - -function displayPins(resp) { - var po = $("#pin-mux"); - po.innerHTML = ""; - currPin = resp.curr; - resp.map.forEach(function(v) { - po.appendChild(createInputForPin(v)); - }); - var i, inputs = $(".pin-input"); - for (i=0; i Date: Tue, 14 Jul 2015 00:09:21 -0700 Subject: [PATCH 02/11] oops, readd mistakenly deleted file --- html/ui.js | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 html/ui.js diff --git a/html/ui.js b/html/ui.js new file mode 100644 index 0000000..5de2f4c --- /dev/null +++ b/html/ui.js @@ -0,0 +1,358 @@ +//===== Collection of small utilities + +/* + * Bind/Unbind events + * + * Usage: + * var el = document.getElementyById('#container'); + * bnd(el, 'click', function() { + * console.log('clicked'); + * }); + */ + +var bnd = function( + d, // a DOM element + e, // an event name such as "click" + f // a handler function +){ + d.addEventListener(e, f, false); +} + +/* + * Create DOM element + * + * Usage: + * var el = m('

Hello

'); + * document.body.appendChild(el); + * + * Copyright (C) 2011 Jed Schmidt - WTFPL + * More: https://gist.github.com/966233 + */ + +var m = function( + a, // an HTML string + b, // placeholder + c // placeholder +){ + b = document; // get the document, + c = b.createElement("p"); // create a container element, + c.innerHTML = a; // write the HTML to it, and + a = b.createDocumentFragment(); // create a fragment. + + while ( // while + b = c.firstChild // the container element has a first child + ) a.appendChild(b); // append the child to the fragment, + + return a // and then return the fragment. +} + +/* + * DOM selector + * + * Usage: + * $('div'); + * $('#name'); + * $('.name'); + * + * Copyright (C) 2011 Jed Schmidt - WTFPL + * More: https://gist.github.com/991057 + */ + +var $ = function( + a, // take a simple selector like "name", "#name", or ".name", and + b // an optional context, and +){ + a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol. + return( // return an element or list, from within the scope of + b // the passed context + || document // or document, + )[ + "getElement" + ( // obtained by the appropriate method calculated by + a[1] + ? a[1] == "#" + ? "ById" // the node by ID, + : "sByClassName" // the nodes by class name, or + : "sByTagName" // the nodes by tag name, + ) + ]( + a[2] // called with the name. + ) +} + +/* + * Get cross browser xhr object + * + * Copyright (C) 2011 Jed Schmidt + * More: https://gist.github.com/993585 + */ + +var j = function( + a // cursor placeholder +){ + for( // for all a + a=0; // from 0 + a<4; // to 4, + a++ // incrementing + ) try { // try + return a // returning + ? new ActiveXObject( // a new ActiveXObject + [ // reflecting + , // (elided) + "Msxml2", // the various + "Msxml3", // working + "Microsoft" // options + ][a] + // for Microsoft implementations, and + ".XMLHTTP" // the appropriate suffix, + ) // but make sure to + : new XMLHttpRequest // try the w3c standard first, and + } + + catch(e){} // ignore when it fails. +} + +// createElement short-hand + +e = function(a) { return document.createElement(a); } + +// chain onload handlers + +function onLoad(f) { + var old = window.onload; + if (typeof old != 'function') { + window.onload = f; + } else { + window.onload = function() { + old(); + f(); + } + } +} + +//===== helpers to add/remove/toggle HTML element classes + +function addClass(el, cl) { + el.className += ' ' + cl; +} +function removeClass(el, cl) { + var cls = el.className.split(/\s+/), + l = cls.length; + for (var i=0; i= 200 && xhr.status < 300) { + console.log("XHR done:", method, url, "->", xhr.status); + ok_cb(xhr.responseText); + } else { + console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr); + err_cb(xhr.status, xhr.responseText); + } + } + console.log("XHR send:", method, url); + try { + xhr.send(); + } catch(err) { + console.log("XHR EXC :", method, url, "->", err); + err_cb(599, err); + } +} + +function dispatchJson(resp, ok_cb, err_cb) { + var j; + try { j = JSON.parse(resp); } + catch(err) { + console.log("JSON parse error: " + err + ". In: " + resp); + err_cb(500, "JSON parse error: " + err); + return; + } + ok_cb(j); +} + +function ajaxJson(method, url, ok_cb, err_cb) { + ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); +} + +function ajaxSpin(method, url, ok_cb, err_cb) { + $("#spinner").removeAttribute('hidden'); + ajaxReq(method, url, function(resp) { + $("#spinner").setAttribute('hidden', ''); + ok_cb(resp); + }, function(status, statusText) { + $("#spinner").setAttribute('hidden', ''); + //showWarning("Error: " + statusText); + err_cb(status, statusText); + }); +} + +function ajaxJsonSpin(method, url, ok_cb, err_cb) { + ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); +} + +//===== main menu, header spinner and notification boxes + +onLoad(function() { + var l = $("#layout"); + var o = l.childNodes[0]; + // spinner + l.insertBefore(m(''), o); + // notification boxes + l.insertBefore(m( + '
'), o); + // menu hamburger button + l.insertBefore(m(''), o); + // menu left-pane + var mm = m( + '\ + '); + l.insertBefore(mm, o); + + // make hamburger button pull out menu + var ml = $('#menuLink'), mm = $('#menu'); + bnd(ml, 'click', function (e) { + console.log("hamburger time"); + var active = 'active'; + e.preventDefault(); + toggleClass(l, active); + toggleClass(mm, active); + toggleClass(ml, active); + }); + + // populate menu via ajax call + var getMenu = function() { + ajaxJson("GET", "/menu", function(data) { + var html = "", path = window.location.pathname; + for (var i=0; i" + + "" + + data.menu[i] + ""); + } + $("#menu-list").innerHTML = html; + + v = $("#version"); + if (v != null) { v.innerHTML = data.version; } + }, function() { setTimeout(getMenu, 1000); }); + }; + getMenu(); +}); + +//===== Wifi info + +function showWifiInfo(data) { + Object.keys(data).forEach(function(v) { + el = $("#wifi-" + v); + if (el != null) { + if (el.nodeName === "INPUT") el.value = data[v]; + else el.innerHTML = data[v]; + } + }); + var dhcp = $('#dhcp-r'+data.dhcp); + if (dhcp) dhcp.click(); + $("#wifi-spinner").setAttribute("hidden", ""); + $("#wifi-table").removeAttribute("hidden"); + currAp = data.ssid; +} + +function getWifiInfo() { + ajaxJson('GET', "/wifi/info", showWifiInfo, + function(s, st) { window.setTimeout(getWifiInfo, 1000); }); +} + +//===== Notifications + +function showWarning(text) { + var el = $("#warning"); + el.innerHTML = text; + el.removeAttribute('hidden'); +} +function hideWarning() { + el = $("#warning").setAttribute('hidden', ''); +} +var notifTimeout = null; +function showNotification(text) { + var el = $("#notification"); + el.innerHTML = text; + el.removeAttribute('hidden'); + if (notifTimeout != null) clearTimeout(notifTimeout); + notifTimout = setTimeout(function() { + el.setAttribute('hidden', ''); + notifTimout = null; + }, 4000); +} + +//===== GPIO Pin mux card + +var currPin; +// pin={reset:12, isp:13, LED_conn:0, LED_ser:2} +function createInputForPin(pin) { + var input = document.createElement("input"); + input.type = "radio"; + input.name = "pins"; + input.data = pin.name; + input.className = "pin-input"; + input.value= pin.value; + input.id = "opt-" + pin.value; + if (currPin == pin.name) input.checked = "1"; + + var descr = m('"); + var div = document.createElement("div"); + div.appendChild(input); + div.appendChild(descr); + return div; +} + +function displayPins(resp) { + var po = $("#pin-mux"); + po.innerHTML = ""; + currPin = resp.curr; + resp.map.forEach(function(v) { + po.appendChild(createInputForPin(v)); + }); + var i, inputs = $(".pin-input"); + for (i=0; i Date: Tue, 14 Jul 2015 23:38:18 -0700 Subject: [PATCH 03/11] make esp-12 with 4MB flash work --- Makefile | 55 +++++++++++++++++++++++++++++++----------------- user/cgiflash.c | 4 +++- user/user_main.c | 1 + 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index cad8624..99d5617 100644 --- a/Makefile +++ b/Makefile @@ -29,11 +29,28 @@ ESPBAUD ?= 460800 # --------------- chipset configuration --------------- +# Pick your flash size: "512KB" or "4MB" +FLASH_SIZE ?= 4MB + +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 ESP_HOSTNAME ?= esp-link @@ -163,7 +180,6 @@ SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) $(BUILD_BASE)/espfs_img.o LIBS := $(addprefix -l,$(LIBS)) APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) -TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) USER1_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).user1.out) USER2_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).user2.out) @@ -202,16 +218,11 @@ endef .PHONY: all checkdirs clean webpages.espfs wiflash -all: echo_version checkdirs $(FW_BASE) firmware/user1.bin firmware/user2.bin +all: echo_version checkdirs $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin echo_version: @echo VERSION: $(VERSION) -$(TARGET_OUT): $(APP_AR) $(LD_SCRIPT) - $(vecho) "LD $@" - $(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ -# $(OBJDP) -x $(TARGET_OUT) | egrep '(espfs_img)' - $(USER1_OUT): $(APP_AR) $(LD_SCRIPT1) $(vecho) "LD $@" $(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT1) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ @@ -224,12 +235,11 @@ $(USER2_OUT): $(APP_AR) $(LD_SCRIPT2) $(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT2) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ # $(Q) $(OBJDP) -x $(TARGET_OUT) | egrep espfs_img -$(FW_BASE): $(TARGET_OUT) +$(FW_BASE): $(vecho) "FW $@" $(Q) mkdir -p $@ - $(Q) $(ESPTOOL) elf2image $(TARGET_OUT) --output $@/ -firmware/user1.bin: $(USER1_OUT) +$(FW_BASE)/user1.bin: $(USER1_OUT) $(FW_BASE) $(Q) $(OBJCP) --only-section .text -O binary $(USER1_OUT) eagle.app.v6.text.bin $(Q) $(OBJCP) --only-section .data -O binary $(USER1_OUT) eagle.app.v6.data.bin $(Q) $(OBJCP) --only-section .rodata -O binary $(USER1_OUT) eagle.app.v6.rodata.bin @@ -241,7 +251,7 @@ firmware/user1.bin: $(USER1_OUT) @echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available" $(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi -firmware/user2.bin: $(USER2_OUT) +$(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE) $(Q) $(OBJCP) --only-section .text -O binary $(USER2_OUT) eagle.app.v6.text.bin $(Q) $(OBJCP) --only-section .data -O binary $(USER2_OUT) eagle.app.v6.data.bin $(Q) $(OBJCP) --only-section .rodata -O binary $(USER2_OUT) eagle.app.v6.rodata.bin @@ -251,7 +261,6 @@ firmware/user2.bin: $(USER2_OUT) $(Q) mv eagle.app.flash.bin $@ $(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi - $(APP_AR): $(OBJ) $(vecho) "AR $@" $(Q) $(AR) cru $@ $^ @@ -262,7 +271,7 @@ $(BUILD_DIR): $(Q) mkdir -p $@ wiflash: all - ./wiflash $(ESP_HOSTNAME) firmware/user1.bin firmware/user2.bin + ./wiflash $(ESP_HOSTNAME) $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin flash: all $(Q) $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash \ @@ -302,24 +311,32 @@ endif # we also adjust the sizes of the segments 'cause we need more irom0 # in the end the only thing that matters wrt size is that the whole shebang fits into the # 236KB available (in a 512KB flash) -build/eagle.esphttpd.v6.ld: $(SDK_LDDIR)/eagle.app.v6.ld - $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ - $(SDK_LDDIR)/eagle.app.v6.ld >$@ +ifeq ("$(FLASH_SIZE)","512KB") build/eagle.esphttpd1.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.512.app1.ld $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ -e '/^ irom0_0_seg/ s/2B000/38000/' \ - $(SDK_LDDIR)/eagle.app.v6.new.512.app1.ld >$@ + $(SDK_LDDIR)/eagle.app.v6.new.512.app1.ld >$@ build/eagle.esphttpd2.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.512.app2.ld $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ -e '/^ irom0_0_seg/ s/2B000/38000/' \ - $(SDK_LDDIR)/eagle.app.v6.new.512.app2.ld >$@ + $(SDK_LDDIR)/eagle.app.v6.new.512.app2.ld >$@ +else +build/eagle.esphttpd1.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.1024.app1.ld + $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ + -e '/^ irom0_0_seg/ s/6B000/7C000/' \ + $(SDK_LDDIR)/eagle.app.v6.new.1024.app1.ld >$@ +build/eagle.esphttpd2.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.1024.app2.ld + $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ + -e '/^ irom0_0_seg/ s/6B000/7C000/' \ + $(SDK_LDDIR)/eagle.app.v6.new.1024.app2.ld >$@ +endif espfs/mkespfsimage/mkespfsimage: espfs/mkespfsimage/ $(Q) $(MAKE) -C espfs/mkespfsimage USE_HEATSHRINK="$(USE_HEATSHRINK)" GZIP_COMPRESSION="$(GZIP_COMPRESSION)" release: all $(Q) rm -rf release; mkdir -p release/esp-link - $(Q) cp firmware/user1.bin firmware/user2.bin $(SDK_BASE)/bin/blank.bin \ + $(Q) cp $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin $(SDK_BASE)/bin/blank.bin \ "$(SDK_BASE)/bin/boot_v1.4(b1).bin" wiflash release/esp-link $(Q) tar zcf esp-link.tgz -C release esp-link $(Q) rm -rf release diff --git a/user/cgiflash.c b/user/cgiflash.c index 2c5dbd4..85aaf97 100644 --- a/user/cgiflash.c +++ b/user/cgiflash.c @@ -22,8 +22,10 @@ Some flash handling cgi routines. Used for reading the existing flash and updati // Check that the header of the firmware blob looks like actual firmware... static char* ICACHE_FLASH_ATTR check_header(void *buf) { uint8_t *cd = (uint8_t *)buf; + uint32_t *buf32 = buf; + os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]); if (cd[0] != 0xEA) return "IROM magic missing"; - if (cd[1] != 4 || cd[2] > 3 || cd[3] > 0x40) return "bad flash header"; + if (cd[1] != 4 || cd[2] > 3 || (cd[3]>>4) > 6) return "bad flash header"; if (((uint16_t *)buf)[3] != 0x4010) return "Invalid entry addr"; if (((uint32_t *)buf)[2] != 0) return "Invalid start offset"; return NULL; diff --git a/user/user_main.c b/user/user_main.c index 57443ae..645d215 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -156,6 +156,7 @@ void user_init(void) { os_printf("exccause=%d epc1=0x%x epc2=0x%x epc3=0x%x excvaddr=0x%x depc=0x%x\n", rst_info->exccause, rst_info->epc1, rst_info->epc2, rst_info->epc3, rst_info->excvaddr, rst_info->depc); + os_printf("Flash map %d, chip %08X\n", system_get_flash_size_map(), spi_flash_get_id()); os_printf("** esp-link ready\n"); } From b0a477a1ecfc95453de153a1824c856ea7845df8 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Mon, 3 Aug 2015 20:56:39 -0700 Subject: [PATCH 04/11] clear bssid before reassociating --- user/cgiwifi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/user/cgiwifi.c b/user/cgiwifi.c index 7292aa4..0d96e96 100644 --- a/user/cgiwifi.c +++ b/user/cgiwifi.c @@ -261,6 +261,7 @@ static ETSTimer reassTimer; static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { os_printf("Wifi changing association\n"); wifi_station_disconnect(); + stconf.bssid_set = 0; wifi_station_set_config(&stconf); wifi_station_connect(); // Schedule check From bb5dfd082ace58f1716ef02a767f673b4a1f7cea Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Sat, 10 Oct 2015 11:57:31 +0200 Subject: [PATCH 05/11] conditionaly include "local.conf" from Makefile for convenience reasons included from Makefile, added to gitignore.. --- .gitignore | 1 + Makefile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a541909..9554f77 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ esp-link.sdf espfs/mkespfsimage/mman-win32/libmman.a .localhistory/ tools/ +local.conf diff --git a/Makefile b/Makefile index a1fe4c0..1b1c8ac 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ # `VERBOSE=1 make ...` will print debug info # `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 # Lots of work, in particular to support windows, by brunnels # Original from esphttpd and others... From 0cb217046da34cd9b66322592ba6df087fdd4f15 Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Mon, 23 Nov 2015 20:17:52 +0100 Subject: [PATCH 06/11] simple handler for system_os_task/system_os_post we wrap both functions in much easier ones (register_usr_task, post_usr_task). register_usr_task requires an os_task_t parameter (the task itself) and returns a task number (0...MAXUSRTASKS) which is later on used by "post_usr_task". register_usr_task is self-initializing. no static arrays - malloc only... --- esp-link/task.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ esp-link/task.h | 20 +++++++++++++ serial/uart.c | 11 +++---- 3 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 esp-link/task.c create mode 100644 esp-link/task.h diff --git a/esp-link/task.c b/esp-link/task.c new file mode 100644 index 0000000..879a694 --- /dev/null +++ b/esp-link/task.c @@ -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 + +#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; +} + diff --git a/esp-link/task.h b/esp-link/task.h new file mode 100644 index 0000000..2dfd5d8 --- /dev/null +++ b/esp-link/task.h @@ -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 diff --git a/serial/uart.c b/serial/uart.c index 8e61f7e..f7f07fa 100644 --- a/serial/uart.c +++ b/serial/uart.c @@ -18,6 +18,7 @@ * Heavily modified and enhanced by Thorsten von Eicken in 2015 */ #include "esp8266.h" +#include "task.h" #include "uart.h" #ifdef UART_DBG @@ -26,14 +27,10 @@ #define DBG_UART(format, ...) do { } while(0) #endif -#define recvTaskPrio 1 -#define recvTaskQueueLen 64 +LOCAL uint8_t uart_recvTaskNum; // UartDev is defined and initialized in rom code. extern UartDevice UartDev; - -os_event_t recvTaskQueue[recvTaskQueueLen]; - #define MAX_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)); 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 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 From 9ec3a30c87c53c98131789af969a1dfc4dc52632 Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Mon, 23 Nov 2015 21:21:37 +0100 Subject: [PATCH 07/11] syslog - a simple syslog client --- Makefile | 14 +++++--- esp-link/config.c | 40 +++++++++++++--------- esp-link/config.h | 6 ++++ esp-link/main.c | 64 ++++++++++++++++++++++++++++++++---- html/home.html | 16 +++++++++ include/espmissingincludes.h | 6 ++++ serial/serbridge.c | 4 ++- 7 files changed, 122 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index eb260e9..e235338 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ # Makefile heavily adapted to esp-link and wireless flashing by Thorsten von Eicken # Lots of work, in particular to support windows, by brunnels # Original from esphttpd and others... -#VERBOSE=1 +# VERBOSE=1 # --------------- toolchain configuration --------------- @@ -23,7 +23,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/ # Base directory of the ESP8266 SDK package, absolute # 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 # Typically you'll use https://github.com/themadinventor/esptool @@ -83,7 +83,7 @@ LED_SERIAL_PIN ?= 14 CHANGE_TO_STA ?= yes # Optional Modules -MODULES ?= mqtt rest +MODULES ?= mqtt rest syslog # --------------- esphttpd config options --------------- @@ -198,6 +198,10 @@ ifneq (,$(findstring rest,$(MODULES))) CFLAGS += -DREST endif +ifneq (,$(findstring syslog,$(MODULES))) + CFLAGS += -DSYSLOG +endif + # which modules (subdirectories) of the project to include in compiling LIBRARIES_DIR = libraries MODULES += espfs httpd user serial cmd esp-link @@ -205,7 +209,7 @@ MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*)) EXTRA_INCDIR = include . # libraries used in this project, mainly provided by the SDK -LIBS = c gcc hal phy pp net80211 wpa main lwip +LIBS = c gcc hal phy pp net80211 wpa main lwip # compiler flags using during compilation of source files CFLAGS += -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ @@ -355,7 +359,7 @@ flash: all $(Q) $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash -fs $(ET_FS) -ff $(ET_FF) \ 0x00000 "$(SDK_BASE)/bin/boot_v1.4(b1).bin" 0x01000 $(FW_BASE)/user1.bin \ $(ET_BLANK) $(SDK_BASE)/bin/blank.bin - + tools/$(HTML_COMPRESSOR): $(Q) mkdir -p tools ifeq ($(OS),Windows_NT) diff --git a/esp-link/config.c b/esp-link/config.c index 2b756c1..b2db4c2 100644 --- a/esp-link/config.c +++ b/esp-link/config.c @@ -9,21 +9,31 @@ FlashConfig flashConfig; FlashConfig flashDefault = { - 33, 0, 0, - MCU_RESET_PIN, MCU_ISP_PIN, LED_CONN_PIN, LED_SERIAL_PIN, - 115200, - "esp-link\0", // hostname - 0, 0x00ffffff, 0, // static ip, netmask, gateway - 0, // log mode - 0, // swap uart (don't by default) - 1, 0, // tcp_enable, rssi_enable - "\0", // api_key - 0, 0, 0, // slip_enable, mqtt_enable, mqtt_status_enable - 2, 1, // mqtt_timeout, mqtt_clean_session - 1883, 60, // mqtt port, mqtt_keepalive - "\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic - "\0", // system description - 1, // rx_pullup + .seq=33, .magic=0, .crc=0, + .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN, + .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN, + .baud_rate = 115200, + .hostname = "ems-link02\0", + .staticip = 0, + .netmask = 0x00ffffff, + .gateway = 0, + .log_mode = 0, + .swap_uart = 0, + .tcp_enable = 1, .rssi_enable = 0, + .api_key = "\0", + .slip_enable = 0, .mqtt_enable = 0, .mqtt_status_enable = 0, + .mqtt_timeout = 2, .mqtt_clean_session = 1, + .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 = "diskstation\0", + .syslog_host = "diskstation\0", + .syslog_minheap= 8192, + .syslog_filter = 7, + .syslog_showtick= 1, + .syslog_showdate= 0, }; typedef union { diff --git a/esp-link/config.h b/esp-link/config.h index 9b20df3..4ad37b7 100644 --- a/esp-link/config.h +++ b/esp-link/config.h @@ -25,6 +25,12 @@ typedef struct { char mqtt_status_topic[32]; char sys_descr[129]; // system description 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; extern FlashConfig flashConfig; diff --git a/esp-link/main.c b/esp-link/main.c index 3719d9c..2dc1dfa 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -30,10 +30,18 @@ #include "config.h" #include "log.h" #include +#include "syslog.h" +#include "sntp.h" static int ICACHE_FLASH_ATTR cgiSystemInfo(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. 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" }; +// 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 static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { char buff[1024]; @@ -115,13 +134,18 @@ static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { os_sprintf(buff, "{\"name\": \"%s\", \"reset cause\": \"%d=%s\", " "\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\"," "\"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], flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff), part_id ? "user2.bin" : "user1.bin", flashConfig.slip_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); @@ -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 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) { // schedule hostname change-over @@ -225,18 +269,24 @@ void user_init(void) { #endif struct rst_info *rst_info = system_get_rst_info(); - os_printf("Reset cause: %d=%s\n", 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("Reset cause: %d=%s", rst_info->reason, rst_codes[rst_info->reason]); + 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->excvaddr, rst_info->depc); 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)); + NOTICE("** esp-link ready"); + + enableSNTP(); - os_printf("** esp-link ready\n"); #ifdef MQTT + NOTICE("initializing MQTT"); mqtt_client_init(); #endif + NOTICE("initializing user application"); app_init(); + + NOTICE("waiting for work to do..."); } diff --git a/html/home.html b/html/home.html index ef99429..1341903 100644 --- a/html/home.html +++ b/html/home.html @@ -27,6 +27,20 @@ SLIP status MQTT status Serial baud + Syslog Server +
+ + + +
+ + SNTP Server +
+ + + +
+
@@ -145,6 +159,8 @@ onLoad(function() { makeAjaxInput("system", "description"); makeAjaxInput("system", "name"); + makeAjaxInput("system", "sntp"); + makeAjaxInput("system", "syslog"); fetchPins(); getWifiInfo(); getSystemInfo(); diff --git a/include/espmissingincludes.h b/include/espmissingincludes.h index bf4c9d5..5161862 100644 --- a/include/espmissingincludes.h +++ b/include/espmissingincludes.h @@ -3,6 +3,10 @@ #include #include +#include +#include +#include +#include //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. @@ -43,6 +47,8 @@ void ets_update_cpu_frequency(int freqmhz); #define DEBUG_SDK false #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_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2))); diff --git a/serial/serbridge.c b/serial/serbridge.c index 8d400fd..696d635 100644 --- a/serial/serbridge.c +++ b/serial/serbridge.c @@ -10,6 +10,7 @@ #include "console.h" #include "slip.h" #include "cmd.h" +#include "syslog.h" #define SKIP_AT_RESET @@ -404,11 +405,12 @@ serbridgeConnectCb(void *arg) #ifdef SERBR_DBG os_printf("Accept port %d, conn=%p, pool slot %d\n", conn->proto.tcp->local_port, conn, i); #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) { #ifdef SERBR_DBG os_printf("Aiee, conn pool overflow!\n"); #endif + syslog(SYSLOG_FAC_USER, SYSLOG_PRIO_WARNING, "esp-link", "Aiee, conn pool overflow!\n"); espconn_disconnect(conn); return; } From e84900dbc76c906fb240ca96eeb56c2692e8fabe Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Mon, 23 Nov 2015 21:21:37 +0100 Subject: [PATCH 08/11] syslog - a simple syslog client syslog UDP messages are send via syslog(uint8_t facility, uint8_t severity, const char tag[], const char message[], ...); the syslog function queues any msg on system heap. If heap reaches a minimum size (8kB), syslog stops queuing. As soon as Wifi connectivity is available, syslog will send out all queued messages. Queuing will be reenabled after all pending messages are sent. --- syslog/syslog.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ syslog/syslog.h | 93 ++++++++++++ 2 files changed, 462 insertions(+) create mode 100644 syslog/syslog.c create mode 100644 syslog/syslog.h diff --git a/syslog/syslog.c b/syslog/syslog.c new file mode 100644 index 0000000..0a84b67 --- /dev/null +++ b/syslog/syslog.c @@ -0,0 +1,369 @@ +/* + * syslog.c + * + * + * Copyright 2015 Susi's Strolch + * + * For license information see projects "License.txt" + * + */ + +#include +#include "config.h" +#include +#include +#include "task.h" + +#define SYSLOG_DBG +#ifdef SYSLOG_DBG +#define DBG_SYSLOG(format, ...) os_printf(format, ## __VA_ARGS__) +#else +#define DBG_SYSLOG(format, ...) do { } while(0) +#endif + +LOCAL os_timer_t check_udp_timer; +LOCAL struct espconn syslog_espconn; +LOCAL int 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(char *msg); +LOCAL void ICACHE_FLASH_ATTR syslog_check_udp(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_check_udp + * Description : check whether get ip addr or not + * Parameters : none + * Returns : none +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +syslog_check_udp(void) +{ + struct ip_info ipconfig; + DBG_SYSLOG("syslog_check_udp: state: %d ", syslogState); + + //disarm timer first + os_timer_disarm(&check_udp_timer); + + //get ip info of ESP8266 station + wifi_get_ip_info(STATION_IF, &ipconfig); + if (wifi_station_get_connect_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 { + DBG_SYSLOG("waiting 100ms\n"); + if ((wifi_station_get_connect_status() == STATION_WRONG_PASSWORD || + wifi_station_get_connect_status() == STATION_NO_AP_FOUND || + wifi_station_get_connect_status() == STATION_CONNECT_FAIL)) { + os_printf("*** connect failure!!! \r\n"); + } else { + //re-arm timer to check ip + os_timer_setfn(&check_udp_timer, (os_timer_func_t *)syslog_check_udp, NULL); + os_timer_arm(&check_udp_timer, 100, 0); + } + } + } + +LOCAL void ICACHE_FLASH_ATTR +syslog_udp_send_event(os_event_t *events) { + if (syslogQueue == NULL) + syslogState = SYSLOG_READY; + else { + int res, len = os_strlen(syslogQueue->msg); + DBG_SYSLOG("syslog_udp_send: %s\n", syslogQueue->msg); + 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->msg, len); + if (res != 0) + os_printf("syslog_udp_send: error %d\n", res); + } +} + +LOCAL void ICACHE_FLASH_ATTR +syslog_add_entry(char *msg) +{ + syslog_entry_t *se = NULL, + *q = syslogQueue; + + // ensure we have sufficient heap for the rest of the system + if (system_get_free_heap_size() > syslogHost.min_heap_size) { + se = os_zalloc(sizeof (syslog_entry_t) + os_strlen(msg) + 1); + os_strcpy(se->msg, msg); + se->next = NULL; + + if (q == NULL) + syslogQueue = se; + else { + while (q->next != NULL) + q = q->next; + q->next = se; // append msg to syslog queue + } + } else { + if (syslogState != SYSLOG_HALTED) { + syslogState = SYSLOG_HALTED; + os_printf("syslog_add_entry: Warning: queue filled up, halted\n"); + // add obit syslog message + } + } +} + +/****************************************************************************** + * 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; + DBG_SYSLOG("syslog_udp_sent_cb: %p\n", pespconn); + + // datagram is delivered - free and advance queue + syslog_entry_t *p = syslogQueue; + syslogQueue = syslogQueue -> next; + os_free(p); + + 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); + + syslogState = SYSLOG_WAIT; + syslogHost.min_heap_size = MINIMUM_HEAP_SIZE; + syslogHost.port = 514; + + 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() + } + 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 ); +} + + /****************************************************************************** + * 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, ...) +{ + char udp_payload[1024], + *p = udp_payload; + uint32_t tick = WDEV_NOW(); // 0 ... 4294.967295s + + DBG_SYSLOG("syslog: state=%d ", syslogState); + if (syslogState == SYSLOG_ERROR || + syslogState == SYSLOG_HALTED) + return; + + // The Priority value is calculated by first multiplying the Facility + // number by 8 and then adding the numerical value of the Severity. + int sl = os_sprintf(p, "<%d> ", facility * 8 + severity); + p += sl; + + // 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) + sl = 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); + + sl = 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); + } + p += sl; + + // add HOSTNAME APP-NAME PROCID MSGID + if (flashConfig.syslog_showtick) + sl = os_sprintf(p, "%s %s %lu.%06lu %d ", flashConfig.hostname, tag, tick / 1000000, tick % 1000000, syslog_msgid++); + else + sl = os_sprintf(p, "%s %s - %d ", flashConfig.hostname, tag, syslog_msgid++); + p += sl; + + // append syslog message + va_list arglist; + va_start(arglist, fmt); + sl = ets_vsprintf(p, fmt, arglist ); + va_end(arglist); + + DBG_SYSLOG("msg: %s\n", udp_payload); + syslog_add_entry(udp_payload); // add to message queue + + if (syslogState == SYSLOG_READY) { + syslogState = SYSLOG_SENDING; + syslog_send_udp(); + } + + if (syslogState == SYSLOG_NONE) { + //set a timer to check whether we got ip from router succeed or not. + os_timer_disarm(&check_udp_timer); + os_timer_setfn(&check_udp_timer, (os_timer_func_t *)syslog_check_udp, NULL); + os_timer_arm(&check_udp_timer, 100, 0); + syslogState = SYSLOG_WAIT; + } +} diff --git a/syslog/syslog.h b/syslog/syslog.h new file mode 100644 index 0000000..d2853b9 --- /dev/null +++ b/syslog/syslog.h @@ -0,0 +1,93 @@ +/* + * 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; + char msg[]; +}; + +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[], ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSLOG_H */ From f3dd7368d0eb270578996d78b2fc6fbc856f4bdc Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Mon, 23 Nov 2015 23:45:59 +0100 Subject: [PATCH 09/11] fix rebase / merge errors - missing LOG_xxx macros in syslog.h - fixed tag (esp-link) in LOG_xxx macro --- syslog/syslog.c | 6 ++++++ syslog/syslog.h | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/syslog/syslog.c b/syslog/syslog.c index 0a84b67..6d421f7 100644 --- a/syslog/syslog.c +++ b/syslog/syslog.c @@ -226,9 +226,15 @@ syslog_init(char *syslog_server) 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 } /****************************************************************************** diff --git a/syslog/syslog.h b/syslog/syslog.h index d2853b9..c39eb08 100644 --- a/syslog/syslog.h +++ b/syslog/syslog.h @@ -86,6 +86,22 @@ 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 From 538e79f1dcc9f51eb89e552c12d317adaf818a9d Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Tue, 24 Nov 2015 14:06:25 +0100 Subject: [PATCH 10/11] fixes/changes after pull request - changed defaults for Flashconfig - SNTP-Server: empty - Syslog-Server: empty - hostname: reverted to esp-link - heavy cleanup in syslog.c - removed debug messages - add local syslog_compose function --- esp-link/config.c | 6 +- syslog/syslog.c | 361 ++++++++++++++++++++++++---------------------- syslog/syslog.h | 3 +- 3 files changed, 194 insertions(+), 176 deletions(-) diff --git a/esp-link/config.c b/esp-link/config.c index b2db4c2..f962fdc 100644 --- a/esp-link/config.c +++ b/esp-link/config.c @@ -13,7 +13,7 @@ FlashConfig flashDefault = { .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN, .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN, .baud_rate = 115200, - .hostname = "ems-link02\0", + .hostname = "esp-link\0", .staticip = 0, .netmask = 0x00ffffff, .gateway = 0, @@ -28,8 +28,8 @@ FlashConfig flashDefault = { .mqtt_username= "\0", .mqtt_password = "\0", .mqtt_status_topic = "\0", .sys_descr = "\0", .rx_pullup = 1, - .sntp_server = "diskstation\0", - .syslog_host = "diskstation\0", + .sntp_server = "\0", + .syslog_host = "\0", .syslog_minheap= 8192, .syslog_filter = 7, .syslog_showtick= 1, diff --git a/syslog/syslog.c b/syslog/syslog.c index 6d421f7..ca22130 100644 --- a/syslog/syslog.c +++ b/syslog/syslog.c @@ -14,6 +14,8 @@ #include #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__) @@ -21,9 +23,11 @@ #define DBG_SYSLOG(format, ...) do { } while(0) #endif -LOCAL os_timer_t check_udp_timer; +#define WIFI_CHK_INTERVAL 1000 // ms to check Wifi statis +LOCAL os_timer_t wifi_chk_timer; + LOCAL struct espconn syslog_espconn; -LOCAL int syslog_msgid = 1; +LOCAL uint32_t syslog_msgid = 1; LOCAL uint8_t syslog_task = 0; LOCAL syslog_host_t syslogHost; @@ -31,8 +35,8 @@ LOCAL syslog_entry_t *syslogQueue = NULL; static enum syslog_state syslogState = SYSLOG_NONE; -LOCAL void ICACHE_FLASH_ATTR syslog_add_entry(char *msg); -LOCAL void ICACHE_FLASH_ATTR syslog_check_udp(void); +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); @@ -41,102 +45,159 @@ LOCAL void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsig #define syslog_send_udp() post_usr_task(syslog_task,0) /****************************************************************************** - * FunctionName : syslog_check_udp + * FunctionName : syslog_chk_wifi_stat * Description : check whether get ip addr or not * Parameters : none * Returns : none *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR -syslog_check_udp(void) +syslog_chk_wifi_stat(void) { - struct ip_info ipconfig; - DBG_SYSLOG("syslog_check_udp: state: %d ", syslogState); + struct ip_info ipconfig; + DBG_SYSLOG("syslog_chk_wifi_stat: state: %d ", syslogState); - //disarm timer first - os_timer_disarm(&check_udp_timer); + //disarm timer first + os_timer_disarm(&wifi_chk_timer); - //get ip info of ESP8266 station - wifi_get_ip_info(STATION_IF, &ipconfig); - if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != 0) - { + //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); + 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("waiting 100ms\n"); - if ((wifi_station_get_connect_status() == STATION_WRONG_PASSWORD || - wifi_station_get_connect_status() == STATION_NO_AP_FOUND || - wifi_station_get_connect_status() == STATION_CONNECT_FAIL)) { - os_printf("*** connect failure!!! \r\n"); - } else { - //re-arm timer to check ip - os_timer_setfn(&check_udp_timer, (os_timer_func_t *)syslog_check_udp, NULL); - os_timer_arm(&check_udp_timer, 100, 0); - } - } + 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, len = os_strlen(syslogQueue->msg); - DBG_SYSLOG("syslog_udp_send: %s\n", syslogQueue->msg); + 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->msg, len); - if (res != 0) + 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(char *msg) +syslog_add_entry(syslog_entry_t *entry) { - syslog_entry_t *se = NULL, - *q = syslogQueue; - - // ensure we have sufficient heap for the rest of the system - if (system_get_free_heap_size() > syslogHost.min_heap_size) { - se = os_zalloc(sizeof (syslog_entry_t) + os_strlen(msg) + 1); - os_strcpy(se->msg, msg); - se->next = NULL; - - if (q == NULL) - syslogQueue = se; - else { - while (q->next != NULL) - q = q->next; - q->next = se; // append msg to syslog queue - } - } else { - if (syslogState != SYSLOG_HALTED) { - syslogState = SYSLOG_HALTED; - os_printf("syslog_add_entry: Warning: queue filled up, halted\n"); - // add obit syslog message - } - } + 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 - *******************************************************************************/ + * 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; - DBG_SYSLOG("syslog_udp_sent_cb: %p\n", pespconn); + (void) pespconn; // datagram is delivered - free and advance queue - syslog_entry_t *p = syslogQueue; + syslog_entry_t *pse = syslogQueue; syslogQueue = syslogQueue -> next; - os_free(p); + os_free(pse); if (syslogQueue != NULL) syslog_send_udp(); @@ -144,14 +205,14 @@ syslog_udp_sent_cb(void *arg) 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) @@ -160,13 +221,9 @@ syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length) } #endif - /****************************************************************************** - * - *******************************************************************************/ - - /****************************************************************************** - * - *******************************************************************************/ +/****************************************************************************** + * + ******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg) { @@ -192,48 +249,47 @@ syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg) void ICACHE_FLASH_ATTR syslog_init(char *syslog_server) { - char host[32], *port = &host[0]; - - syslog_task = register_usr_task(syslog_udp_send_event); - - syslogState = SYSLOG_WAIT; - syslogHost.min_heap_size = MINIMUM_HEAP_SIZE; - syslogHost.port = 514; - - 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 + 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 + 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() - } + 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 ); + 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 ); + 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 } @@ -311,65 +367,26 @@ syslog_init(char *syslog_server) void ICACHE_FLASH_ATTR syslog(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...) { - char udp_payload[1024], - *p = udp_payload; - uint32_t tick = WDEV_NOW(); // 0 ... 4294.967295s - - DBG_SYSLOG("syslog: state=%d ", syslogState); - if (syslogState == SYSLOG_ERROR || - syslogState == SYSLOG_HALTED) - return; - - // The Priority value is calculated by first multiplying the Facility - // number by 8 and then adding the numerical value of the Severity. - int sl = os_sprintf(p, "<%d> ", facility * 8 + severity); - p += sl; - - // 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) - sl = 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); - - sl = 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); - } - p += sl; - - // add HOSTNAME APP-NAME PROCID MSGID - if (flashConfig.syslog_showtick) - sl = os_sprintf(p, "%s %s %lu.%06lu %d ", flashConfig.hostname, tag, tick / 1000000, tick % 1000000, syslog_msgid++); - else - sl = os_sprintf(p, "%s %s - %d ", flashConfig.hostname, tag, syslog_msgid++); - p += sl; - - // append syslog message - va_list arglist; - va_start(arglist, fmt); - sl = ets_vsprintf(p, fmt, arglist ); - va_end(arglist); - - DBG_SYSLOG("msg: %s\n", udp_payload); - syslog_add_entry(udp_payload); // add to message queue - - if (syslogState == SYSLOG_READY) { - syslogState = SYSLOG_SENDING; - syslog_send_udp(); - } - - if (syslogState == SYSLOG_NONE) { - //set a timer to check whether we got ip from router succeed or not. - os_timer_disarm(&check_udp_timer); - os_timer_setfn(&check_udp_timer, (os_timer_func_t *)syslog_check_udp, NULL); - os_timer_arm(&check_udp_timer, 100, 0); - syslogState = SYSLOG_WAIT; - } + 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 + } } diff --git a/syslog/syslog.h b/syslog/syslog.h index c39eb08..f13d383 100644 --- a/syslog/syslog.h +++ b/syslog/syslog.h @@ -78,7 +78,8 @@ struct syslog_host_t { typedef struct syslog_entry_t syslog_entry_t; struct syslog_entry_t { syslog_entry_t *next; - char msg[]; + uint16_t datagram_len; + char datagram[]; }; syslog_host_t syslogserver; From 30ff23c0e2979ba21a72a4f73a617ba37227c706 Mon Sep 17 00:00:00 2001 From: susisstrolch Date: Tue, 24 Nov 2015 15:46:28 +0100 Subject: [PATCH 11/11] espmissingincludes.h encapsulate os_printf macro with do/while to avoid unwanted side effects during macro expansion --- include/espmissingincludes.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/espmissingincludes.h b/include/espmissingincludes.h index 5161862..2c35965 100644 --- a/include/espmissingincludes.h +++ b/include/espmissingincludes.h @@ -53,10 +53,11 @@ int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__(( int os_printf_plus(const char *format, ...) __attribute__((format(printf, 1, 2))); #undef os_printf -#define os_printf(format, ...) \ - system_set_os_print(true); \ - os_printf_plus(format, ## __VA_ARGS__); \ - system_set_os_print(DEBUG_SDK); // int os_printf(const char *format, ...) +#define os_printf(format, ...) do { \ + system_set_os_print(true); \ + os_printf_plus(format, ## __VA_ARGS__); \ + system_set_os_print(DEBUG_SDK); \ + } while (0) // memory allocation functions are "different" due to memory debugging functionality