// 使用ws模块
const { monitorEventLoopDelay } = require('perf_hooks');
const WebSocket = require('ws');

// npm i stickpackage
// npm i ws

var ws = new WebSocket("ws://jiangyi.site:11111/");

let stringsArray = [
    "get:version=?",
    "get:heart_beat=?",
    "get:time=?",

    "get:work_status=?",
    "get:fire_status=?",
    "get:fault_status=?",

    "get:humidity=?",
    "get:temperature=?",
    "get:cur_photosen0=?",
    "get:photosen0=?",
    "get:net=?",
    "get:event_num=?",
    "get:warning_num=?",

    // "set:extra_time=180",
    // "set:standing_time=10",
    // "set:interval_time=600",

    // "set:photosen0=6000,6000,6000,6000",
    // "set:time=24,9,15,21,53,0",
    // "set:reset=1",
    // "set:net=WIFI24,12345678,qq.com,1883,user,123456",
    // "set:event_num=1000",
    // "set:warning_num=1000",
    // "set:erase_bit=7",
];
let strings_i = 0;



function bin2String(array) {
    return String.fromCharCode.apply(String, array);
}

function calculateChecksum16bit(code) {
    let sum = 0;
    for (let i = 0; i < code.length; i++) {
        sum += code[i]&0xff;
        // console.log("sum:"+ sum +",i:"+ code[i] );
    }
    // 将结果转换为16位二进制字符串
    return sum&0xffff;
}

function stringToByteArray(str) {
    const encoder = new TextEncoder(); // 创建TextEncoder实例
    const bytes = encoder.encode(str); // 将字符串转换为字节序列
    return bytes; // 返回字节数组
}

//小端模式
function BytesToIntLittleEndian(bytes){
    var val = 0;
    for (var i = bytes.length - 1; i >= 0; i--) {        
        val += bytes[i];    
        if (i != 0) {
            val = val << 8;
        }    
    }
    return val;
}
 
//小端模式
//number 要转换的整形数值
//length 要转成什么byte数组，规定数组的长度
//如uint16，则lenght=2表示两个字节，转成的byte数组长度是length=2
//如uint32，则lenght=2表示两个字节，转成的byte数组长度是length=4
function IntToBytesLittleEndian(number, length){
    var bytes = [];
    var i = 0;
    do {
    bytes[i++] = number & (255);
    number = number>>8;
    } while ( i < length )
    return bytes;
}
 
//大端模式
function BytesToIntBigEndian(bytes){
    var val = 0;
    for (var i = 0; i < bytes.length; ++i) {        
        val += bytes[i];        
        if (i < bytes.length-1) {
            val = val << 8;
        }
    }
    return val;
}
 
//大端模式
//number 要转换的整形数值
//length 要转成什么byte数组，规定数组的长度
//如uint16，则lenght=2表示两个字节，转成的byte数组长度是length=2
//如uint32，则lenght=2表示两个字节，转成的byte数组长度是length=4
function IntToBytesBigEndian(number, length){
    var bytes = [];
    var i = length;
    do {
    bytes[--i] = number & (255);
    number = number>>8;
    } while (i)
    return bytes;
}

function Uint8ArrayToString(fileData){
    var dataString = "";
    for (var i = 0; i < fileData.length; i++) {
      dataString += String.fromCharCode(fileData[i]);
    }
   
    return dataString
  
  }

function stringToUint8Array(str){
    var arr = [];
    for (var i = 0, j = str.length; i < j; ++i) {
      arr.push(str.charCodeAt(i));
    }
   
    var tmpUint8Array = new Uint8Array(arr);
    return tmpUint8Array
  }
     

// 封包
function pack_send(str) {
    console.log("封包前:"+str);
    
    body = str;
    body = stringToByteArray(str);
    data_len = body.length;
    data_check = calculateChecksum16bit(body);
    let headBuf = Buffer.from([0x59, 0x4C, '<', (data_len>>8)&0xff, (data_len>>0)&0xff, (data_check>>8)&0xff, (data_check>>0)&0xff]);
    let pack_date = headBuf+body
    ws.send(pack_date);   
    console.log("封包后:"+pack_date);
}

function handler_recv(out){
    console.log("解析:" + out);
    str = String(out);
    let arr = str.split("=");
    if(arr.length == 2){
        let key = arr[0]
        let val = arr[1]
        if(key == "heart_beat"){
            let arr2 = val.split(",");
            if(arr2.length == 6){
                year = arr2[0];
                mon = arr2[1]; 
                day = arr2[2]; 
                hour = arr2[3];
                min = arr2[4]; 
                sec = arr2[5]; 
                console.log("heart_beat:20"+year+"-"+mon+"-"+day+" "+hour+":"+min+":"+sec);
            }

        }
    }
}


// 解包
let RecvBuf = "";
function unpack_recv(data) {
    console.log("recv " + data.length +":"+ data);
    // data添加到全局RecvBuf
    if(RecvBuf == ""){
        RecvBuf = data;
    }else{
        RecvBuf += data;
    }
    

    if(RecvBuf.length < 7){
        return;
    }

    // console.log(Buffer.from(RecvBuf.slice(0, 7)).toString('hex')); 

    //找包头 
    let index = -1;    
    for (i = 0; i < RecvBuf.length-3; i++) { 
        if(RecvBuf.slice(i, i+3) == "YL>"){
            index = i;
            break;
        }
    }
    if(index == -1){
        console.log("未找到到包头");
        return;
    }
    console.log("已查到包头, index:"+ index );

    // 如果不满足，断包了
    if(index+7 > RecvBuf.length){
        console.log("检查长度1失败");
        return;
    }
    console.log("检查长度1正常" );

    // console.log(RecvBuf.slice(index+3, index+5));   
    let data_len = BytesToIntBigEndian(RecvBuf.slice(index+3, index+5));
    // console.log("data_len:"+ data_len );
    // 检查实际长度
    if(index+7+data_len > RecvBuf.length || data_len == 0){
        console.log("检查长度2失败, data_len:" + data_len + "recv_len:" + RecvBuf.length );
        return;
    }    
    console.log("检查长度2正常" );

    // 检查校验码
    // console.log("5:" + RecvBuf[index+5]  +", 6:"+ RecvBuf[index+6] );
    let recv_check = BytesToIntBigEndian(RecvBuf.slice(index+5, index+7));
    let cal_check = calculateChecksum16bit(RecvBuf.slice(index+7,index+7+data_len));
    if(recv_check != cal_check){
        console.log("校验码失败, recv_check:" + recv_check  +", cal_check:"+ cal_check );
        return;
    }
    console.log("校验码成功" );

    //解析数据
    let start = index+7;
    let stop = index+7+data_len;
    console.log("start:" + start  +", stop:"+ stop );
    let out = RecvBuf.slice(index+7,index+7+data_len);

    // 处理out数据
    handler_recv(out);

    // 留下剩余数据：正常情况下长度=0：无剩余数据
    let old_len = data.length;
    RecvBuf = RecvBuf.slice(index+7+data_len);
    console.log("剩余数据:" + RecvBuf);
}


// 设置一个每5000毫秒执行一次的定时器
setInterval(function() {
    array = stringsArray[strings_i];
    pack_send(array);


    strings_i++;
    if(strings_i >= stringsArray.length){
        strings_i = 0;
    }
}, 5000);



ws.onopen = function(evt) {
	console.log("Connection open ...");
};
 
ws.onmessage = function(evt) {
    unpack_recv(evt.data); //string
};
 
ws.onclose = function(evt) {
	console.log("Connection closed.");
};


