mes3cs记录

1.日志级别,info默认,下面的不会执行,上面的可以执行,
例如 error … info … 此时 默认 info ,那么 info 及其 以上的 都是 可以打印出来的,目的 也就是 在 日志文件中,可以通过 error 还是 info 提示 我们 这里我们编写的 日志 是 error的,那么 这里是有问题的,就是说 只有 日志级别的设定,以及 我们 写的 是 logger.? 我们是可以控制的,例如 默认 info ,那么 这里我想打一个日志 例如
if(xxx){
logger.error(xxx)
}

就是说 if发生了,在我看来就是 出错了(不代表程序出错,是认为性错误,可能是业务等),那么 我这里打一个日志,error() 那么日志文件的 日志显示 会显示error : ,,这样我就知道 这里是有问题的,如果 我写 info() 那么我在 日志文件里面 看到 info 我就不会管它,因为我在 日志文件里面 筛选 bug的时候,一般只看 error的,然后定位到代码处

public void testLogger(){
        try {
            int i = 10 / 0;
        }catch (Exception e){
            logger.info("直接打印e:error(String.valueOf(e))");
            logger.error(String.valueOf(e));
            logger.info("也算是直接打印e了:error(\"异常\" + e)");
            logger.error("异常" + e);
            logger.info("打印e的toString():error(e.toString())");
            logger.error(e.toString());
            logger.info("打印e的message:error(e.getMessage())");
            logger.error(e.getMessage());
            logger.info("通过这种方式打印e:error(\"异常\", e)");
            logger.error("异常", e);
        }
    }

关于控制台 和日志文件
1.控制台和日志文件,只是 2个输出端介质,日志信息可以输出到任何介质上去

误区debug 看控制台日志,就以为所有的日志都在里面,实际不是,控制台里面的日志,有些是语言框架自己输出到控制台的(也输出到日志文件里面了),还有是我们把日志 打印到控制台了(不是 print 这个只是输出信息到控制台,不是日志)
就是说,控制台的日志,和 日志文件中的日志,有些是 系统打的,有些是控制台打的,但是一般来说,控制台打的,日志文件里面也肯定有,除非我们对日志文件做了 特殊的调整处理,不然 日志文件里面的 日志一定是 和 控制台输出的日志一样的,加上 我们在代码里面 自己加的 logger日志(一般也是 输入到 日志文件中),所以日志文件中的 日志一般是 最全的,当日志文件都解决不了的时候,我们就只有 debug 结合日志 和 逐过程 看代码了

当然,还有一种 替换了 debug的方式,例如 java的 arthas 可以不用 debug 直接 看每一步的 执行过程,
排查代码问题,说白了,就是想知道每一步的执行情况,如果知道一部分就是 通过日志文件(系统的,和我们自己加的),如果一部分判断不了,就知道 知道每一步的执行情况(这种 以前只有 debug可以实现),但是 arthas,可以不用 debug 直接 运行状态,就可以知道 所有步的执行情况

2.C# 属性定义时 后面 可接 {} 代码块

3.fxml 不是 一个 窗口,是属于一个,里面包含了,布局和控件,
xaml 是一个个 window 窗体

4.mes 中 日志打印,是 将信息 放到 队列里面去,然后创建一个线程,去 将队列中的信息打印出来,而 自己定义的 日志类,是 通过 static方法,程序启动就加载的

5.使用线程,异步处理,如果不需要获得异步数据,那么 多线程即可,如果需要获得异步数据,多线程 callable 以及,mq都可以

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("线程执行......");
        Thread.sleep(5000);
        System.out.println("线程执行完毕......");
        return "hello world!!!";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        /***
         * futureTask 实现了 Runnable接口
         * 所以新建线程的时候可以传入futureTask
         * FutureTask重写的run方法中实际是调用了Callable接口在call()方法
         * 所以执行线程的时候回执行call方法的内容
         */
        Thread thread = new Thread(futureTask);
        thread.start();
        String value = futureTask.get();
        System.out.println(value);
    }
}

6.mes3cs ,通过 config类(object的),(工具类),去 读取json文件中的信息,封装给 一个 var config:ConfigFile
达成了,程序启动,就有 config的目的(里面所有的 json信息都存在里面),而组织json结构,全部 写在 object
config 里面的 各种 data class 这里面的 data class 不算 业务实体数据类,只能说 是 封装 这个 工具类变量的,结构组成,所临时创建的 data class 目的就是为了 封装这一个 json config变量,后面很多地方会用到,

1.切割版图 :一块原片就是一个切割版图,每个切割版图上把玻璃切片了并且分号了,我们从erp获取数据(存到 model_piece中)

流程卡
2.状态编号:表示每块玻璃 处于哪个分支流程的 那个设备,设备从0-8 9个设备 0x10(决定设备在哪个设备上) + (1 到 9 随机数 表示玻璃状态)
3. 每个plc 设备 和 mes设备 plcdev 是程序启动,开启线程 处于监听状态,去接受指令,返回指令的,主线程主要处理按钮页面交互的,
4.mes方向
5.立即上片
model_piece表,获取数据后,model_piece表里面会有数据,关联了 2张比较重要的表,model_process model_optimize 流程卡 和 优化单,表示 此数据的状态
通过 更改 流程卡 和 优化单的数据,改变了 model_piece的数据
里面的 seq 代表了 此优化单 和流程卡 是否正在上片,然后记录了 流程卡和优化单的 出口 入口等
例如点击立即上片,优化单的 seq改变,玻璃数据的 seq简接改变,现在如果玻璃过来,plc发数据过来,说玻璃过来了,检测到玻璃,发送给mes ,然后mes匹配成功,并给plc发匹配成功,并且将mes_id传给plc 说完成检测,plc收到数据后,上片完成,然后发数据给mes说检测完成,mes收到消息返回给 plc 等待

model_process 中的 出库顺序 是 model_process的seq
6.交互位置的 字段位置 代表,数组的下标,数据包,是数组(一次数据交互,是来回2次握手,4) 因为涉及 两步处理,plc处理,和 mes处理,1次处理需要握手一次,即A-B(B收到,处理)-A(通知A我收到了,并且可能把数据返回给 B)

7.握手 status怎么改变????

8.mes系统主要做的,就是 根据杂乱无章的玻璃,把他们 每个步骤 玻璃的处理情况记录下来,并且按照一定认为要求去 指导 plc执行硬件流程,只有plc的话,1.玻璃数据的执行流程消息得不到保存,2.玻璃无法按照一定的规律去 执行。而指导plc 通过 2者监听去做,plc要给mes 发指令,让其知道,我要对玻璃处理了,(并会尽可能的把关于 device 和 玻璃的消息,这里的信息通常指的是硬件测量到的,或者plc那边以及此时 device的状态 发给 mes),mes去 保存执行流程信息,并且发给 plc (1.你可以去执行了,以及mes_id , 玻璃信息,以及 你应该怎么处理这块玻璃,用哪个 小车,走那条线路等等) 也就是让 mes 1.保存执行流程,2.指导我plc该怎么去执行这块玻璃

