You are reading a single comment by @SergeP and its replies. Click here to read the full conversation.
  • I've cleaned my code for big clock, now it is more regular. At the same time @Wilberforce and @JumJum have improved ESP32 build. So I've just cleaned my code even more by removing unnecessary MQTT and NTP implementations.
    Now the code works on newest Travis build for ESP32. I think it will work on v2.01 as well.
    If you do not need Russian months names just remove var MC and its usage - it is just names mapping.
    Additional fields on display may get data from http requests or MQTT channel bigclock/in/temp_1 ... temp_4 (because I use the fields to show temperatures collected by other sensors). If first symbol of the message is ', field icon is omitted. If there is no new data, '---' is shown after timeout.
    The program may be easily extended to show more fields on larger display or with multiplexing.
    Some ugly code is still present, mostly because I don't understand internal implementation of some components (for example, I have not found sntp_init() implementation and so do not know SNTP renewal interval and also SNTP timezone and E.setTimeZone() interaction).

    var DevName='bigclock';
    var DevNum=1;
    var FullName=DevName+'_'+DevNum;
    
    var neopixel = require("neopixel");
    E.setTimeZone(3);
    var wifi=require("Wifi");
    
    //var tnum;
    function getNTP() {
      wifi.setSNTP("pool.ntp.org",0);
    //  tnum=setTimeout(getNTP,24*3600*1000);
    }
    wifi.on('connected', ()=>setTimeout(getNTP,30000));
    
    //--------------------------------------­-------------------------------
    //----------------------- Additions to font ---------------------------
    //--------------------------------------­-------------------------------
    
    //require("Font6x8").add(Graphics);
    var gt = Graphics.createArrayBuffer(16,64,24,{zig­zag:true,color_order:'grb'});
    gt.setRotation(3,1);
    var font = atob("AAAAAPoAwADAAFhw2HDQAGSS/5JMAGCW+L­zSDAxSolIMEsAAPEKBAIFCPABIMOAwSAAQEHwQEA­ABBgAQEBAQAAIAAwwwwAB8ipKifABA/gBChoqSYg­CEkrLSjAAYKEj+CADkoqKinAA8UpKSDACAgI6wwA­BskpKSbABgkpKUeAAiAAEmABAoRAAoKCgoKABEKB­AAQIqQYAA8WqW9RDgOOMg4DgD+kpKSbAB8goKCRA­D+goJEOAD+kpKCAP6QkIAAfIKCklwA/hAQEP4A/g­AMAgIC/AD+EChEggD+AgICAP5AIED+AP7AMAz+AH­yCgoJ8AP6QkJBgAHyChoN8AP6QmJRiAGSSkpJMAI­CA/oCAAPwCAgL8AOAYBhjgAPAOMA7wAMYoECjGAM­AgHiDAAI6SosIA/4EAwDAMAwCB/wBAgEAAAQEBAQ­EBEn6SggQABCoqHgD+IiIcABwiIhQAHCIi/gAcKi­oYACB+oIAAGCUlPgD+ICAeAL4AAQG+AP4IFCIA/A­IAPiAeIB4APiAgHgAcIiIcAD8kJBgAGCQkPwA+EC­AgABIqKiQAIPwiADwCAjwAIBgGGCAAOAYIBjgAIh­QIFCIAIRkGGCAAJioyIgAQboEA5wCBbhAAQIDAQI­AAPFqlpUI8");
    var widths = atob("BAIEBgYGBgIEBAYGAwUCBQYDBgYGBgYGBg­YCAwQGBAUGBgYGBgUFBgYCBgYFBgYGBgYGBgYGBg­YGBgUDBQMEBgYFBQUFBQUFBQIEBQMGBQUFBQUFBA­UGBgYGBQQCBAYG");
    font+='\x08\x1E\x32\x52\x32\x1E\x08';
    font+='\x41\x93\xAF\x79\xA1\x91\x41';
    widths+='\x07\x07';
    font+='\x62\x94\x98\x90\xFE\x00';
    font+='\x3E\x08\x08\x3E\x00';
    font+='\x3E\x2A\x2A\x14\x00';
    font+='\x78\x84\xFE\x84\x78\x00';
    font+='\x3E\x20\x20\x3E\x00';
    font+='\xFE\x0C\x30\x40\xFE\x00';
    font+='\x3E\x08\x1C\x22\x1C\x00';
    font+='\x06\x18\x20\x3E\x00';
    font+='\x3E\x20\x20\x20\x00';
    font+='\x3E\x08\x14\x22\x00';
    font+='\x20\x3E\x20\x00';
    font+='\x12\x2C\x28\x3E\x00';
    font+='\x03\x7E\x82\x82\xFE\x03\x00';
    widths+='\x06\x05\x05\x06\x05\x06\x06\x0­5\x05\x05\x04\x05\x07';
    
    //8  NNNN            NNN       N   N                                 NNN
    //4 N   N           N N N      N  NN                                N  N
    //2 N   N N  N NNN  N N N NNNN N N N N  N    NN NNNN N  N NNN  NNN  N  N
    //1  NNNN N  N N  N N N N N  N N N N N N N  N N N    N N   N  N  N  N  N
    //8   N N NNNN NNN  N N N N  N NN  N NNN N  N N N    NN    N   NNN  N  N
    //4  N  N N  N N  N  NNN  N  N NN  N N N N N  N N    N N   N   N N  N  N
    //2 N   N N  N NNN    N   N  N N   N N  N  N  N N    N  N  N  N  N NNNNNN
    //1                                                                N    N
    //    82   83   84    85   86    87   88    89   8A   8B   8C  8D    8E
    var MC={'Jan':'\x82\x83\x84', 'Feb':'\x85e\x84', 'Mar':'Map', 'Apr':'A\x86p', 'May':'Ma\x8D',
            'Jun':'\x87\x88\x83', 'Jul':'\x87\x88\x89', 'Aug':'A\x84\x8A', 'Sep':'Ce\x83',
            'Oct':'O\x8B\x8C', 'Nov':'Ho\x8D', 'Dec':'\x8Ee\x8B'};
    
    
    Graphics.prototype.setFont6x8 = function() {
        this.setFontCustom(font, 32, widths, 8);
    };
    
    Graphics.prototype.convertColorFromHTML = function(HTMLColor) {
        return parseInt(HTMLColor.substr(5,2)+HTMLColor­.substr(1,2)+HTMLColor.substr(3,2),16);
    };
    
    //--------------------------------------­--------------------
    //-------------------- main code ---------------------------
    //--------------------------------------­--------------------
    
    gt.setFont6x8();
    
    var br,d;
    
    var ClockBrightness=2,LampBrightness=0;
    var ClockB=(Math.pow(2,(ClockBrightness-1)/9­*8)+ClockBrightness/4)/256;//add linear component to be better near brightness=1
    var LampB =(Math.pow(2,(LampBrightness -1)/9*8)+LampBrightness /4)/256;//add linear component to be better near brightness=1
    
    //var TempIn='---', TempOut='---', TempX1='---', TempX2='---';
    
    function drawFieldDefault(fieldNum) {
      var clr=E.HSBtoRGB(fields[fieldNum].hs.h,fie­lds[fieldNum].hs.s,ClockB,true);
      gt.setColor(clr[0]/255,clr[1]/255,clr[2]­/255);
      var text=(fields[fieldNum].text[0]=="'")?
        fields[fieldNum].text.substr(1,20): //No icon if started with '
        (fields[fieldNum].icon+fields[fieldNum].­text);
      gt.drawString(text,((fields[fieldNum].w-­gt.stringWidth(text))/2|0)+fields[fieldN­um].x,fields[fieldNum].y);
    }
    
    var fields=[
      {x:0, y:0, w:32,hs:{h:0.6,  s:1  }, view:[0,1], drawField:drawFieldDefault, icon:''    , text:'---'},
      {x:32,y:0, w:32,hs:{h:0.5,  s:1  }, view:[0,1], drawField:drawFieldDefault, icon:''    , text:'---'},
      {x:0, y:8, w:32,hs:{h:0,    s:0  }, view:[0],   drawField:drawFieldDefault, icon:'\x80', text:'---', timeout:undefined},
      {x:32,y:8, w:32,hs:{h:0.334,s:1  }, view:[0],   drawField:drawFieldDefault, icon:'\x81', text:'---', timeout:undefined},
      {x:0, y:8, w:32,hs:{h:0.26, s:0.6}, view:[1],   drawField:drawFieldDefault, icon:'\x81', text:'---', timeout:undefined},
      {x:32,y:8, w:32,hs:{h:0.1  ,s:0.6}, view:[1],   drawField:drawFieldDefault, icon:'\x81', text:'---', timeout:undefined}
    ];
    var currentView=0;
    var updateCounter=0;
    function updateField(fieldNum) {
      updateCounter++;
      if(updateCounter==1) setTimeout(function() {
        if(updateCounter) {
          var clr=E.HSBtoRGB(0,0.01,LampB,true);
          gt.setBgColor(clr[0]/255,clr[1]/255,clr[­2]/255);
          gt.clear();
    
          for(let i=0;i<fields.length;i++)
            if(fields[i].view.indexOf(currentView)!=­-1) fields[i].drawField(i);
          neopixel.write(D2, gt.buffer);
          updateCounter=0;
        }
      },1200);
    }
    
    function updateSettings() {
      //ugly hack because updateField does not really use fieldNum
      updateField(-1);
    }
    
    function setView(vnum) {
      currentView=vnum;
      updateField(-1);
    }
    
    var vcnt=0;
    setInterval(function() {
      if(++vcnt==10){ vcnt=0; setView(0); }
      if(vcnt==7) setView(1);
    },1000);
    
    var oldTime, newTime;
    
    function prepareTime() {
      var ds=Date().toString();
      newTime=ds.substr((ds[14]==' ')?15:16,5);
      if(oldTime != newTime) {
        oldTime=newTime;
        fields[1].text = newTime;
        fields[0].text = Date().getDate()+' '+MC[Date().toString().substr(4,3)];
        updateField(0);
        updateField(1);
      }
    }
    setInterval(prepareTime,1000);
    
    var mqtt_server = "192.168.1.40"; // the ip of your MQTT broker
    var mqtt_options = { // ALL OPTIONAL - the defaults are below
      client_id : FullName,   // the client ID sent to MQTT - it's a good idea to define your own static one based on `getSerial()`
    };
    
    var mqtt=require("MQTT").create(mqtt_server,­mqtt_options);
    
    mqtt.on('disconnected', function() {
      console.log("MQTT disconnected... reconnecting.");
      setTimeout(function() {
        var status=wifi.getDetails();
        if( status.status && 
            status.status=="connected" && 
            !mqtt.connected 
          ) mqtt.connect();
      }, 30000);
    });
    
    wifi.on('connected', ()=>{
      mqtt.connect();
      setTimeout(getNTP,30000);
    });
    
    setInterval(()=>{
      var status=wifi.getDetails();
      if(!status.status || status.status != "connected")
      {
        if(tnum) {
          clearTimeout(tnum);
          tnum=undefined;
        }
        wifi.restore();
      }
    },60000);
    
    function prepareTemp(msg,i) {
      if(msg[0] != "'") {
        let Temp=parseFloat(msg);
        fields[1+i].text=((Temp>0)?'+':'')+Temp.­toFixed(1);
      }
      else
        fields[1+i].text=msg.substr(0,20);
      if(fields[1+i].timeout) clearTimeout(fields[1+i].timeout);
      fields[1+i].timeout=setTimeout((i)=>{fie­lds[1+i].text='---'; fields[1+i].timeout=undefined;updateFiel­d(1+i);},300000,i);
      updateField(1+i);
    }
    
    neopixel.write(D2, gt.buffer);
    neopixel.write(D2, gt.buffer);
    
    var http=require("http");
    
    function onPageRequest(req, res) {
    //  console.log('pr',req.url,Date().toString­());
      var a = url.parse(req.url, true);
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.write('<html><body>');
      res.write('<script src="https://cdnjs.cloudflare.com/ajax/l­ibs/jscolor/2.0.4/jscolor.min.js"></scri­pt>');
      res.write('<script>function update(hsv) { location.search="?time_color_h="+hsv[0]+­"&time_color_s="+hsv[1];}</script>'); 
      res.write('<button class="jscolor {mode:\'HS\',valueElement:null,value:\'6­6ccff\'}" style="border:2px solid black" onchange="update(this.jscolor.hsv)">Pick­ a color</button>');
    //  ,value:\'66ccff\'
    //  res.write('<p>Pin is '+(BTN.read()?'on':'off')+'</p>');
    //  res.write('<div>Mode: <a href="?mode=lamp">Lamp</a> <a href="?mode=clock">clock</a></div>');
      res.write('<div>Clock brightness: ');
      for(let i=0; i<=10; i++)
        res.write(' <a href="?clock_brightness='+i+'">'+i+'</a>­');
      res.write('</div>');
      res.write('<div>Lamp brightness: ');
      for(let i=0; i<=10; i++)
        res.write(' <a href="?lam p_brightness='+i+'">'+i+'</a>');
      res.write('</div>');
      res.end('</body></html>');
      if (a.query) {
        for(let i=1;i<=fields.length-2;i++)
          if("temp_"+i in a.query) {
            prepareTemp(a.query["temp_"+i],i);
          }
        if("lamp_brightness" in a.query) {
          LampBrightness=E.clip(parseInt(a.query.l­amp_brightness),0,10);
          LampB =(Math.pow(2,(LampBrightness -1)/9*8)+LampBrightness /4)/256;//add linear component to be better near brightness=1
          updateSettings();
        }
        if("clock_brightness" in a.query) {
          ClockBrightness=E.clip(parseInt(a.query.­clock_brightness),0,10);
          ClockB=(Math.pow(2,(ClockBrightness-1)/9­*8)+ClockBrightness/4)/256;//add linear component to be better near brightness=1
          updateSettings();
        }
      }
    //  console.log('pr2',Date().toString());
    }
    
    require("http").createServer(onPageReque­st).listen(80);
    
    mqtt.on('connected', function() {
      mqtt.subscribe([
        DevName+"/in/#",
        FullName+"/in/#"
      ]);
    });
    
    mqtt.on('publish', function (pub) {
      console.log("topic: "+pub.topic);
      console.log("message: "+pub.message);
      var command=pub.topic.split("/",3)[2];
      var i;
      for(i=1;i<=fields.length-2;i++)
        if(command == "temp_"+i)
          prepareTemp(pub.message,i);
      if(command == "lamp_brightness") {
        LampBrightness=E.clip(parseInt(pub.messa­ge),0,10);
        LampB =(Math.pow(2,(LampBrightness -1)/9*8)+LampBrightness /4)/256;//add linear component to be better near brightness=1
        updateSettings();
      }
      else if(command == "clock_brightness") {
        ClockBrightness=E.clip(parseInt(pub.mess­age),0,10);
        ClockB=(Math.pow(2,(ClockBrightness-1)/9­*8)+ClockBrightness/4)/256;//add linear component to be better near brightness=1
        updateSettings();
      }
      else if(command == "eval") {
        setTimeout( function (s) {
          var res=eval(s);
          console.log(res);
          mqtt.publish(DevName+'/out/eval', JSON.stringify(res));
          updateSettings();
        },0,pub.message);
      }
    });
    
    
    //---------- auto brightness ----------
    setInterval(function() {
      var newCB=ClockBrightness;
      if(newTime=="07:00")
          newCB=3;
      if(newTime=="22:00")
          newCB=1;
      if(newCB != ClockBrightness) {
        ClockBrightness=newCB;
        ClockB=(Math.pow(2,(ClockBrightness-1)/9­*8)+ClockBrightness/4)/256;//add linear component to be better near brightness=1
        updateSettings();
      }  
    },60000);
    
    //---------------- init ---------------
    
    if(wifi.getDetails().status=="connected"­) {
      getNTP();
      mqtt.connect();
    }
    
About

Avatar for SergeP @SergeP started