var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey  = fs.readFileSync('sslcert/private.key.nopassphrase', 'utf8');
var certificate = fs.readFileSync('sslcert/cert.pem', 'utf8');

var credentials = {key: privateKey, cert: certificate};

express = require('express');  //web server
app = express();

http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);


//serverHttp = require('http').createServer(app);
serverHttps = require('https').createServer(credentials, app);

io = require('socket.io').listen(serverHttps);	//web socket server


//serverHttp.listen(80); //start the webserver on port 80
serverHttps.listen(443); //start the webserver on port 443

app.use(express.static('sb-admin')); //tell the server that ./dash/ contains the static webpages

console.log("connect to http://192.168.1.183");



//------------------------ 
//     SERIAL PORT
//------------------------


var serialport = require("serialport");
var SerialPort = serialport;

var portName = "/dev/ttyUSB0";

var myPort = new SerialPort(portName, {
  baudrate: 115200,
  parser: serialport.parsers.byteDelimiter([13,10])
});


//---------------------------------- 
//     VARIABLES INITIALIZATION
//----------------------------------

var pld =[];
var msg =[];
var payload = "";
var temp195 = "--";
var hum195 = "--";
var temp187 = "--";
var hum187 = "--";


//---------------------------------- 
//          WEBSOCKET & MAIN LOOP
//----------------------------------


// Send current time every sec
setInterval(sendTime, 1000);

//io.sockets.on('connection', sendTime);

console.log("running");


myPort.on('open', onOpen);
//myPort.on('data', onData);
myPort.on('close', onClose);
myPort.on('error', onError);