9.modelpiece 表中,出库顺序有2个字段,outorder_predefined outorder_optimize 映射到实体类的outorder_number 因为 具体出库顺序有2种1:根据配置文件,2:代码中指定的

1.切割版图 :一块原片就是一个切割版图,每个切割版图上把玻璃切片了并且分号了,我们从erp获取数据(存到 model_piece中)

流程卡
2.状态编号:表示每块玻璃 处于哪个分支流程的 那个设备,设备从0-8 9个设备 0x10(决定设备在哪个设备上) + (1 到 9 随机数 表示玻璃状态)
3. 每个plc 设备 和 mes设备 plcdev 是程序启动,开启线程 处于监听状态,去接受指令,返回指令的,主线程主要处理按钮页面交互的,
4.mes方向
5.立即上片
model_piece表,获取数据后,model_piece表里面会有数据,关联了 2张比较重要的表,model_process model_optimize 流程卡 和 优化单,表示 此数据的状态
通过 更改 流程卡 和 优化单的数据,改变了 model_piece的数据
里面的 seq 代表了 此优化单 和流程卡 是否正在上片,然后记录了 流程卡和优化单的 出口 入口等
例如点击立即上片,优化单的 seq改变,玻璃数据的 seq简接改变,现在如果玻璃过来,plc发数据过来,说玻璃过来了,检测到玻璃,发送给mes ,然后mes匹配成功,并给plc发匹配成功,并且将mes_id传给plc 说完成检测,plc收到数据后,上片完成,然后发数据给mes说检测完成,mes收到消息返回给 plc 等待

6.交互位置的 字段位置 代表,数组的下标,数据包,是数组(一次数据交互,是来回2次握手,4) 因为涉及 两步处理,plc处理,和 mes处理,1次处理需要握手一次,即A-B(B收到,处理)-A(通知A我收到了,并且可能把数据返回给 B)

7.握手 status怎么改变????

8.mes系统主要做的,就是 根据杂乱无章的玻璃,把他们 每个步骤 玻璃的处理情况记录下来,并且按照一定认为要求去 指导 plc执行硬件流程,只有plc的话,1.玻璃数据的执行流程消息得不到保存,2.玻璃无法按照一定的规律去 执行。而指导plc 通过 2者监听去做,plc要给mes 发指令,让其知道,我要对玻璃处理了,(并会尽可能的把关于 device 和 玻璃的消息,这里的信息通常指的是硬件测量到的,或者plc那边以及此时 device的状态 发给 mes),mes去 保存执行流程信息,并且发给 plc (1.你可以去执行了,以及mes_id , 玻璃信息,以及 你应该怎么处理这块玻璃,用哪个 小车,走那条线路等等) 也就是让 mes 1.保存执行流程,2.指导我plc该怎么去执行这块玻璃

9.modelpiece 表中,出库顺序有2个字段,outorder_predefined outorder_optimize 映射到实体类的outorder_number 因为 具体出库顺序有2种1:根据配置文件,2:代码中指定的

10.json中的,device 和 plc是对应关系的,即那mes的 哪一个 device 会给 哪一个plc交互消息
device中主要有 device的信息,以及 exchangeDevice(即 交互的 plc的信息)

11.plc中 slot(巷道号) 还有一个层号 是啥意思

12.交互信息的 数段位置 代表在数组中的位置,而 配置文件中的,或者表中的 postion 代表,设备的位置 postion还是需要的,每个device 类或表等,都还是需要position的,虽然一个设备的所有postion字段值一样的,但是1.position可以代表设备的位置,玻璃的状态也是由position来的,而且相同类型的 设备 position可能不一样的,这也是区别相同类型的设备 的 不同作用,例如 测片台1 和 测片台2,属于一个类型device 属于1张表,但是postion不一样,我就知道 是哪个 具体的设备,而不是类型

13.理片库不是一个 device 而是多个设备,当然1个理片库 也是1个device 但是里面包含了 小车底车等设备,然后对应的小车类里面保存了,exchange信息,等于理片库不做事,而是里面的 小车底车设备做事,json中 里片库的 plc信息,也是封装到,里片库类里面的 小车类的 exchange类里面的

14.各种方向 都是mes方向,叫法不一样,字段名不一样而已 ,还有什么出口exit_id 也是方向
13.mes中 config device类 data类(实体类,表结构对应) 和 config(一般配置文件里面读到的 json类,都会对应一个 data类) device里面的 内部类

status = 0 代表 还没有上片(默认值 是 0), 立即上片指的是,让其优化单的seq变成1 , 那么这块玻璃才有机会 上到 测量上片台后,status可以变成1,即能够处于上片状态,即 立即上片(对优化单),然后对破片的玻璃立即上片,都是对优化单,流程卡,seq改变,这样这些玻璃才能够被识别监听执行流程,才有计划 status可以变化,

破片的status是 -1 对于破片,有点不一样,破片玻璃属于的优化单的 seq = 1 ,这块玻璃也不能status改变的,因为会检查玻璃的优化单的seq(判断 这块玻璃能不能上片,即status能不能改变,),也会检查这块玻璃的status 是不是 -1 如果是 就证明 是破片,也不能上片的,即stauts 状态不能改变的

14.交互信息走几次 ,怎么走的

15.plc代码完成

16.plc_record 为什么 很多 设备都用了 他们自己的plc表 且 用了 plc_record

破片的解决
破片任何时候都可能发生,破片后将这块玻璃记录成破片然后不处理这块玻璃了,唯一的好处是,可以切换下个优化单,或者版图,然后单想要重新上片的时候,完成上个优化单后,切换回来,点 重新上片,然后再从头开始处理这块玻璃,系统会记录这块玻璃处理了多次

流程卡是最先有的,多个流程卡 组合成 一个优化单(优化原片的切割),上片的时候随机,到里片库 出片的时候,必须按 一个个流程卡 出完 在出下一个流程卡,不能随便出

按优化单上片 和 切割版图上片的 方式不同,就是系统会 把范围控制大小,即 如果按 切割版图 上片,那么 系统只会匹配 这个切割版图的玻璃(在 误差允许的范围下),其他版图的不会匹配到的,优化单就是把这个 范围阔大了

立即上片的作用:没有上片的 玻璃,在model_piece里面的 优化单的 seq 是 =0的,即系统不会去匹配这些,立即上片后 seq =1 系统会匹配这些model_piece里面的 玻璃
即立即上片的作用,就是 将这些玻璃的 优化单的 seq改成 1,代表这些玻璃status能够变化,能够去 model_piece中 匹配这些表

完成优化单的作用就是,将 这个优化单的玻璃 status = 0的,就是没被检测到的,要么去 将这些玻璃 上片,status状态改过来,要么就是破片了,将这些状态改成破片(这种情况 就是 这些玻璃还未上片 就破片了,其实就等于 还未上片,这些status = 0 的玻璃还没被检测到,)

