---@diagnostic disable: lowercase-global, undefined-global



-- 适配的方案id
PLAN_ID=15



-- 更新日志
-- 2023.4.13
-- 检测流程编写完成
-- 2023.4.14
-- 发现未接触时检测电流有可能为1，此时会报芯片异常
-- 把接触异常电流<1改为<5
-- 2023.4.20
-- 打印出出错的任务代码
-- 2023.4.23
-- 调试代码解决异常代码不对的问题
-- 电压无法上升改为检测器异常
-- 修改因脚本产生的错误代码从0xd2(210)开始编码
-- "数据长度与方案不符",210
-- "方案ID不符",211
-- "检测项目不足，无法判定",212
-- "数据不合规",213
-- 2023.5.11
-- 修改脚本适配 雷管厂电解电容来料检测
-- 2023.5.12
-- 大于启停的时间从检测器异常改为芯片异常
-- 2023.5.19
-- 扫描uid，超出最大返回时间范围则显示芯片异常
-- 添加起爆充能失败的判断，此时返回芯片异常
-- 2023.6.29
-- 使用算数运算代替位运算



-- 方案配置文件：
-- cfg_name
-- 检测数据
-- check_data
-- 当前路径
-- get_path()
-- 打印表
-- prints:print_t()
-- json解码
-- json:decode()



-- 读取方案配置信息
check_cfg_file=io.open(cfg_name,"r")
check_cfg_str=check_cfg_file:read("*a")
check_cfg_file:close()
json_table = json:decode(check_cfg_str)


-- 表长度
function len(t)
    local res=0
    if(t==nil)then return 0 end
    for k,v in pairs(t) do
        res=res+1
    end
    return res
end

-- 截取数组
function mid(array,start,length)
    if(len(array)<(start+length-1)) then
        print("mid:out of range",start,length)
        return nil
    end
    return table.pack(table.unpack(array,start,start+length-1))
end


-- 把n插入t中，不允许重复
function insert(t,n)
    for k,v in pairs(t) do
        if(v==n) then
            return
        end
    end
    table.insert(t,n)
end


-- 删除t中的值n
function del(t,n)
    for k,v in pairs(t) do
        if(v==n) then
            table.remove(t,k)
            break
        end
    end
end

-- 删除t中除n之外的所有值
function only(t,n)
    for k,v in pairs(t) do
        if(v~=n) then
            -- table.remove(t,k)
            t[k]=nil
        end
    end
end



-- 计算2的n次幂
function exp2(n)
    local ret=1
    for i=1,n,1 do
        ret=ret*2
    end
    return ret
end





-- 8个字节描述执行结果0成功，1失败
function find_ack(index,acks)
    if(index>len(acks)*8) or index<1 then
        print("index out of range.index=",index)
        return false
    end
    local temp=acks[math.floor((index-1)/8)+1]
    local i=(index-1)%8
    if ((math.floor((temp % exp2(i+1))/exp2(i)))~=0) then
        return false
    else
        return true
    end
end


-- 8个字节描述执行与否，1执行，0未执行
function find_stat(index,stats)
    if(index>len(stats)*8) or index<1 then
        print("index out of range.index=",index)
        return false
    end
    local temp=stats[math.floor((index-1)/8)+1]
    local i=(index-1)%8
    if ((math.floor((temp % exp2(i+1))/exp2(i)))~=0) then
        return true
    else
        return false
    end
end


-- 展示任务回复，0成功，1失败
function show_acks(acks)
    -- prints:print_a(acks)
    print("执行结果:(0:ok;1:err)")
    local str=""
    for i=1,len(json_table["TaskArray"]),1 do
        local ack=find_ack(i,acks)
        if ack==true then
            str=str.."0, "
        else
            str=str.."1, "
        end
    end
    print(str)
end

-- 展示任务执行状态，0未执行，1已执行
function show_stats(stats)
    -- prints:print_a(stats)
    print("执行状态:(0:skiped;1:executed)")
    local str=""
    for i=1,len(json_table["TaskArray"]),1 do
        local stat=find_stat(i,stats)
        if stat==true then
            str=str.."1, "
        else
            str=str.."0, "
        end
    end
    print(str)
end






