当前位置 博文首页 > wuch:python工业互联网应用实战6—任务分解

    wuch:python工业互联网应用实战6—任务分解

    作者:wuch 时间:2021-02-13 12:28

    本章节我们讲述了如何通过admin.py来快速的完成页面功能的构建,并通过自定义action快速的实现了任务分解功能,并根据业务进展也逐步的完善了查看页面以内联表的方式显示作业详情。

      根据需求定义“任务”是一个完整的业务搬运流程,整个流程涉及到多个机构(设备)分别动作执行多个步骤,所以依据前面的模型设计,需要把任务分解到多个连续的子任务(作业),未来通过顺序串联下达执行的方式来分步骤的完成任务的执行。

    1.1. 仓库规划

      同样,依据需求我们先来做几个仓库的规划设计,101位置是AGV的入库起始站台,102是提升机门口的入库工位,104是提升机1楼轿厢工位,同理504是提升机在5楼的轿厢工位。左边是5楼的货位区编码规则,完整好的货位号加上楼层编码05-01-01表示五楼的01-01货位,如下图:

     

      有了图上的基本仓库规划设计,我们才能把一个任务依据设计进行分解,例如:任务编码100的搬运任务是把货物从101 入库工位搬运到05-01-01货位存放。

        设计约定:

        ① 102、502为进提升机工位,103、503为出提升机工位,出和入的工位分开来解决任务冲突的问题(当然也可以先规划一个工位,随着程序迭代改进)。

        ② 提升机控制逻辑与电梯类似,到达指定楼层后会自动开门。

        ③ 电梯只有关上廊门才能提升/下降。

      这样根据约定(前置条件)现在我们针对这个任务逐步分解成以下子任务(作业)如下表,对照早期的需求会发现有增加作业,实际项目中也是如此,早期的需求定义到实际编码的时候,需要根据实际的设备接口协议,规定等调整早期的需求定义。

    序号

    作业描述

    执行设备

    1

    调度AGV101站台搬运托盘到102站台

    1AGV

    2

    调度提升机到1楼并打开门

    提升机

    3

    调度AGV102工位搬运到104工位并卸货

    1AGV

    4

    调度空AGV104工位到103工位

    1AGV

    5

    调度提升机关门

    提升机

    6

    调度提升机1楼提升到5楼并开门

    提升机

    7

    调度空AGV到504工位并载货

    5AGV

    8

    调度AGV从504工位到503工位

    5AGV

    9

    调度提升机关门

    提升机

    10

    调度AGV从503工位搬运到05-01-01货位并卸货

    5AGV

      上面的分解比需求表增加了两个子任务“调度空AGV104工位到102工位”和“调度AGV504工位到502工位”,是与实际的AGV设备对接通信协议后增加的,AGV小车的控制系统不能识别“调度AGV提升机1楼门口工位到提升机并卸货,返回提升机门口工位”需求里“返回”提升机门口工位。依据设备的接口逻辑,只能把这个步骤再分解成两个步骤来执行。

      上述分解提供一个简化分解的模型和思路,实际项目可能更为复杂或简单。

    1.2. 分解代码实现

      我们在后台任务管理里添加任务编码100、源地址101、目标地址05-01-01的任务,如下图:

      同时admin.py里增加新增任务默认状态设置为未处理的代码,我们通过pk值是否为None来判断model是否是新增还是修改。

    #Task模型的管理器
    class TaskAdmin(admin.ModelAdmin):
    ...
    
        def save_model(self, request, obj, form, change):
            #新增任务默认状态设置为 未处理
            if obj.pk==None:
                obj.State=1 
                obj.User=request.user
            return super().save_model(request, obj, form, change)

      接下来,我们演示如何依据上面的分解逻辑用代码来实现把任务分解成子任务并保存到Job对应的表里,同时,把任务的状态从“未处理”更新到“处理完成”状态。这里需要注意的就是任务的分解和状态变更必须在一个事务里完成,系统不能存在任务状态已经变更到处理完成,但是没有对应的作业,也不能存在已有对应的作业任务状态仍然是未处理状态的情形,否则就会造成系统业务上的混乱,前面章节提到的事务应用就非常重要!

    #Task模型的管理器
    class TaskAdmin(admin.ModelAdmin):
    ...
    
         @atomic
        def task_decompose_action(self, request, queryset):
            for obj in queryset:
                #只处理状态等于未处理的任务
                if obj.State==1:
                    result=self.task_decompose(request,obj)
                    if result:
                        self.message_user(request, str(obj.TaskNum) + " 处理成功.")
                    else:
                        self.message_user(request, str(obj.TaskNum) + " 处理成功.")
    
        task_decompose_action.short_description = '处理所选的' + ' 任务'
    
        def task_decompose(self,request,obj):
            success=True
            try:
                job1=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":1,"Source":obj.Source,"Target":'102',"Executor":"AGV01","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})
                job1.save()
                job2=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":2,"Source":None,"Target":'1',"Executor":"ELEVATOR","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,}) 
                job2.save()
                job3=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":3,"Source":"102","Target":'104',"Executor":"AGV01","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})
                job3.save()
                job4=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":4,"Source":'104',"Target":'103',"Executor":"AGV01","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})
                job4.save()
                job5=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":5,"Source":'1',"Target":'5',"Executor":"ELEVATOR","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})  
                job5.save()
                job6=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":6,"Source":'504',"Target":'503',"Executor":"AGV05","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})
                job6.save()
                job7=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":7,"Source":'5',"Target":None,"Executor":"ELEVATOR","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,}) 
                job7.save()
                job8=Job(**{"Task":obj,"TaskNum":obj.TaskNum,"OrderNo":8,"Source":'503',"Target":'05-01-01',"Executor":"AGV05","State":1,\
                    "Priority":obj.Priority,"Barcode":obj.Barcode,"User":request.user,})
                job8.save()
                #子任务分解完成,并提交数据库
                #更新任务的状态到“处理完成”
                obj.State=5
                obj.save()
            except Exception:
                success = False     
    
            return  success

      执行效果如下图:

     

    1.3. 列表增加“作业数量”

      任务分解完成后,列表除了显示状态变化之外,能够查看作业的分解数量,为此在Task Admin里增加job_count函数用来显示作业数量。

    #Task模型的管理器
    class TaskAdmin(admin.ModelAdmin):
        #listdisplay设置要显示在列表中的字段(TaskId字段是Django模型的主键)
        list_display = ('TaskId','TaskNum', 'Source', 'Target', 'Barcode','State','