seq = 1 的 玻璃,一个优化单的玻璃,立即上片后,seq都为1,然后根据选择上片方式的不同,必须处理完 这个方式的玻璃,才能处理下个玻璃

seq = 1代表,有能力上片,能不能上片其他 即把其他优化单的 seq改成1,让其他玻璃有能力上片,和上片的方式有关系

基本只要这个 优化单的 seq改成了1 ,那么 属于 这个优化单的玻璃,一直有权力上片 status可以改变,但是能不能上,还取决与,上片的方式

即2层限定 玻璃能不能处理的 关键 1:玻璃的seq =1 2.上片方式:这块玻璃是不是处在 这个上片方式的 这个阶段下(例如某个优化单,或者某个优化单的切割版图下),
即 seq = 1?? lono = ? 切割版图 = ? 最后这块玻璃的 status >= 0 (也能检测,但是 status = -1 系统会报 次片破片,就是可以检测,但是我不让上)才行 这些指定好的,才能上片检测

破片重新上片 是指 seq = 1有了,lono = ?有了,切割版图 = ?有了,但是 status = -1

重新选择 选择过的 优化单,上片,实际是改 lono = ? 切割版图 = ? seq只会改一遍,也就是让这个 lono 版图下的 玻璃 再次有机会匹配到

测量上片台,1个测量上片台是一个设备(属于1个类型) 1个可以处理1个版图,2个不能处理相同的版图,并且是按切割版图顺序(一般),

出片台方向,只能是里片库有2个,一一对应的,就是 一开始的mes_direction决定的,因为mes_direction决定了哪个 入片台,决定了 哪个里片库

测量上片台,版图上显示的是model_piece的数据,是erp数据,其他数据是测量数据,测量数据 和 版图数据 不匹配时,报警,而且报警后,版图玻璃不会加进来,报警数据mes_id = 0 ,看的话 直接看这块玻璃的 测量数据,和 整块版图的玻璃 对比下,一般差别很大的,就是测量与erp数据不匹配

里片库,1-169是左边里片库,170后面的是右边的里片库,

里片库的 入库,出库,完全出库 是按流程卡的,有3位数据,分别是未入库,库中,已出库 车的启动和暂停按钮,是车有故障时手动停止的

交互信息:

plc 和 mes 的每个设备 都是 会 发消息 等信息的,主要关注 信息交互字段是哪些

硬件的控制 时plc控制的,1.plc主动控制,2.plc需要等到 mes的信息才控制

底车和 入库小车 和 出库小车时同时动的,目的就是让玻璃在里片库中能动起来

入片台 和出片台,为什么要设置一个控制,(交互信息就是 玻璃数量),原因就是,这里是需要等待的,入片台,需要等待小车,出片台 需要等待磨边机空闲,(而且这里不需要 对 玻璃的信息 做交互 并执行逻辑)

一般,需要等待,plc 和 mes需要做逻辑交互的(除了需要等待,这仅仅是玻璃数量的逻辑交互,目的是让台子上玻璃不会溢出),就需要device了

入片台,出片台,出库入库底车,都可能有多块玻璃的

mes一直处于监听状态的,监听到就 发指令给 设备(plc) ,有时可以不管plc 就管 mes 和 设备即可,理解起来就是 mes 给 设备发指令,plc给我们发的不管,
我们还可以手动 mes 给 设备发指令

交互信息中 plc开头的 是plc发来的,mes开头的 是mes发的,都没有的 是两边都要发的

config 里面内部类 详解:
1:有所有 配置文件json 封装的内部类 (等于 mes3cs.json 里面的 所有出现的 嵌套json)
2.ConfigFile == 解析mes3cs.json的 内部类 (对标 mes3cs.json)

3.然后实例化了 一个 静态public 变量ConfigFile instance,是 ConfigFile的 即 mes3cs.Json有一个 静态变量,有一个 load静态方法去 将 json文件 转成 instance

4.里面有一个 ConFigDevice 内部类,里面的有一个属性 就是交互信息的,以及 device里面有多个device的(例如 里片库)
Ex xxxx
存储设备,磨边机器,钢化炉,云梯。。。。。

因为json中交互信息有很多类,所以 c#采用 jsonignore 去做,

Device属性详解
Config.ConfigDevice config 属性 记录了所有预先设定值 来自 instance的 device属性(ConfigDevice类型的) 一般这个构造时,就赋值了,这个就是这个device的详细信息

static public List devices = new List(); 存放所有设备信息

public List _devPrevs = new List(); /// 数组变量 - 记录了该设备的前接设备信息

public List _devNexts = new List(); /// 数组变量 - 记录了该设备的后接设备信息

也就是说 Device 除了 存了 ConfigDevice类型(这个设备的基本信息) 还有很多其他的东西 共同组成 Device

代码里面很喜欢 定义内部类,要注意,属性使用 内部类,
代码里面喜欢 定义 成员变量,在方法里面使用成员变量 传值等,不使用局部变量

plc 和 mes之间的通信 页面 按钮 btnConnectClick
PLC.start
plc.ConnectToPLC(),使用 s7 read类 去连接 plc (根据ip地址)
plc.StartOnePlc -> _thread = new Thread(PlcMain); -> consumer.CheckPLC();
启动一个 plc线程读线程 checkplc 就是 读取 plc数据的

每个plc在程序启动,从配置文件中加载了,然后分别开启了一个线程 去处理plc 和 mes的交互 具体怎么实现的 还没仔细看,反正 一个线程 一个plc 和 device的交互,
只知道现在 plc通过 S7Client 的 connection 连接了 plc设备,但是具体,是怎么 读的,不知道

读操作 (在线程中)
var res = client.ConnectTo(“192.168.1.1”, 0, 1);//连接PLC的IP地址
var res = client.ConnectTo(“192.168.1.1”, 0, 1);//连接PLC的IP地址

至于怎么循环读的,有一个 do while 不stop do 一直执行

开启每个 plcConsumer的 读线程,checkPlc() 去 读消息,然后执行 逻辑,给 plc发指令

PLC类, /// PLC与MES情报交互类
存了,config (plc的信息)
_rb 读取的 mes和plc交互的 字节
consumers (所有的消费者) 即所有的 与 plc交互的消费者,即device

代码里面使用了很多内部类,和 static 成员变量,以及 init块,将信息都先存到 成员变量中,特别是 基类,里面会创建 这个基类的实例成员对象,以及 包含所有这个基类类型的对象的 集合

静态变量static 主要是跟这个类 没啥关系的,也不改的,只读的,不具有实例的特点的,就用,例如 Config 中的 configFile instance
以及 Device里面的 所有设备 static public List devices = new List();

私有变量,与这个类相关,且 与实例有关的,例如Device里面的 Config.ConfigDevice config 这个具体的设备信息