io.sockets.on('connection', function (socket) {
      sendTime();
      io.sockets.emit('initialize');
   
    // When the server receives a .message. type signal from the client   
   socket.on('message', function (message) {

    console.log('Client message: ' + message);

    switch(message) {

     case "AC_ON":
        console.log('Case: AC_ON');
        DomotixNetO('s',1,4,1,"AC_ON");
        break;
     case "AC_OFF":
        console.log('Case: AC_OFF');
        DomotixNetO('s',1,4,1,"AC_OFF");
        break;
     case "AC_HEAT":
        console.log('Case: AC_HEAT');
        DomotixNetO('s',1,4,1,"AC_HEAT");
        break;
     case "AC_COOL":
        console.log('Case: AC_COOL');
        DomotixNetO('s',1,4,1,"AC_COOL");
        break;
     case "AC_DRY":
        console.log('Case: AC_DRY');
        DomotixNetO('s',1,4,1,"AC_DRY");
        break;
     case "AC_AUTO":
        console.log('Case: AC_AUTO');
        DomotixNetO('s',1,4,1,"AC_AUTO");
        break;
     case "AC_T+":
        console.log('Case: AC_T+');
        DomotixNetO('s',1,4,1,"AC_T+");
        break;
     case "AC_T-":
        console.log('Case: AC_T-');
        DomotixNetO('s',1,4,1,"AC_T-");
        break;
     case "AC_PROFILE_NORMAL":
        console.log('Case: AC_PROFILE_NORMAL');
        DomotixNetO('s',1,4,1,"AC_PROFILE_NORMAL");
        break;
     case "AC_PROFILE_QUIET":
        console.log('Case: HVAC_PROFILE_QUIET');
        DomotixNetO('s',1,4,1,"HVAC_PROFILE_QUIET");
        break;
     case "AC_PROFILE_ECONAVI":
        console.log('Case: AC_PROFILE_ECONAVI');
        DomotixNetO('s',1,4,1,"AC_PROFILE_ECONAVI");
        break;
     case "AC_PROFILE_AUTOCONFORT":
        console.log('Case: AC_PROFILE_AUTOCONFORT');
        DomotixNetO('s',1,4,1,"AC_PROFILE_AUTOCONFORT");
        break;

     case "AC_FAN1":
        console.log('Case: AC_FAN1');
        DomotixNetO('s',1,4,1,"AC_FAN2");
        break;
     case "AC_FAN2":
        console.log('Case: AC_FAN2');
        DomotixNetO('s',1,4,1,"AC_FAN2");
        break;
     case "AC_FAN3":
        console.log('Case: AC_FAN3');
        DomotixNetO('s',1,4,1,"AC_FAN3");
        break;
     case "AC_FAN4":
        console.log('Case: AC_FAN4');
        DomotixNetO('s',1,4,1,"AC_FAN4");
        break;
     case "AC_FAN5":
        console.log('Case: AC_FAN5');
        DomotixNetO('s',1,4,1,"AC_FAN5");
        break;
     case "AC_FANAUTO":
        console.log('Case: AC_FANAUTO');
        DomotixNetO('s',1,4,1,"AC_FANAUTO");
        break;
     case "AC_VANNEUD_AUTO":
        console.log('Case: AC_VANNEUD_AUTO');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_AUTO");
        break;
     case "AC_VANNEUD_S1":
        console.log('Case: AC_VANNEUD_S1');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_S1");
        break;
     case "AC_VANNEUD_S2":
        console.log('Case: AC_VANNEUD_S2');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_S2");
        break;
     case "AC_VANNEUD_S3":
        console.log('Case: AC_VANNEUD_S3');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_S3");
        break;
     case "AC_VANNEUD_S4":
        console.log('Case: AC_VANNEUD_S4');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_S4");
        break;
     case "AC_VANNEUD_S5":
        console.log('Case: AC_VANNEUD_S5');
        DomotixNetO('s',1,4,1,"AC_VANNEUD_S5");
        break;
     case "AC_VANNELR_AUTO":
        console.log('Case: AC_VANNELR_S1');
        DomotixNetO('s',1,4,1,"AC_VANNELR_S1");
        break;
     case "AC_VANNELR_L2":
        console.log('Case: AC_VANNELR_L2');
        DomotixNetO('s',1,4,1,"AC_VANNELR_L2");
        break
     case "AC_VANNELR_L1":
        console.log('Case: AC_VANNELR_L1');
        DomotixNetO('s',1,4,1,"AC_VANNELR_L1");
        break
     case "AC_VANNELR_MD":
        console.log('Case: AC_VANNELR_MD');
        DomotixNetO('s',1,4,1,"AC_VANNELR_MD");
        break
     case "AC_VANNELR_R1":
        console.log('Case: AC_VANNELR_R1');
        DomotixNetO('s',1,4,1,"AC_VANNELR_R1");
        break
     case "AC_VANNELR_R2":
        console.log('Case: AC_VANNELR_R2');
        DomotixNetO('s',1,4,1,"AC_VANNELR_R2");
        break

     case "VOL:1":
        DomotixNetO('s',1,4,1,"@VOL:1\r");
        console.log('Case: Marantz Vol:1 Up');
        break;
     case "VOL:2":
        DomotixNetO('s',1,4,1,"@VOL:2\r");
        console.log('Case: Marantz Vol:2 Down');
        break;
     case "VOL:?":
        DomotixNetO('s',1,4,1,"@VOL:?\r");
        console.log('Case: Marantz Vol:? Status');
        break;
     case "AMT:1":
        DomotixNetO('s',1,4,1,"@AMT:1\r");
        console.log('Case: Marantz AMT:1 Mute OFF');
        break;
     case "AMT:2":
        DomotixNetO('s',1,4,1,"@AMT:2\r");
        console.log('Case: Marantz Mute:2 Mute ON');
        break;
     case "AMT:0":
        DomotixNetO('s',1,4,1,"@AMT:0\r");
        console.log('Case: Marantz AMT:0 Toggle Mute');
        break;
     case "PWR:2":
        DomotixNetO('s',1,4,1,"@PWR:2\r");
        console.log('Case: Marantz Pwr:1 On');
        break;
     case "PWR:1":
        DomotixNetO('s',1,4,1,"@PWR:1\r");
        console.log('Case: Marantz Pwr:0 Off');
        break;
     case "PWR:?":
        DomotixNetO('s',1,4,1,"@PWR:?\r");
        console.log('Case: Marantz Pwr:? Status');
        break;
     case "SRC:?":
        DomotixNetO('s',1,4,1,"@SRC:?\r");
        console.log('Case: Marantz SRC:? Status');
        break;
     case "SRC:SAT":
        DomotixNetO('s',1,4,1,"@SRC:55\r");
        console.log('Case: Marantz SRC:SAT Up');
        break;
     case "SRC:DVD":
        DomotixNetO('s',1,4,1,"@SRC:22\r");
        console.log('Case: Marantz SRC:Kodi Up');
        break;
     case "SRC:TUN":
        DomotixNetO('s',1,4,1,"@SRC:G\r");
        console.log('Case: Marantz SRC:TUN Up');
        break;
     case "MSP:2":
        DomotixNetO('s',1,4,1,"@MSP:2\r");
        console.log('Case: Marantz MSP:2 Multiroom ON');
        break;
     case "MSP:1":
        DomotixNetO('s',1,4,1,"@MSP:1\r");
        console.log('Case: Marantz MSP:1 Multiroom OFF');
        break;
     case "MSP:?":
        DomotixNetO('s',1,4,1,"@MSP:?\r");
        console.log('Case: Marantz MSP:? Multiroom Power Status');
        break;
     case "MSC:SAT":
        DomotixNetO('s',1,4,1,"@MSC:5\r");
        console.log('Case: Marantz MSC:SAT Multiroom SAT');
        break;
     case "MSC:TUN":
        DomotixNetO('s',1,4,1,"@MSC:G\r");
        console.log('Case: Marantz MSC:TUN Multiroom Radio');
        break;
     case "MSC:?":
        DomotixNetO('s',1,4,1,"@MSC:?\r");
        console.log('Case: Marantz MSC:? Multiroom Source?');
        break;
     case "MSV:1":
        DomotixNetO('s',1,4,1,"@MSV:1\r");
        console.log('Case: Marantz MSV:2 Multiroom Vol+');
        break;
     case "MSV:2":
        DomotixNetO('s',1,4,1,"@MSV:2\r");
        console.log('Case: Marantz MSV:2 Multiroom Vol-');
        break;
     case "MSV:?":
        DomotixNetO('s',1,4,1,"@MSV:?\r");
        console.log('Case: Marantz MSV:? Multiroom Vol?');
        break;
     case "MSM:2":
        DomotixNetO('s',1,4,1,"@MSM:2\r");
        console.log('Case: Marantz MSM:2 Multiroom Mute ON');
        break;
     case "MSM:1":
        DomotixNetO('s',1,4,1,"@MSM:1\r");
        console.log('Case: Marantz MSM:1 Multiroom Mute OFF');
        break;
     case "Indoor":
        io.emit('update', {label: "temp187" ,value: temp187});
        io.emit('update', {label: "hum187" ,value: hum187});
        console.log('Case: Indoor Climate Request');
        break;
     case "Outdoor":
        io.emit('update', {label: "temp195" ,value: temp195});
//        io.emit('update', {label: "hum195" ,value: hum195});
        console.log('Case: Outdoor Climate Request');
        break;
     default:
        console.log('Case: Default');
    }

  }) 
})


 
function onOpen(){
    console.log('port open. Data rate: ' + myPort.options.baudRate);
    myPort.on('data', onData);
    cn=0;
    c=0;
    p=0;    
    StartPosition=0;
}
 