-- 统计指定index之前应该跳过的数据长度和当前index的返回长度
function calc_skip(index,tasks)
    local len=0
    -- for i=1,table.getn(tasks),1 do
    local i=1
    while i<index do
    -- for i=1,index,1 do
        -- print("calc_skip,index=",index,"i=",i)
        len=len+tasks[i]["ReturnCount"]
        i=i+1
    end
    -- print("calc_skip,len=",len)
    return len*2,tasks[index]["ReturnCount"]*2
end



-- 找到指定index的任务返回数和值,把两个字节合并为一个值
function find_return(index)
    local data=check_data
    local skip_len,len=calc_skip(index,json_table["TaskArray"])
    local ret={}
    local temp=mid(data,skip_len+1+16,len)
    if(temp==nil) then return ret end
    -- print("find_return,temp=")
    -- prints:print_a(temp)
    local len_t=math.floor(len/2)
    for i=1,len_t,1 do
        ret[i]=temp[i*2-1]+(temp[i*2]*exp2(8))
    end
    return ret
end




-- JQ_Test_PowerPrapare,       //0 电源准备        1
-- JQ_Test_PowerOn,            //1 上电充能        1,(3,充能值(时间)超上限(开路/短路)、总线电压超下限(短路))
-- JQ_Test_SetBusV,	           //2 设置总线电压    1
-- JQ_Test_BaseCur,	           //3 获取总线电流    1,3(总线电流偏大(漏流/短路)、总线电流为0(开路))
-- JQ_Test_ScanUID,            //4 扫描UID         1,2,3,5(能扫描到uid即认为芯片正常)
-- JQ_Test_PWCheck,	           //5 密码验证
-- JQ_Test_ReadChipID,         //6 读取芯片代码    1,2,3,5(能读到id即认为芯片正常)
-- JQ_Test_OTPCheck,           //7 OTP检测
-- JQ_Test_FTCheck,            //8 工厂测试检测
-- JQ_Test_ReadState,          //9 读取状态
-- JQ_Test_WriteUserInfo,      //10 写工厂信息
-- JQ_Test_ChgEnergy,          //11 充能统计
-- JQ_Test_CheckDAC,           //12 充电电压检测
-- JQ_Test_WaitDelay,          //13 延时等待
-- JQ_Test_SetDelay,           //14 设置延时
-- JQ_Test_ReadDelay,          //15 读取延时
-- JQ_Test_ClkTrim,            //16 时钟校准
-- JQ_Test_Discharge,          //17 放电
-- JQ_Test_Reset,              //18 复位
-- JQ_Test_BootEn,             //19 起爆使能
-- JQ_Test_BoomEnergy,         //20 起爆充能
-- JQ_Test_EnCommEndCur,       //21 使能通讯末电流采集
-- JQ_Test_GetCommEndCur,      //22 获取通讯末电流
-- JQ_Test_WriteOTP,           //23 写OTP
-- JQ_Test_ReadOTP,            //24 读OTP
-- JQ_Test_ClearBoom,          //25 清除起爆计数
-- JQ_Test_PowerOff,           //26 关总线

-- 根据任务id找到下一个任务
function find_index(index,task_id)
    -- print("find_index:index=",index)
    local tasks=json_table["TaskArray"]
    -- prints:print_t(tasks)
    for i=index,len(tasks),1 do
        if(tasks[i]["TaskID"]==task_id) then
            return tasks[i]
        end
    end
    print("find_index err:index=",index,"task_id=",task_id)
    return nil
end



-- 检测器异常,1
-- 主电容异常,2
-- 接触异常,3
-- 桥丝阻值异常,4
-- 芯片异常,5
-- 其他异常,6