项目中除了 data类,其他类 都不是想的那种 只存具体数据的类,例如Device类,不能觉得是 设备类,存了设备相关的属性,不是里面只有 一个 ConfigDevice属性,存了设备的具体信息,还有其他很多属性的,还有List ,还有 public List _devPrevs = new List(); (这个设备的前面的设备) public List _devNexts = new List(); (这个设备的后面的设备)

系统 与 plc交互的,采用了 plc线程,线程 plcmain() 方法,里面有个 do while 去 一直 read, 除非调用 stop 方法,才会结束循环,具体逻辑,就是用 S7Client类 连接 plc 并读数据 写数据过去

一个流程卡的玻璃的,出口方向只能有一个,model_process 的 exit_id 字段,方向为 1 2

切割版图:我们这边 mes 是 按 顺序来的,如果这块版图的玻璃 都完成了 上片 status 改变了都,那么自动切换下一个切割版图
然后匹配的时候,自动去匹配这块版图的,玻璃,那边的玻璃是没有版图的,或者说,拿来的玻璃只有大小,然后在我们 选择的 切割版图 去匹配,
所以 它的切割版图(原片),他们优化单上画了,有几种切割版图,然后如果我上这个类型的切割版图的玻璃,那么 mes这边就要匹配 这个类型的切割版图
一般,它选择的切割版图,和 我这边最开始的切割版图的 类型 都是一致的,然后这块切割版图搞完,mes 切割版图 自动+1 ,它这边选择的切割版图类型 也要和我们一样,才能顺利,不然 他们提供的玻璃尺寸,和我们 此刻切割版图的 玻璃很多不一样,就会一直报警的
总之,
1.mes切割版图 和 那边切割版图 类型 要一致(保证 顺利匹配)
2.mes切割版图完成 +1
3.如果 它那边换了切割版图 和 mes不一致,那么 切换mes版图,或者 它那边换版图
4.不要在 这块切割版图 还没有完成的情况下,去换切割版图,除非 将这块 切割版图的玻璃 破片处理,

破片,等于 破片的玻璃,erp那边会形成新的优化单,第二天处理
其次,破片的玻璃,因为 status 也不是0了,代表这块 玻璃 至少不是 未上片状态,那么 优化单也可以切换了,切割版图也可以切换了

切割版图,如果有玻璃来了,那么必须把这块版图的玻璃都完成了,或者 把 这块版图的 玻璃 都搞成破片,才能切换下一个版图,

测量分流台 可以选择不同的 优化单
现在已经没有切换优化单立即上片了,只能完成这个优化单才能 重新选择优化单上片,

优化单完成,或者 切割版图完成,是指,这个范围下的,玻璃的 status 不为 0 即可,是破片也算

流程卡出口方向:不同流程卡,如果在不同的 里片库中,那么可以都设置成 1,因为,有 2个出库小车,但是如果在同一个里片库,那么只有一个入库小车可以处理(特殊 高的 那两个里片库不管)

优化单 seq
流程卡 seq(出库顺序) exit_id(方向)

流程卡出库顺序:是当这个流程卡 全部入库了 ,才能改的,流程卡的出库顺序 ,流程卡的出库顺序默认是0,是0的情况下是不会出库的,
所以,当 某个流程卡的 所有玻璃全部入库了,这时 我们需要手动改变 流程卡的 出库顺序(1 2 3 4 …)
而且 界面上 流程卡的(没有完全出库的),出库顺序 只能是 1 2 3 4 5 6 中间不能有空的例如 1 3 5

当某个流程卡的 出库顺序为 1(全部入库了后 改为1,没有全部入库的情况下是不能改的,也就是 出库顺序一旦有值 != 0 , 一旦是全部入库 且还没有全部出库的情况),
那么 出库小车 会先出这个流程卡的玻璃,当这个流程卡的玻璃全部出完,这个流程卡的 出库顺序变成0,系统继续找出库顺序为1的流程卡,如果没有就找 出库顺序为2的,
如果还没有 不选择出库,如果有那么将 出库顺序为2的 流程卡的 seq改成1,并将其他所有流程卡的 seq -1 ,然后继续
简单来说,出库小车 一直在 遍历 流程卡 为1的玻璃出库,如果有就出库,如果没有,就看有没有2的,有 所有流程卡全部-1,然后出库为1的
如果想插队,那么可以将 某个流程卡的 seq设置成一个数,例如 1 2 3 4 现在想把 流程卡A设置成3,那么3就是流程卡A了,原来的3 4就依次递增,

一个巷到可以有几块玻璃 多块
玻璃的出库顺序 和流程卡的 出库顺序

一个方向的 流程卡是有 出库顺序的

玻璃的出库顺序(针对 一个流程卡里面的玻璃 是有出库顺序的)
mes里片库 就是来处理

  1. 一个巷道 放一个流程卡的玻璃
    2.玻璃的出库顺序(开始定好了的),所以入库时的 巷道选择,就要在 一个巷道 不能反不同流程卡的基础上,加上玻璃放进去后,不能影响玻璃的出库顺序,
    首先,一个巷道只能有一个流程卡的玻璃,所以考虑 玻璃的出库顺序时,只用考虑 一个流程卡的,因为不同流程卡的玻璃根本不可能在 一个巷道,就也不会因为流程卡的出库顺序,导致 玻璃的出库顺序受影响
    对于一个流程卡来说,首先选择 空巷道,或者 同一个流程卡的巷道,其次,同一个流程卡的巷道,还要考虑,这块玻璃在这个流程卡巷道(已经有玻璃),放进去会不会影响出库顺序,影响的话就要 选择空巷道

入库小车 上面可以有多块玻璃
入库小车入库,可以将 多块或1块 入库 一个 或 多个巷道的

流程卡出库顺序为0是不会出这个流程卡的玻璃的

流程卡出库顺序是需要 手动设置的其他不需要,设置完才能出库,所以 出库时 需要设置,不让不能出库,也就不用管出库阶段了

流程卡出口方向
流程卡 出口,在 这个流程卡的 玻璃status都没有改变前,即上片前 就必须确定,如果不确定,那么当这个流程卡的 第一块玻璃 status改变了,那么就会把这个流程卡的 exit_id 设置成1 或者 2 依据的是 看哪个出口方向暂时没有玻璃,就设置成 哪个出口方向,这时就改不了了

所以,一个流程卡里面所有的玻璃 只能有一个方向,一旦这个流程卡里面有玻璃 status 改变了,exit_id 就不能改了

出口方向 可以不用人工改,当某块玻璃上片时,会把这个玻璃的 所属流程卡的 exit_id 即出口 设置一个值,那么 这个流程卡的 所有玻璃的 出口方向就有值了,因为玻璃的出口方向 的值 就是 来自于 model_process 的 exit_id 字段
要改的话,就要在 这块玻璃 status改变前 设置,在系统上显示的,没有入库的,可能可以改,因为 status改变了,不代表已经入库了

最好的情况就是 在上片前,就把要改方向的 流程卡改了,这时,所有流程卡里面的玻璃 的 status = 0 是可以改的

