Jianw
2025-05-14 29f8b36ebb718d2051bf0e7e701973ec4419ee80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
--[[
    编码: WMS-08-10
    作者:HAN    
    日期:2025-1-29
        
    入口函数: EQActionProcess
        
    功能说明:
 
    变更记录:
 
--]]
wms_op = require( "wms_operation" )
wms_dev = require( "wms_devcomm" )
wms_task = require( "wms_task" )
wms_wh = require( "wms_wh" )
 
function EQActionProcess ( strLuaDEID ) 
    local nRet, strRetInfo
 
    -- step1  获取设备动作队列 MQ_EQAction
    local mq_eq_action
    nRet, mq_eq_action = m3.GetSysCurEditDataObj( strLuaDEID, "MQ_EQAction ")
    if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), mq_eq_action ) end 
 
    -- step2 AGV传上来的数据保存在 mq_eq_action.data 是下面这样一段Json字符串
    -- {"State":"%d","No":"%s","Ext1":"%s","Ext2":"%s","Ext3":"%s","ForkliftNo":"%d","ErrCode":"%d","ExtData":"%d"}
    local agv_action, success
    success, agv_action = pcall( json.decode, mq_eq_action.data)
    if ( success == false ) then lua.Error( strLuaDEID, debug.getinfo(1), "动作队列中的字符串是不合法的JSON格式! "..mq_eq_action.data ) end
 
    -- 注意 动作码 是数值类型
    local nActionCode = lua.StrToNumber( agv_action.State )
    local strTaskCode = agv_action.No
    local strForkliftNo = agv_action.ForkliftNo
 
    -- step3. 获取任务信息,如果有任务编码检查一下任务是否存在
    --        检查任务的状态是否=完成,已经完成的任务也不能继续接收 action
    local task = {}
    if ( strTaskCode ~= '') then
        nRet, task = wms_task.GetInfo( strLuaDEID, strTaskCode )
        -- 如果任务不存在或出错, 返回
        if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), task ) end
    else
        task = nil
    end
    if ( task == nil ) then lua.Error( strLuaDEID, debug.getinfo(1), "设备动作队列中任务编码为空或任务编码无效! " ) end
 
    -- V3.1
    if ( task.bs_state == wms_base.Get_nConst(strLuaDEID, "任务状态-完成") )  then
        lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..task.code.."' 的任务已经完成,无法继续接受任务活动!")
    end
    if ( strForkliftNo == nil or  strForkliftNo == '') then
        lua.Error( strLuaDEID, debug.getinfo(1), "HostToAGV 回调接口数据不完整,少车辆号(ForkliftNo)! ".. mq_eq_action.data )
    end  
     
    -- step4  根据设备的动作类型进行处理
    local strActionValue = ''           -- 附加值
 
    -- 以下这些动作要判断一下任务里是否已经有,有返回
    if ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-开始运行" ) or nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-搬运完成" ) or
         nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-取货请求" ) ) then
        nRet, strRetInfo = wms_task.Action_Exist( strLuaDEID, task.code, nActionCode )
        if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "任务动作检查时出错! "..strRetInfo ) end
        if ( strRetInfo == "yes" ) then return end   
    end
 
    -- 1
    if ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-开始运行" ) ) then
        -- 车辆开始执行
        -- 需要给任务赋值车辆代码,开始时间
        if ( task.eq_code ~= "" ) then
            --  如果任务已经绑定了车辆,报错
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码='"..task.code.."'的任务已经绑定了设备,设备编码='"..task.eq_code.."'" )
        end
        task.eq_code = agv_action.ForkliftNo
        task.bs_state = wms_base.Get_nConst(strLuaDEID, "任务状态-执行")
        task.start_time = os.date("%Y-%m-%d %H:%M:%S")
 
        nRet, strRetInfo = wms_task.Update( strLuaDEID, task )
        if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "更新任务信息失败!"..strRetInfo ) end
    -- 2
    elseif ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-搬运完成" ) ) then
        -- AGV 搬运完成    
        nRet, strRetInfo = wms.wms_TaskFinish( strLuaDEID, task.code )
        if ( nRet ~= 0 ) then 
            -- V7.2
            local setAttr, strErr
            setAttr = "S_ERR = '".."在设备动作监听脚本 WMS-107-02 中执行 wms_TaskFinish 失败! 原因:"..strRetInfo.."'"
            nRet, strErr = mobox.addProcSQL2( "Task", task.id, setAttr )
            if ( nRet ~= 0 ) then
                lua.Error( strLuaDEID, debug.getinfo(1), "addProcSQL2 失败!"..strErr )
            end
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码='"..task.code.."'的任务设置完成失败!"..strRetInfo ) 
        end  
    -- 4
    elseif ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-取货完成" ) ) then
        -- AGV取货完成,给PLC一个完成信号
 
        -- step1 获取线体编号 line_seg_code
        local line_seg_code
        -- 如果是入库搬运需要和输送线进行交互,如果出库不需要直接从货架取
        if ( task.type == wms_base.Get_nConst( strLuaDEID, "任务类型-AGV入库搬运")) then
            nRet, line_seg_code = XX_GetLineSegCodeByLocCode( strLuaDEID, task.start_loc_code )
            if ( nRet ~= 0 ) then 
                lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务属性早中起始货位不完整! "..line_seg_code ) 
            end
            --PLC写入的完成信号
            local body = {}
            body.device_code = "S7_Line_01"
            body.comm_code = line_seg_code.."_FINISH"
            body.value = {}
            body.value[1] = wms_base.Get_nConst( strLuaDEID, "PLC信号-AGV出框完成" )
 
            wms_dev.WriteS7PLCCommsData( strLuaDEID, body )
        end
 
        -- 货位和托盘解绑
        nRet, strRetInfo = wms_wh.Loc_Container_Unbinding( strLuaDEID, task.start_loc_code, task.cntr_code, "绑定解绑方法-系统", task.code.."取货完成"  )
        if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '货位容器解绑失败!'..strRetInfo ) end 
    -- 6
    elseif ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-卸货完成" ) ) then
        -- AGV卸货完成
        -- 需要判断一下 当前 task 的任务类型
        if ( task.type == wms_base.Get_nConst( strLuaDEID, "任务类型-AGV入库搬运")) then
            -- 货位和托盘进行绑定
            -- 从任务中获取 目标位置,目标位置和托盘进行绑定
            -- 从作业对象中获取容器编码(目前只是单个容器)            
            local operation = {}
            nRet, operation = wms_op.GetInfo( strLuaDEID, task.op_code )
            if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "获取编码='"..task.op_code.."'的作业对象失败! "..operation ) end
            -- 货位和托盘进行绑定
            nRet, strRetInfo = wms_wh.Loc_Container_Binding( strLuaDEID, task.end_loc_code, operation.cntr_code, "绑定解绑方法-系统",  task.code.."卸货完成" )
            if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '货位容器绑定失败!'..strRetInfo ) end 
        elseif ( task.type == wms_base.Get_nConst( strLuaDEID, "任务类型-AGV出库搬运")) then
            -- AGV 已经把出库货品搬运到 线体出口
            -- 需要给PLC发一个进框完成信号
            local line_seg_code
            nRet, line_seg_code = XX_GetLineSegCodeByLocCode( strLuaDEID, task.end_loc_code )
            if ( nRet ~= 0 ) then 
                lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务属性早中起始货位不完整! "..line_seg_code ) 
            end
            -- 组织给PLC写入的完成信号
            local body = {}
            body.device_code = "S7_Line_01"
            body.comm_code = line_seg_code.."_FINISH"
            body.value = {}
            body.value[1] = wms_base.Get_nConst( strLuaDEID, "PLC信号-AGV进框完成" )
 
            lua.Debug( strLuaDEID, debug.getinfo(1), "AGV进框完成 body", lua.table2str(body))
 
            wms_dev.WriteS7PLCCommsData( strLuaDEID, body )
 
        else
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务类型不正确! " ) 
        end
 
    -- 1101
    elseif ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-取货请求" ) ) then
        -- AGV取货请求
        -- 根据【任务】类型来判断 线体出入口 位置
        -- 如果是入库作业,任务的开始位置是线体端,如果是出库任务的目标位置是线体端
        if ( task.type == wms_base.Get_nConst( strLuaDEID, "任务类型-AGV入库搬运")) then
            line_loc_code =  task.start_loc_code
        else
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务类型不正确! " ) 
        end
 
        nRet, line_seg_code = XX_GetLineSegCodeByLocCode( strLuaDEID, line_loc_code )
        if ( nRet ~= 0 ) then 
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务属性早中起始货位不完整! "..line_seg_code ) 
        end
 
        -- 获取 线体信号,如果是有框,发出出框请求并且 AGV 的搬运任务状态设置为 "等待出框"
        local state = wms_dev.ReadS7PLCCommsData( strLuaDEID, "S7_Line_01", line_seg_code..'_STUS' )
        -- 判断线体 (1) 是否空闲  = 0(2)是否有框 = 1 -- 有框 (3)是否允许出框 = 1 -- 允许出框
        if ( state[wms_base.Get_nConst(strLuaDEID,"输送线-线体状态")] == 0 and 
             state[wms_base.Get_nConst(strLuaDEID,"输送线-光电信号")] == 1 and
             state[wms_base.Get_nConst(strLuaDEID,"输送线-线体信号")] == 1 ) then
            -- 通知 AGV 开始取货
            local strXml
            --  ParamNo='9 继续取货
            strXml = "<Order No='"..task.code.."' ParamNo='9' Param='1' ></Order>"
            nRet, strRetInfo = wms.wms_ChangeNdcOrderParameter( task.factory, task.schedule_type, strXml )
            if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "HostToAGV推送指令失败!"..strRetInfo) end
         else
            return
        end
        
    -- 1102
    elseif ( nActionCode == wms_base.Get_nConst( strLuaDEID, "AGV-卸货请求" ) ) then 
        -- AGV卸货请求  
        -- 如果是出库作业,任务的终止位置是线体端
        if ( task.type == wms_base.Get_nConst( strLuaDEID, "任务类型-AGV出库搬运")) then
            line_loc_code =  task.end_loc_code
        else
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务类型不正确! " ) 
        end
        nRet, line_seg_code = XX_GetLineSegCodeByLocCode( strLuaDEID, line_loc_code )
        if ( nRet ~= 0 ) then 
            lua.Error( strLuaDEID, debug.getinfo(1), "任务编码 = '"..strTaskCode.."' 的任务属性早中终点货位不完整! "..line_seg_code ) 
        end
 
        -- 获取 线体信号,如果是有框,发出进框请求并且 AGV 的搬运任务状态设置为 "等待出框"
        local state = wms_dev.ReadS7PLCCommsData( strLuaDEID, "S7_Line_01", line_seg_code..'_STUS' )
        -- 判断线体 (1) 是否空闲  = 0(2)是否有框 = 0 -- 无框 (3)是否允许进框 = 2 -- 允许进框
        if ( state[wms_base.Get_nConst(strLuaDEID,"输送线-线体状态")] == 0 and 
             state[wms_base.Get_nConst(strLuaDEID,"输送线-光电信号")] == 0 and
             state[wms_base.Get_nConst(strLuaDEID,"输送线-线体信号")] == 2 ) then
            -- 通知 AGV 开始卸货
            local strXml
            --  ParamNo='9 继续卸货
            strXml = "<Order No='"..task.code.."' ParamNo='9' Param='1' ></Order>"
 
            lua.Debug( strLuaDEID, debug.getinfo(1), "ChangeNdcOrderParameter", strXml )
            --[[
            nRet, strRetInfo = wms.wms_ChangeNdcOrderParameter( task.factory, task.schedule_type, strXml )
            if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), "HostToAGV推送指令失败!"..strRetInfo) end
            --]]
        else
            -- 如果线体的信号不能满足就返回,等下一次信号
            return
        end                     
    end
    
    -- 根据动作码获取动作名称
    local task_action = m3.AllocObject(strLuaDEID,"Task_Action")
 
    task_action.task_code = strTaskCode
    task_action.action_code = nActionCode
    task_action.eq_code = task.eq_code
    task_action.eq_type_name = mq_eq_action.eq_type_name
    task_action.data = lua.FormatJsonString( mq_eq_action.data )
    task_action.value = strActionValue
 
    nRet, strRetInfo = m3.CreateDataObj( strLuaDEID, task_action )
    if ( nRet ~= 0 ) then lua.Error( strLuaDEID, debug.getinfo(1), '创建【任务动作】对象失败!'..strRetInfo ) end 
end