-- 判断上电错误，返回下一个检测任务,nil停止检测
function JQ_Test_PowerPrapare(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 上电错误只能是检测器异常，检测结束
        print("task failed.index=",task["TaskIndex"])
        only(err_code,1)
        return nil
    else
        -- 上电正常，排除检测器异常
        -- del(err_code,1)
        print("检测上电充能")
        -- 下一步是上电充能
        return find_index(task["TaskIndex"]+2,1)
    end
end




-- 判断上电充能错误，返回下一个检测任务,nil停止检测
function JQ_Test_PowerOn(task,err_code)
    local ret_value={}
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 上电充能异常
        del(err_code,0)
        print("task failed.index=",task["TaskIndex"])
        -- 下一步检测电流
        return find_index(task["TaskIndex"]+2,3)
    else
        -- 充能流程正常,返回第一个值是电压，第二个值是充能时间
        ret_value=find_return(task["TaskIndex"]+1)
        -- 电压无法上升，检测器异常
        if(ret_value[1]<task["TestStandard"][1]["Min"]) then
            only(err_code,1)
            return nil
        end
        -- 充电时间过长，进一步检测电流，判断开路还是短路
        if(ret_value[2]>39000) then
            del(err_code,0)
            print("检测电流")
            return find_index(task["TaskIndex"]+2,3)
        elseif(ret_value[2]<1) then
        -- 新小板程序在开路时会返回0，保险起见还是看一下电流
            del(err_code,0)
            print("检测电流")
            return find_index(task["TaskIndex"]+2,3)
        end
        ---- 排除检测板异常
        del(err_code,1)
        print("检测芯片UID")
        -- 下一步检测芯片
        return find_index(task["TaskIndex"]+2,4)
    end
end




-- 扫描uid，成功则芯片正常，返回下一个检测任务,nil停止检测
function JQ_Test_ScanUID(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 通信失败，返回芯片异常，检测结束
        print("task failed.task_index=",task["TaskIndex"])
        only(err_code,5)
        return nil
    else
        ret_value=find_return(task["TaskIndex"]+1)
        -- 最大反馈时间在范围之外，芯片异常
        if(ret_value[2]<task["TestStandard"][2]["Min"]) or (ret_value[2]>task["TestStandard"][2]["Max"]) then
            only(err_code,5)
            return nil
        end

		print("检测电流")
		return find_index(task["TaskIndex"]+2,3)
        --print("读取芯片代码")
        --return find_index(task["TaskIndex"]+2,6)
    end
end






-- 判断低压电流，返回下一个检测任务,nil停止检测
function JQ_Test_BaseCurLow(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 电流检测错误只能是检测器异常，检测结束
        print("task failed.task_index=",task["TaskIndex"])
        only(err_code,1)
        return nil
    else
        -- 返回正向电流，反向电流
        ret_value=find_return(task["TaskIndex"]+1)
		print("电流:",ret_value[1])
        -- 电流为0，开路，返回接触异常
        if(ret_value[1]<10) and (ret_value[2]<10)then
            only(err_code,3)
            return nil
        -- 电流过大，短路，返回芯片异常
        elseif((ret_value[1]>task["TestStandard"][1]["Max"]) and (ret_value[1]<1500))
			or ((ret_value[2]>task["TestStandard"][2]["Max"]) and (ret_value[2]<1500))
		then
            only(err_code,5)
            return nil
        elseif((ret_value[1]>1500) and (ret_value[2]>1500))then
            only(err_code,3)
            return nil
        end
        -- 排除接触异常
        del(err_code,3)
        --print("读取芯片UID")
        ---- 下一步检测芯片
        --return find_index(task["TaskIndex"]+2,6)
        print("读取芯片代码")
        return find_index(task["TaskIndex"]+2,6)
    end
end





-- 读取芯片代码，成功则芯片正常，返回下一个检测任务,nil停止检测
function JQ_Test_ReadChipID(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 通信失败，返回芯片异常，检测结束
        print("task failed.task_index=",task["TaskIndex"])
        only(err_code,5)
        return nil
    else
        print("检测高压电流")
        return find_index(task["TaskIndex"]+2,3)
    end
end





-- 判断高压电流，返回下一个检测任务,nil停止检测
function JQ_Test_BaseCurHigh(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 电流检测错误只能是检测器异常，检测结束
        print("task failed.task_index=",task["TaskIndex"])
        only(err_code,1)
        return nil
    else
        -- 返回正向电流，反向电流
        ret_value=find_return(task["TaskIndex"]+1)
		print("电流:",ret_value[1])
        -- 电流为0，开路，返回接触异常
        if(ret_value[1]<10) and (ret_value[2]<10)then
            only(err_code,5)
            return nil
        -- 电流过大，短路，返回芯片异常
        elseif((ret_value[1]>task["TestStandard"][1]["Max"]) and (ret_value[1]<1500))
			or ((ret_value[2]>task["TestStandard"][2]["Max"]) and (ret_value[2]<1500))
		then
            only(err_code,5)
            return nil
        elseif((ret_value[1]>1500) or (ret_value[2]>1500))then
            only(err_code,5)
            return nil
        end
        -- 排除接触异常
        del(err_code,3)
        print("检测桥丝和电容")
        -- 下一步检测桥丝和电容
        return find_index(task["TaskIndex"]+2,11)
    end
end



-- 检测充能，失败则电容异常
function JQ_Test_ChgEnergy(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        only(err_code,2)
        return nil
    else
        ret_value=find_return(task["TaskIndex"]+1)
        if((ret_value[1]>task["TestStandard"][1]["Max"]) or (ret_value[1]<task["TestStandard"][1]["Min"])) then
            only(err_code,2)
            return nil
        end
        if((ret_value[2]>task["TestStandard"][2]["Max"]) or (ret_value[2]<task["TestStandard"][2]["Min"])) then
            only(err_code,2)
            return nil
        end
        -- 排除电容异常
        del(err_code,2)
        print("检测桥丝")
        -- 下一步检测桥丝
        return find_index(task["TaskIndex"]+2,12)
    end
end



-- 检测电容电压，返回下一个检测任务,nil停止检测
function JQ_Test_CheckDAC(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 检测电压失败则桥丝或主电容异常
        print("task failed.task_index=",task["TaskIndex"])
        -- 这里判断上电充能值，如果偏大则桥丝异常，偏小则电容异常
        -- 充能流程正常,返回第一个值是电压，第二个值是充能时间
        -- local task_p=find_index(1,1)
        -- ret_value=find_return(task_p["TaskIndex"]+1)
        -- if(ret_value[2]>39999) then
        --     only(err_code,4)
        --     return nil
        -- else
        --     only(err_code,2)
        --     return nil
        -- end
        only(err_code,4)
        return nil
    else
        ret_value=find_return(task["TaskIndex"]+1)
        if((ret_value[1]>task["TestStandard"][1]["Max"]) or (ret_value[1]<task["TestStandard"][1]["Min"])) then
            only(err_code,4)
            return nil
        end
        -- 排除电容异常
        del(err_code,4)
        -- 下一步检测起爆
        return find_index(task["TaskIndex"]+2,20)
    end
end


-- 起爆充能
function JQ_Test_BoomEnergy(task,err_code)
    if(find_ack(task["TaskIndex"]+1,mid(check_data,1,8))==false)then
        -- 检测电压失败则桥丝或主电容异常
        print("task failed.task_index=",task["TaskIndex"])
        -- 这里判断上电充能值，如果偏大则桥丝异常，偏小则电容异常
        -- 充能流程正常,返回第一个值是电压，第二个值是充能时间
        -- local task_p=find_index(1,1)
        -- ret_value=find_return(task_p["TaskIndex"]+1)
        -- if(ret_value[2]>39999) then
        --     only(err_code,4)
        --     return nil
        -- else
        --     only(err_code,2)
        --     return nil
        -- end
        only(err_code,5)
        return nil
    else
        -- 排除芯片异常，密码错误会导致起爆失败
		del(err_code,5)
        print("检测完毕")
        return nil
    end
end






-- 定义占位函数，不应该调用
function JQ_Test_Empty(task,err_code)
    print("err function call,task index=",task["TaskIndex"])
    insert(err_code,6)
    return nil
end


-- 这个数组根据方案检测顺序确定
tasks_judge_fun={
    JQ_Test_PowerPrapare,--0
    JQ_Test_PowerOn,--1
    JQ_Test_ScanUID,--2
    JQ_Test_BaseCurLow,--3
    JQ_Test_ReadChipID,--4
    JQ_Test_Empty,--5
    JQ_Test_Empty,--6
    JQ_Test_Empty,--7
    JQ_Test_BaseCurHigh,--8
    JQ_Test_Empty,--9
    JQ_Test_Empty,--10
    JQ_Test_Empty,--11
    JQ_Test_Empty,--12
    JQ_Test_Empty,--13
    JQ_Test_Empty,--14
    JQ_Test_Empty,--15
    JQ_Test_Empty,--16
    JQ_Test_ChgEnergy,--17 充能统计
    JQ_Test_Empty,--18
    JQ_Test_CheckDAC,--19
    JQ_Test_Empty,--20
    JQ_Test_Empty,--21
    JQ_Test_BoomEnergy,--22
}


-- 根据任务依次判断
function judge()
    local fun_index=1
    local err_code={0,1,2,3,4,5}
    -- 找到上电任务
    local task=find_index(1,0)
    while true do
        if(task==nil)then
            if(len(err_code)>1)then
                -- 如果找不到任务，则应该是方案错误，这里返回其他异常
                print("can not find task,fun_index=",fun_index)
                insert(err_code,6)
            end
            break
        end
        if(find_stat(task["TaskIndex"]+1,mid(check_data,9,8))==false)then
            -- 如果任务未执行，则应该是方案错误，这里返回其他异常
            print("task unexecuted.index=",task["TaskIndex"])
            insert(err_code,6)
            break
        end
        fun_index=task["TaskIndex"]+1
        task=tasks_judge_fun[fun_index](task,err_code)
    end
    return err_code
end




-- 判断一个任务的子错误
function judge_task(task,data)
    local range=task["TestStandard"]
    local ret={}
    -- print("judge task")
    if range~=nil then
        -- print("judge task")
        for i=1,len(range),1 do
            if(data[i]<range[i]["Min"]) or (data[i]>range[i]["Max"]) then
                -- print("task=",task["TaskBrief"],"out of range:")
                -- print("err code=",task["ResultErrCode"][i])
                table.insert(ret,task["ResultErrCode"][i])
            end
        end
    end
    return ret
end


-- 依次判断主错误
function judge_list()
    local acks=mid(check_data,1,8)
    local stats=mid(check_data,9,8)
    for i=1,len(json_table["TaskArray"]),1 do
        local stat=find_stat(i,stats)
        if stat==true then
            local ack=find_ack(i,acks)
            local task_p=json_table["TaskArray"][i]
            local ret_value=find_return(i)
            local err_code=judge_task(task_p,ret_value)
            if ack==false then
                table.insert(err_code,task_p["ExecuteErrCode"])
            end
            if len(err_code)>0 then
                print("task:",task_p["TaskBrief"],"err_code:")
                prints:print_a(err_code)
            end
        end
    end
end




-- 要校验小板的版本号，方案的版本号
-- 脚本产生的异常从210开始，0xd2

function check_env()
    -- 校验输入数据的长度
    local skip,l=calc_skip(len(json_table["TaskArray"]),json_table["TaskArray"])
    -- print("requier len=",skip+l)
    if(skip+l+16>len(check_data)) then
        print("check data too less.",skip+l+16)
        return "数据长度与方案不符",210
    end
    if(json_table["PlanID"]~=PLAN_ID) then
        print("plan id check err.")
        return "方案ID不符",211
    end
    return "ok",0
end


-- 取得表中第一个值
function get_err_code(err_code)
    for k,v in pairs(err_code) do
        if(v~=nil) then
            return v
        end
    end
    return nil
end

function main()
    local err_str_table={"检测器异常","主电容异常","接触异常","桥丝阻值异常","芯片异常"}
    local ch_err,ch_code=check_env()
    if(ch_code~=0) then
        return ch_err,ch_code
    end
    -- 展示任务执行结果
    show_acks(mid(check_data,1,8))
    show_stats(mid(check_data,9,8))
    -- 开始判定
    local err_code=judge()
    if(len(err_code)>1) then
		prints:print_a(err_code)
        return "检测项目不足，无法判定",212
    end
    prints:print_a(err_code)
    local err=get_err_code(err_code)
    if(err~=nil) then
        if(err==0) then
            judge_list()
            return "ok",err
        else
            return err_str_table[err],err
        end
    else
        print("err:err_code is none.")
        return "数据不合规",213
    end
end

-- 先返回错误描述，再返回错误码
return main()
-- print("sssss",exp2(-1))
-- show_acks({1,2,3,4,5,6,7,8})
-- prints:print_a({1,2,3,4,5,6,7,8,9,0xf0,0xe,0xd})