出库的时候,必须一个流程卡 出完,再出下个流程卡,所以这才有流程卡的出库顺序,

入库小车 和 出库小车 一次可能有多块玻璃

入库小车 和 出库小车 可以去任何 入出片台,也可以去任何方向(2个方向的巷到) ???
入库小车 1 2, 有相互交互的地方,中间2个高的里片库就是
入库小车1 是 1-169 + 右边高的
入库小车2 是 170-338 到左边高的地方
出库小车类似

底车4个的目的是,入库出库小车12 同时工作的时候用的

plc 和 mes的交互 采用的时 tcp/ip协议,采用S7Client 连接 plc
至于 一次指令的话,相互交互几次,那不用管,一般情况下,mes的状态 有2个 0:等待 2:发指令 只有0等待状态,接受plc信息后,才能够 发指令给plc 并把mes_status 改成 发指令状态 plc就收后去完成指令,还会发一个指令给 mes mes收到后,表示 mes的指令 plc成功接到了,然后会将状态再次改成0,等待下一个 plc指令过来,并且发给plc 表示mes这边收到你的指令了

所以 一次交互 mes 从0 - 2 - 0 mes要给plc发 2次指令,至于plc给 mes发几次指令,不用管,因为 plc 给 mes发指令了,mes不一定要回的,只有 plc发 请求等待指令,mes需要给plc发执行指令,,然后plc给mes发。收到了mes你的执行指令 mes才会改回状态到 等待状态,然后发给plc我也收到了,并且我的状态变成了 等待状态,你可以再发请求执行指令给我,其他情况下,mes是不用 给 plc回指令的

然后,如果出问题了(mes这边的)
1.mes 没给 plc 发执行指令 (导致 plc无法执行,设备无法动)
2.mes 没给 plc 发 等待指令 (导致 plc 不会给 mes发 请求执行指令,导致plc 都不会请求 mes执行指令)
这两种,plc 1不给 设备执行,2.plc都不请求mes执行指令,就更不会执行
即 发请求,没得到回应,不会执行
2.请求都不发给 mes

对应的,mes这边 如果状态为 0,那就是mes 没给 plc发 执行指令,我们发给plc就好,如果发了还不行,并且 plc 也没回给mes(即,plc_status = 其他指令) 那就是 plc的问题
mes 如果状态 为 2 ,那就是 mes这边 没给 plc发 等待指令,导致plc 不会请求mes 那么就 给 plc 发 等待指令,如果发了,plc 也没给 mes发过 请求执行指令(即 plc_status = 1 没发过来),那么 也是 plc的为你

检测是不是 mes的问题:

  1. 手动发一个指令 给 plc 然后它那边能收到,就代表 不是我们 写的问题
    2.plc 给我们发 一个 写,我们能读到,那么 就代表不是我们 读的问题
    3.如果 plc给我们发写,我们读到了,如果是请求执行指令,我们没有 再次发给 plc 就是 我们中间逻辑除了问题,

总之 就是 读,写,和中间逻辑(自动读写,自动写读)出了问题

入片台 会一直保存 最后几片玻璃的状态的
磨边机,是玻璃完成磨边,玻璃记录才会上去,有进入时间 和离开时间

完成优化单,会把里面的 status = 0 的,破片处理,如果里面没有数据了,会把 这个优化单的,seq = 0,即可选择其他优化单了

代码中解决注入问题:
static成员变量,或者 init方法
然后程序启动,值就从 我们从配置文件读出来的哪些静态变量中来,
代码重要的就是 设备device 和 plc ,这些在程序启动就读了,并且 赋值给 类中的静态变量了,
有时,还有创建这个类的,一个静态实例,有些类需要这个类的实例的时候,直接定义静态方法 然后把这个类的实例赋值给它

优化单,model_optimize (seq 是否在上片, import输入时间 , fetch_method 上片方式)
获取数据时如何获取的,是通过 http请求,访问 plc的一个 NanoHTTPD接口,去获取 数据库种的数据,然后将其 存在mes的 数据库中
数据清除,重置不要点,因为会 删除数据库中的数据,将 几天的数据全部删除
只需要 获得 数据就行了,然后根据时间筛选 优化单,去上片即可

plc中的 erp模拟器开始 :就是 startHttp (NanoHTTPD) ,这样就可以接受请求了,而mes那边,就可以请求 erp数据了,
plc 连接开始,就代表 开始了 读线程,写线程 mes这边同理

mes这边的 选日期,就会去 访问 plc的 list 会将 优化单号访问给 mes 并add到,选择优化单的,下拉框中

mes 这边 所有的 data类 里面也存了 一个 static List<实体类型> 例如 model_piece中,存了一个 System.Collections.ObjectModel.ObservableCollection
集合modelPiece 所有的 玻璃数据都存在里面
device 所有的 设备都存里面

mes 打开玻璃数据页面时,会初始化 玻璃数据,优化单数据,流程卡数据(所有的,从Data实体类中取的)
选择 时间,会从 plc 拿到 所有的这个日期的 优化单号,然后填充到 选择优化单的 下拉框下,点击某个日期的优化单,

mes当前 连接小车号码 mes_connect_car
在入库出库上车上,指的是 当前小车 连接的 底车编号
在底车上,指的是 当前小车连接的 入库出库小车的编号

plc记录的小车数量 和 mes记录的小车数量的区别:
plc记录的,是此刻车上实际的 玻璃数量
mes记录的是,这一次指令,我需要给plc发那几块玻璃需要入库到哪个巷道
例如 现在 小车上检测到 3块玻璃 把
plc_num = 3 分别的mes_id是多少发给 mes
mes 只想让 mes_id = 1的 入 1巷到,发给plc的是,mes_number = 1,mes_id=1 ,mes_connect_car 想连接的底车,

glass_id 多个,,这个是 plc 和 mes两边都要发的,所以 如果你看到 glass_id的数量 和 mes_number一样,代表此刻的 交互信息记录最新是 mes发的
如果数量和 plc_number一样,代表此刻是 plc发的

清理数据:删部分数据
清除/重置:删所有数据

看这些交互信息,不管最后一次 mes是读还是写的,就是 不管最后一次是 mes给plc发数据还是 plc给mes发数据,我们只需要看 交互数据中 mes的数据(就是 最后一次mes给plc发的) plc数据(就是 plc给 mes发的)

小车 之间因为有相交的地方,就是中间两个 高的里片库,所以在分配巷道的时候,除了要考虑,玻璃的出库顺序,一个巷道只允许一个流程卡的数据,还要考虑,
小车是否会发生碰撞的,所以巷道分配的时候 需要注意比较多

系统中对 异常,错误的处理,
1.系统中的异常 必须捕捉,不过不知道,那有可能出现异常,一定要在 程序 在外层,try catch 异常,这样异常被处理,程序不至于,停止
2.异常处理后,留下 异常信息的方式有2种,1.打印logger日志,2.返回结果给 界面
3.程序没有出现异常,只是执行结果,和我们预想的不一样,代表业务逻辑有问题,如何定位?1.那一块业务逻辑中,有打印日志,去看日志(但是因为,程序不是异常,所以,只能凭经验看日志)
程序只要出现异常,不管是否 try catch 都会 有日志信息的,