function onData(data){
  console.log("Serial Input: "+data)
  DomotixNetI(data);
}

function DomotixNetI(dta){
 //console.log("dta: "+dta);
 var PayLo ="";
 if ((dta[0]=0x68) && (dta[1]=0x75)) {

   var swc = (DecVal(dta[6],dta[7]));
   console.log("Device Type: "+swc);
   switch(swc) {
/*     case 1:
        for (var d = 6; d < dta.length; d++) {
          PayLo += String.fromCharCode(dta[d]);
        }
        console.log("PayLo: "+PayLo,PayLo.length);
        valu=PayLo;
        io.emit('update', {label: 'LivingTemp' ,value: valu.toString()});
        break; */
     case 2:
       PayLo = ""; 
        for (var d = 10; d < dta.length; d=d+2) {
          PayLo += String.fromCharCode(DecVal(dta[d],dta[d+1]));
        }
        console.log("Case2 PayLo: "+PayLo);
        val2=PayLo.slice(5,PayLo.length-3);
        lbl=PayLo.slice(1,5)
        io.emit('update', {label: lbl.toString() ,value: val2.toString()});
        console.log("Marantz "+lbl,val2);
        break;
     case 3:
        PayLo = "";
        for (var d = 10; d < dta.length-5; d=d+2) {
          PayLo += String.fromCharCode(DecVal(dta[d],dta[d+1]));
        }
        console.log("Case3 PayLo: "+PayLo);
        var decval = DecVal(dta[8],dta[9]);
        console.log("DevicID: "+decval);
        if (decval == 195){
          var val3 = PayLo.split(":");
          temp195=val3[0].toString();
          hum195=val3[1].toString();
          console.log("val: "+val3);
          io.emit('update', {label: "temp195" ,value: temp195});
          io.emit('update', {label: "hum195" ,value: hum195});

        }
        if (decval == 187){
          var val4 = PayLo.split(":");
          console.log("val4: "+val4);
          temp187=val4[0].toString();
          hum187=val4[1].toString();
          io.emit('update', {label: "temp187" ,value: temp187});
          io.emit('update', {label: "hum187" ,value: hum187});
        }
     break; 

   }
 }
}
 