异常 最外层 try catch的 地方一定要选好,不能一味的在程序的 最外层,除非是致命错 程序必须停止,但是 一般不会让程序停止的,都是 出现异常,try catch后,记录日志信息,弹框给我们提示,说去看日志文件,不会让程序停止的

所以 try catch需要 找好地方的,

什么时候需要打日志
1.try catch 处,需要打日志,或者 返回错误给界面(一般可以一起做)
2.业务逻辑处,如果怕业务逻辑 有问题,可以 在其过程中 打印一些日志消息,便于 直接看日志消息,定位问题
3.实在不行,那就只有,本地调试了,但是本地调试,需要数据,需要问题复现的

那具体什么时候需要记录日志呢?
1.try catch处,实在不知道的话,在程序启动位置 加一个最外层的 try catch (保证了 如果程序出现异常问题错误,程序能够正常执行,并且打印日志出来,这样程序有问题了,去看日志,筛选 logger.E 即可找到问题所在)

2.如果没有try catch 那么程序会退出的,这时也要去看日志,那么系统会打印对应的 错误日志,也能定位到问题所在

  1. 在你写的代码处,的关键位置去添加日志,你的代码 至少要有 一处是由日志消息的,保证,你的代码有问题,你去看日志,不管系统有没有打印日志,不管有没有try catch 打印日志,你代码这里 都有一些日志 消息 供你查询的

4.日志级别的选取,你打印日志的时候,一般就用 logger.i logger.e
logger.i 代表你对一些关键节点数据的 记录,通过查看日志,你可以知道 程序 阶段性 数据(你不知道有没有错误的数据),通过分析这些数据,和你的自己的判断,你就知道,自己程序的 逻辑有没有问题
logger.e 代码 在程序中,你明确知道,这个阶段的数据有问题,你在这里打印日志,在日志文件里面,可以明确的看到 错误消息(这里的错误,不代表程序出现了异常),而是对于 业务逻辑 出现了错误,或者数据出现了错误,

logger.i logger.e 本质都不是异常,而是 程序逻辑的记录,
logger.e 是你有意的控制,代码逻辑不符合你的要求的时候,你打印 logger.e日志,快速的知道,这块代码逻辑,数据是有问题的
logger.i 是你 怕 逻辑,数据有问题,而做的记录,

什么时候用 logger.i 什么时候 用 logger.e
就是在 关键代码处,如果你想做的 全一点,如果想要记录 自己的程序逻辑上有没有问题,那么用 logger.i记录下,也就是 logger.i 可以随便加在任何位置
其次,在你写完代码后,如果你要留后手,必须 我的代码正常执行是好的,logger.i记录,然后我把 不正常的情况也记录下来,然后用 logger.e去打印日志,避免
不正常的情况出现 我也要 记录日志,不然你的程序 只是 记录了 正常情况下xxxx , 不正常情况下(这里指的调用别人的逻辑,数据等,因为你自己的逻辑数据,如果你用logger.i记录了,那么出现问题了,你是找的到的,是我的代码 逻辑,提供的数据有问题),

1.所以现在写代码,第一 一定要 自己提供一个 最外层 try catch (包住 全部代码的 try catch) 保证 自己程序出现了 异常,能够不导致 程序停止,也能记录 looger.e 日志,最好也能给 用户一点提示 例如弹框 (这样,定位 异常错误的 是最便捷的,出现异常 直接弹框,直接去看 logger.E日志,直接知道 异常问题在哪)

2.在 程序的 关键地方 给出 logger.i , 在,去判断 是否因为 自己的逻辑 有问题 导致问题的出现,或者是别人的问题,实际就是通过 logger.i 去分析整个代码的执行流程,梳理这个流程 找到问题所在

3.在 从其他 数据库,接口,等等,只要是 获取 其他地方的 数据,调用其他地方的代码,都要有一个,如果错误的判断,如果是因为 其他原因,导致的程序有问题,打一个logger.e日志,因为从其他地方拿的 数据,调的代码,如果和自己想要的结果不一样,那么 要打印个 logger.e日志,因为其他情况你自己不能控制
还有自己写的代码 有时候 也可以打 logger.e日志,

凡是 你觉得,可能程序逻辑,不让自己的进行的时候,都可以加日志的,但是 这也要看经验了,

这样1.控制自己 和 别人代码 数据 的 异常(因为 try catch 处打印了 logger.e) logger.e 在异常处,就得打印 logger.e(xxxx , e.message) 一定要把异常位置找到

2.异常解决了,那就是逻辑了,自己的代码数据逻辑,直接logger.i 别人的代码,数据 直接 logger.e
这样 因为逻辑问题,导致的问题,先看logger.i 去梳理下 逻辑,没问题的或,那自己的 逻辑数据处理是没问题的
再看 logger.e 如果有问题,就是 其他人的代码数据有问题,如果没问题,那就没问题了,那就是 自己 logger 没有打对位置,

因为 所有地方的 逻辑都可能出现问题,但是你不可能都有地方的 logger 都涉及到,所以 分析完上面的没问题,那就证明 你没打日志的 地方逻辑出现了问题,
然后 你找到改了后,再那里 也要加一个日志,避免以后出现问题

Device详解:(这个 devDevice主要的功能就是加载数据,从数据库中读数据(对应的设备表),并且存到 device 中的 msgdata中,显示给页面,主要就是个 load方法,当然里面还存了 设备的具体信息)
1.属性 List devices/preDevices/nextDevices , ConfigDevice device , RefreshUI(委托变量,用于页面更新)
2.方法 Load(首次从 数据库中读数据) PiledUpPieces(取得玻璃列表 - 经过并完成当前设备处理,但还没进入下一个设备的玻璃)

DevMeasure:Device
1.属性:public readonly ObservableCollection _measures = new ObservableCollection(); (存放途经测量上片台的玻璃单片数据)
2.方法:重写 load方法

上面是第一层,即 Devxxx (保存设备信息,从数据库读首次数据)

上面的DevXxx 就是最基础的设备service类,就是 从数据库 读数据的

DBConsumer接口,只有一个方法,就是 reload() 就是定时去刷新数据的(从数据库定时去读数据的)
DBdev 实现 DBConsumer接口 继承 devXxx

PLcConsumer接口,和mes交互的方法,交互数据,并将数据存到 表中的,过程中也会读表(但是这个读表,不是核心刷新数据的读表,而是和plc交互之间的读表)
plcDev 实现 PLcConsumer 继承 devXxx

程序加载时,会把Device.devices 封装好,里面有一些时 plcDev 有一些时 DbDev (不是想的 全部的plcdev 和 全部的 dbdev)

这时所有的service就已经全部有了

Device (基本抽象类)-> DevMeasure (测量设备基本类) -> PlcDevMeasure (和PLC信息交互的测量设备)
-> DbDevMesure (从数据库获取更新的测量设备)

依据分类,这些service 一部分是去做 与plc交互的 一部分是去 从数据库刷新数据的
但是代码里面,好像 是根据json文件中 source =plc/db 去加载这些 plc 或 dbdev的,一般就全是 plcdev了,
这时 就不会去 开启定时任务 每个dbdevice去 刷新数据库了,而是会开启一个线程CommandMontitor (去执行指令表的sql)
当类型是 command == "Data.Reload ,就是刷新数据了,会调用 plcdev的 load方法(就是 首次刷新数据的)这个线程也是 一直执行do while的,线程停止就不执行了

宗上 service 大概率就是 plcDev
1.开启一个 mes指令执行线程 去反复执行 mes_command 中的 指令数据 (mes和plc在交互的时候,除了交互指令信息,存业务数据表,还会存 指令表),里面就有刷新页面load的 情况
2.为每个 plcDev 开启一个线程 去 do while 交互plc

组件操作:
DB.cs
PLC.cs

ctr xaml 是和页面之间的交互,然后具体是 用 PLcDev的,dev去读数据返回给前端,还是用PLcDev里面的 去和plc交互,处理逻辑 并写数据,看情况

所以,基本只有 PLcDev实例,没有device实例的,创建的时候就创建的PLCDev实例,既可以读数据,又可以交互plc,处理业务逻辑 ,并且写数据到数据库

PLC 具体的 与plc之间的纯数据交互,写在里面,就是单纯的 封装数据,然后 plc交互 类似与db包下 与数据库的操作
而 PLCDev 中,与plc的交互 等于 service ,举个例子

PLCDev PLc
service db

plcdev 中2个主要方法 从plc中读,和从plc中写
例如CheckPLC service具体实现 PLcDevMeasure 实现 checkPlc ,然后 去 获取plc中的数据(用PLC类里面的),处理业务逻辑,写数据到数据库(用DB),然后发送数据给 PLC(等于也是 DB)

总结
1.业务逻辑处理的 PLCDev (主要就是2个方法,从plc中读,写入plc),因为每个plcdev(service) 都是 2个核心功能,读,写plc
在这个过程中去,调用 db plc 类,中间做业务逻辑处理

还有一个 核心方法,就是 和 界面交互(那就是 device中的 功能也,但是 plcdev 也 是extends device的),读数据显示界面,当然界面交互,可会调用到,plcdev
读写 plc 功能的

2.数据操作的 DB PLC

3.界面交互的 ctr

ctr
service : plcdev 可以去读写数据库,可以去读写plc,中间可以去处理业务逻辑
mapper: db , plc类

唯一不同的是,service中的 读写plc ,除了界面,最主要的是,开启 所有plcdev 的 读线程,去主动读数据

mes 有2处是一直监听的
1.和 plcA交互,采用的是 do while(线程是否stop)
2.每个设备去 reload 数据库数据,采用的是 定时任务执行

关于 mes 的 mvc
1.为什么 表结构对应的实体类,不是和 web一样的,纯映射实体类,
service相关的类,不是简单 service 对应表结构的那种
这种 device ,以每个设备为 1个 service 而且每个 service之间是有关系的,所以
1.service 包含基本的通用方法,
2.service 包含了 这个设备的信息
3.这个service 包含 了 之前的设备list 和 之后的 设备list之间的信息
这就是 为什么 service里面 不是存接口方法,还有属性的原因,就是因为 service虽然不同,但是都是设备,相互之间有关系的
而且 service里面 还有 这个 设备的 具体信息(因为 是从 json中获取的,而且设备的信息是 写死的确定的,不用交互表的),

service的接口关系
Device -DBDevice – 具体实例device
-PlcDevice – 具体实例 device

(每个设备service 的功能不一样,所以定义了 dbSrevice 和 plcserivce 子接口)

所以在 servie上,不是只有接口方法的,还有 设备的信息的,以及设备之间的关系(1.设备数量有限,2.没有具体表可以,关联起来每个设备之间的关系,所以用属性即可)
可以理解为 web中 每张表对应一个sevice 然后每张表的信息是确定的,而且表的数量有限,表之间还有关系(是表和表的关系,不是表的某个字段字段的关系),
所以 web中这种,也可以 在 serviec中 加上 这个service的信息属性,以及 list 前后services 这个属性

关于data中的 类
大多都可 表结构映射
但是 modelpiece 不一样,modelpiece里面 还存了 整个玻璃的数据,以及load()方法,静态的都是,
为什么要这么处理,因为玻璃中的数据,只有在上片的时候,才会改变,所以,只要在上片的时候,加载一下 list 即可
其他地方 要用的 modelPiece中的数据的时候,直接 用List 筛选即可

static
:什么时候用,1.存不属于 单例类数据的数据 例如 modelpiece 中的 List
2. 不属于 单例类数据的,数据,而且是 一般 定好的数据,不会变的数据,例如配置文件中的 读取的数据

私有的,
这个类的 单例数据,不管是不是和 这个类中的属性有很大的联系,有时这个类的 某个对象 这个值只能有一种,例如 设备 的 具体信息,一个设备一个值,每个设备不同

项目结构:
命名空间:

  1. mes.common
    在这里插入图片描述

  2. mes.data(实体类)
    在这里插入图片描述

  3. mes.dev(service 所有service的基类 主要就是首次加载数据)
    在这里插入图片描述

  4. mes.db(主要用于数据的重新读取 的 service)
    在这里插入图片描述

  5. mes.plc(主要用于 plc 和 mes 交互逻辑的 service)
    在这里插入图片描述

  6. 页面和 ctrl
    在这里插入图片描述

7.操作数据的类 是 PLC 和DB,DBSqlite这些

在 本地环境的 json配置文件,数据库都是 sqlite的,数据库database是 mes3cs.data mes3cs.data就是一个数据库
而 生产环境的 json配置文件,数据库是 pgsql的,数据库database是 mes3cs

关于分支的:
如果需要修改 一个功能,并且还没有发到 master分支,那么就直接在这个分支上修改,等上个功能合并后,再次提交(避免 它先要提交这部分功能用,),不要切分支,因为切分支后,原来分支有问题,那么新旧分支都有问题

Config – 收集 json中的信息,

Device类里面 为什么要存 List 还有一个非常重要的原因,就是 保存每个设备的实例,一旦某些设备的方法执行完,为了保证这个设备还在,还能找到,
所以,Device里面用一个 List 将其所有设备的实例 保存起来,

误区:1.ConfigDevice[] 啥功能也没有的,仅仅是解析json文件中 关于设备的一些属性信息的,而我们真正指的设备,是 Device ,带有具体功能的设备
且 Config里面 ConfigFile instance 也没有意义,就是 提供配置信息的