function onClose(){
    console.log("Port is closed");
}
function onError(){
    console.log("something went horribly wrong");
}

function sendTime() {
    var d = new Date();

       io.emit('time', { time: pad(d.getHours())+':'+pad(d.getMinutes())+':'+pad(d.getSeconds()) });
}

function pad(n) {
    return (n < 10) ? ("0" + n) : n;
}

function DecVal(Hi,Lo){
var val = ((Hi&15)<<4)+(Lo&15);
return val;
}


//---------------------------------- 
//     DOMOTIX PROTOCOL 
//----------------------------------


function DomotixNetO(MsgTyp, NodeId, DeviceTyp, DeviceId, PayLoad){
   
   var Lenght = 10+PayLoad.length*2;
   var dataO = [ 'h', MsgTyp, EncHi(Lenght), EncLo(Lenght), EncHi(NodeId), EncLo(NodeId), EncHi(DeviceTyp), EncLo(DeviceTyp), EncHi(DeviceId), EncLo(DeviceId) ];
   var CheckSum ;
   var sum ;
   var PL =[];
   var l;
 
//   console.log("NodeId:"+NodeId," DeviceTyp:"+DeviceTyp," DeviceId:"+DeviceId);
//   console.log("Length: "+Lenght);
//   console.log("dataO: "+dataO);
//   console.log("PayLoad: "+PayLoad); 
 
   if (PayLoad != ""){
     l=0;
     for (k = 0; k < PayLoad.length; k++) {
       var ch = PayLoad[k];
       PL[l] =  EncHi(ch.charCodeAt(0));
       PL[l+1] =  EncLo(ch.charCodeAt(0));
       var h1 = PL[l];
       var l1 = PL[l+1];
//       console.log("PayLoad[k]: "+PayLoad[k]," ch: "+ch.charCodeAt(0),"Hi: "+h1,+h1.charCodeAt(0),"Lo: "+l1,l1.charCodeAt(0));
       l += 2;
     }

    var te = dataO.join("")+PL.join(""); 

//    console.log("dataO + PayLoad: "+te); 

//     for (e = 0; e < te.length; e++) {
//      var tp = te.charCodeAt(e);
//      console.log(tp);
//     }



//   for (j = 0; j < te.lenght; j++) {
//      sum = sum + parsInt(te.charCodeAt(j));
//      console.log(sum);
//   }
   CheckSum = ((~(sum))+1) ;
//   console.log("CheckSum: "+sum);
   te += CheckSum;
   te += 'z';

//   for (e = 0; e < te.length; e++) {
//      var tp = te.charCodeAt(e);
//   console.log(e,p);
//   }

//  console.log("Domotix Out te: "+te);
  myPort.write(te);
}
}

//---------------------------------------------------- 
//     HI & LO BYTE ENCODING for DOMOTIX PROTOCOL
//-----------------------------------------------------

function EncHi(byt){
  var res = String.fromCharCode(((byt & 240)>>4) + 48);
  return res;
}

function EncLo(byt){
  var res = String.fromCharCode((byt & 15) + 32);
  return res;
}