误区:2.关于里片库这个设备
首先,设备:我们不要想配置文件中的设备,配置文件,就是 提供 配置文件信息的这么一个类实例
然后设备 是来解决 具体功能的 类,只是设备中的一些信息,具体就是,Device.ConfigDevice 来保存这个设备的 基本信息,且Device里面有个 static的,Device[]
,来保存 所有 设备的实例,避免设备实例回收后,找不到设备,所以在程序启动,读取配置文件信息后,会根据配置文件,创建所有接口Device的 实例,基本信息,就从
配置文件instance里面取即可。这样实例化完,就知道Device.List 里面生成了 哪些具体的 device 是plcDev 还是 DbDev…,

误区:3.关于里片库这个设备
里片库这个类里面,包含了 小车底车这样的设备类,因为 里片库这个设备 和 小车 底车 又包含关系的,即里片库 包含小车 底车
所以 dev里片库这个设备 在创建的时候,就从 配置文件中 里片库这个里面 把里篇库和小车底车的信息(都是在 json中 storage里面 storage{ 小车{} 底车{} }),
都给了 devStorage 的 构造方法,然后去 实例化 devStorage 且把 里面的 小车 底车 属性 而给实例话了

简单来说,里片库,小车,底车都是设备,但是小车和底车 是 依附在 里片库里面了,单独使用没有意义,
或者说,里片库 小车 底车 是分开的,分别根据配置文件里面的信息创建后,小车 和 底车 要 赋值给 具体的里片库 去填充 它里面的 小车 底车属性,且小车底车的 json信息
都是在 storage里面的e

误区:4.dev 和 dbdev 和 plcdev 的关系
dev 就包含了所以 设备里面需要的属性,设备和设备之间的关系,等 plcdev 和 dbdev 只是 设备的用途不同而已,而设备的基本信息,设备与设备之间的包含关系,在dev这个层面就已经确定了,plc 或 db 是在确定了 dev后,去做不同的具体的功能而已,
所以 dev里面的 属性 和 方法,才是 每个设备的 最基石的东西,plc和dev 只是填充了 一些不同的具体方法而已,dev才是确定了,设备的基本属性,设备的包含关系的 基础

过程 window 初始化
:1.初始化 DB.init() 创建数据库连接
2.create devices Device.devices.add()
3.create device interlink 创建device关系
4.ModelPiece.Load();
ModelProcess.Load();
ModelOptimize.Load();
三张最主要的表,读取

5.dev.Load(); 遍历for device ,首次加载每个设备的,表的数据

6.CommandMonitor 的 初始化(PLC) ,开启一个线程,去循环 执行 mes_command表中的命令,如果 type = Data.Reload 那么就是加载 dev的数据
或者 定时任务执行 DBDev的 reload方法

vs中项目中的文件 需要用添加的 方式入项目,否则会无法识别的,
在这里插入图片描述

mes3cs.csproj :这个文件 是管理 C#的,资源的,有新的资源添加,此文件也会更新,也需要提交git

动态添加 页面标签的时候,如果其他方法想要获取 页面内 标签的信息,不能直接获得,需要经过 if 判断后,在拿到标签,因为你是动态添加的标签,本质上 编译器是 默认 页面内没有这个标签的,编译器 只知道 写死在页面 中的 内容

model_piece
model_process
model_optimize
是三张元数据表,里面的数据来自与 erp

关于
mes从 erp获取的数据
plc 发过来的数据
1.长边 短边,是测量的长边短边
在这里插入图片描述
不是误差,误差要自己去看的
配置文件里面,有误差 (用 long_error/比例 即可)
左边的是,erp 中 玻璃原片列表,是 rlong rshort(显示的 是 原片的大小)
这里说一句,原片大小只在 测量台的时候用,因为 只要测量成功(原片大小 和 测量的数据 比对成功,找到一片具体的 玻璃对应上,那么 后面 都是要用这块玻璃的 dlong 和 dshort 即 长边 和 短边,磨边后的长边和短边)

右上,是正在测量的玻璃,长边 和 短边 是 测量的实际长边和短边,和 左边的 测量前长边短边匹配,匹配成功后,这块玻璃在之后的流程,都是用的 测量后的长边和短边,

右下,测量的玻璃,msgMeasea 这张表里面的 ,mes_id 和 实际测量的长边和短边

为什么 erp 提供的 数据 要提供 磨边后长度(即 理想长度),测量前长度,和误差,因为客户要的是 最后的长度,那我们就得提供 一块玻璃 是 最后的长度的(在误差范围内的),例如 长1000mm 误差2mm 那么只要,用这1000去匹配,误差在2mm 的 实际测量长度即可,但是 因为要磨边的,要提供 磨边长度的,所以就不能用1000mm 去和 2mm去匹配,而要用 1000+2mm 去和 实际测量长度 匹配,所以 mes表里面 提供了
磨边后长度, 磨边长度,原片长度 这三个数值,原片 长度 和实际测量 长度 去 匹配,匹配到了,那这块玻璃,mes_id 被 其他表记录下来了,后面用的长度,就用 磨边后长度 代表 这块玻璃即可了

关于什么时候 用 tabcontroll 什么时候 用C#代码写 页面
1.如果页面的内容是 死的,就用 页面,可能会有这种场景,用一个页面,都是有几种情况,这时用 一个 tab
即可
2.如果页面的内容 怎样都不是定下来的,就用C#代码写

例如:单片对话框,的内容 是根据 这片玻璃 目前的状态决定的,要带着 mes_id 去不同的 表中 找数据,那么就用 c#动态拼接

例如:参数设置页面,里面的内容 每个设备不同,但是单个设备的内容是 死的,所以就用 页面 + tab即可,一个页面 处理不同情况

modelPiece表中,status字段,代表这块玻璃的状态,一般就是 用 设备的 position 即计算的,例如里片库是45,

流程卡方向的确定后,是通过判断,这个流程卡的 玻璃的 status,来判断 是否 已经确定方向了

在这里插入图片描述

不是每張 dev 表 都有對應的,data實體類的,有些是沒有的,例如 plc_exit 存了 mes_id等信息,但是dev中,就是用的 List<ModelPiece 來存的 現在 在 出片台上的數據

每個 dev裏面 都有 一個屬性 來存 現在 這個設備的 數據

所以 dev 去 和plc交互/db交互,讀寫數據后,還要吧數據 封裝到 現在 這個設備的 現有數據 一個 屬性裏面,下次 拿這個設備的 數據 就不用去 數據庫裏面拿了

modelpiece dev設備類 等 都有 存所有的數據的屬性

modelPiece 的status 代表 此时玻璃的 状态,如果 status = -1 代表 破片,当 status = -1 ,是不允许,继续其他流程的(因为 plc 和 mes 交互的时候 中的 mes_id 去表中查的 status = -1的话,代表破片了,是不会把这个 mes_id 传过去的)
流程卡的出库顺序 seq字段

1.pgsql mes.data
2.任务:各个设备的参数管理页面
3.vs工具各种配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值